# PatchMyBox post-repair escrow prototype

**Unaudited Solidity prototype. Not deployed. The website demonstrates simulated payments only.**

The owner places `patchmybox.txt` on the host, with `/etc/patchmybox.txt` as a proposed convention; public publication is optional. It records a conditional offer of retrospective owner-level forgiveness and a promised reward for a qualifying repair. It grants no advance permission to enter or obtain root. Discovery after access does not itself satisfy the conditions, and a later patch does not erase earlier theft or damage. Root is neither a prerequisite nor an authorization. Creating the file requires no wallet or deposit.

The reward is a promise under the stated conditions, not a discretionary donation. The owner funds this contract after the repair qualifies under the recorded review process. If the owner then fails to fund by the promised deadline, that is a failure to honor the payment promise; this contract cannot collect an unfunded obligation. No prior case negotiation or escrow transaction is required by the offer, but neither the file nor this contract guarantees legal enforceability, immunity, or payment.

The contract is a deliberately narrow implementation of the payment boundary in [the mediator interface](https://github.com/GroupLang/cyber-salvage/blob/main/docs/mediator-interface.md). It does not implement the whole service, establish system ownership, authorize access, adjudicate forgiveness or legal liability, prove a patch succeeded, or prove non-exfiltration. Hashes link to privately held evidence; they do not prove its truth.

## What is implemented

One native-currency award per payer/case ID, with a fixed recipient, amount, mediator, independent appeal reviewer, agreement commitment, repair-evidence commitment and time windows. All four role addresses must differ. There is no administrator, upgrade mechanism, key reassignment, arbitrary beneficiary selection, ERC-20 support or partial payment.

This version uses authenticated on-chain calls and on-chain state. It **does not implement the interface document's future signed settlement receipts**. There are no off-chain spendable vouchers to race against a challenge. One funding record corresponds to one award; a full case with multiple installments would require a later design or separately identified awards, with duplicate-payment review outside this prototype.

| Operation | Who can call | Effect |
|---|---|---|
| `fundAfterRepair(caseId, terms)` with value | Defender/payer | Deposit the promised reward after repair review and fix the on-chain settlement terms. |
| `proposeRelease(escrowId, decisionHash)` | Fixed mediator | Record a decision and start the challenge clock. |
| `challenge(escrowId, challengeHash)` | Payer, recipient or mediator | Place the funds in an enforceable hold during the open challenge window. |
| `resolve(escrowId, payRecipient, resolutionHash)` | Fixed appeal reviewer | End a held dispute with the full award to its fixed recipient or a full refund to its original payer. |
| `release(escrowId)` | Anyone | After an unchallenged window, credit the fixed recipient. |
| `refundExpired(escrowId)` | Anyone | Credit the original payer after mediator silence or appeal-reviewer silence. |
| `withdrawFor(beneficiary)` | Anyone | Deliver that beneficiary's credit to that same address. |
| `withdrawTo(destination)` | Credited beneficiary only | Withdraw its own credit to a chosen working destination. |

Successful settlement creates a withdrawal credit; it does not itself send money. A rejecting recipient cannot block settlement of its own or other cases. Credit is debited before external calls, withdrawals reject reentry, and failed delivery restores credit. Only the beneficiary can redirect its own withdrawal. The case becomes terminal after a credit, preventing repeated settlement.

## Timers and refund rules

Each window is selected at funding and must be between 1 second and 30 days. These are prototype bounds, **not recommended operational deadlines**. Choose adequate real review periods before any future pilot. The block timestamp governs deadlines; service notifications do not change executable chain state.

1. Funding starts the mediator approval window. The mediator must propose a release strictly before its deadline. At or after that deadline, a still-unapproved case can only refund the payer.
2. A mediator proposal starts the full challenge window. The mediator must first make the exact decision and required evidence available to entitled participants; the contract cannot verify this off-chain fact.
3. A challenge must execute strictly before the challenge deadline. At that deadline or later, an unchallenged proposal can release to the recipient. Transaction inclusion time matters; merely sending a challenge before a deadline is insufficient.
4. A challenge starts a fixed resolution window and blocks normal release. The immutable appeal reviewer can choose payment or refund strictly before that deadline. At or after it, anyone can trigger the pre-agreed payer refund.
5. The appeal result is final within this narrow prototype. There is no second challenge window, revised proposal, late appeal or administrative extension. An unchallenged award never becomes a payer refund merely because the recipient is slow to withdraw.

The timeout-to-payer rule avoids dependence on an absent mediator/reviewer for fund recovery, but it favors the payer when a dispute remains unresolved. A payer could challenge and benefit from reviewer silence. This is a disclosed tradeoff, not a claim of incentive compatibility. The reviewer is trusted to resolve disputed cases; it cannot redirect an award to itself. Once funded, the payer cannot unilaterally reclaim an eligible uncontested award. A refund caused by a timeout is only a disposition of these deposited funds: it does not establish patcher misconduct, revoke a qualifying forgiveness finding, or extinguish any off-chain reward promise. Those questions remain outside this contract.

## Application integration

The funding signature is:

```solidity
fundAfterRepair(bytes32 caseId, Terms calldata terms) external payable
```

`Terms` contains, in order:

```text
address recipient
address mediator
address appealReviewer
bytes32 agreementHash
bytes32 repairEvidenceHash
uint64 approvalWindow
uint64 challengeWindow
uint64 resolutionWindow
```

`escrowIdFor(payer, caseId)` returns `keccak256(abi.encode(payer, caseId))`. Namespacing prevents another account from reserving the payer's ID. Reusing the same payer/case ID is rejected even after settlement. IDs identify records, not a global proof that the same repair has not been claimed elsewhere.

`getCase(escrowId)` returns the payer, amount, terms, state, deadlines and decision/challenge/resolution hashes. The state values are `0=None`, `1=Funded`, `2=ReleaseProposed`, `3=Challenged`, `4=Released`, `5=Refunded`. A `Released` or `Refunded` case means credited, not necessarily withdrawn. Read `withdrawable(address)` and withdrawal events for delivery. Credits aggregate by beneficiary across cases; the UI should distinguish case settlement from a combined withdrawal.

Use random case IDs and salted commitments where metadata could be sensitive. All on-chain values, addresses, amounts and timing are public. Never put target hostnames, vulnerabilities, credentials or raw case evidence in these fields. The application separately verifies operator authority, the exact conditional-offer version, evidence availability and recipient details. The agreement commitment should bind the original offer and its reward rule, the review result, and the resulting settlement terms. It must not silently replace the reward promise with new terms after the repair. This does not require bespoke negotiation or a pre-repair approval transaction. The contract only knows its payer address; it cannot verify that the deposited amount matches the promised reward.

No function allows editing the funded terms, redirecting a beneficiary, replacing a mediator, or releasing through an LLM command. An LLM may assist with the private record; it is not a contract authority. A changed decision enters the challenge/appeal path. The broader multi-signature, portability and key-recovery roadmap is not implemented here.

## Conditions and review outside the contract

Souk must keep three determinations separate: whether the repair achieved its specified result; whether the entire relevant episode met the conduct conditions; and whether the owner funded and the recipient received the promised reward. A chain event is not evidence of the first two.

- **Qualifying conduct:** a successful, scoped repair plus only the necessary bounded diagnosis, verification, rollback if needed, reporting and handover specified by the offer. Record the initial access and conduct before discovery too. Data theft, unrelated access, persistence/backdoors, sabotage, extortion, and manufacturing a defect to claim a reward are disqualifying; they cannot be cured merely by finishing a patch. The policy must explain how accidental damage, unsuccessful repairs and safe aborts are treated rather than letting a reviewer improvise after the work.
- **Review outcomes:** qualifying, disqualified with reasons, or unresolved pending specified evidence/review. Missing evidence is not proof of either innocence or misconduct. An unresolved record does not automatically activate forgiveness or payment. State the evidence threshold, decision deadline, appeal path and payment deadline in the offer; the contract's deposit-time timers do not implement this earlier process.
- **Authentic terms:** a root-controlled file can be forged, edited or backdated. Preserve its exact version and bytes, and authenticate owner intent against an independent anchor. An off-host signature or privately registered commitment can help without publishing the host's participation, but a key taken only from the same compromised host is not an independent trust anchor. A hash alone does not prove authorship, prior existence, or truth.
- **Stable offer:** record when the offer applied and how future withdrawal works. Do not retroactively change the reward rule, conduct standard or evidence threshold for an episode governed by an earlier offer. A stale or conflicting local/public copy needs review; the prototype does not implement signed policies, trusted timestamps or a revocation registry.
- **Bounded evidence:** logs and a TEE session can support claims only for their trusted observation window and measured execution. Evidence collected after root access cannot establish that nothing was exfiltrated beforehand, and a clean repair trace does not prove the whole episode was clean.
- **Separate promises:** qualification can trigger the owner's forgiveness and payment commitments under the offer. Recording a qualifying finding, recording the owner's acknowledgement, funding escrow and confirming receipt are distinct events. Failure to deposit does not by itself turn a qualifying repair into misconduct. Legal effect depends on the applicable law and the owner's actual authority; a private owner cannot promise a prosecutor's or another rights holder's decision.

The mechanism intentionally has an unsecured interval between the work and funding. Reputation, authenticated offers and independent review may improve credibility, but they are not collateral. A bond, guarantor, insurance or pre-funded pool would be a later design with different capital assumptions. Likewise, the prospect of a reward can increase attempts to gain access even though the offer grants no advance permission; local-only discovery reduces public targeting signals but does not eliminate that incentive. Preventive repairs remain eligible without requiring an intrusion or root access.

## Compile and test locally

Node.js 20+ and pnpm are sufficient. Compiler and test-library versions are pinned in `package.json` and `pnpm-lock.yaml`.

```sh
cd contracts
pnpm install --frozen-lockfile --ignore-scripts
pnpm run compile
pnpm test
```

The compiler uses Solidity 0.8.30 with the Shanghai EVM target. It writes ignored ABI/bytecode artifacts to `build/PatchMyBoxEscrow.json`; there is no deployment script. Tests execute signed transactions in an isolated EthereumJS VM, using fixed synthetic accounts and timestamps. They do not connect to an RPC endpoint or use wallets or real funds.

The suite checks authorization, duplicate funding, caller-scoped IDs, exact deadline boundaries, challenge holds, both appeal outcomes, silent-party refunds, fixed beneficiaries, failed withdrawal recovery, cross-case accounting and a reentrant recipient. These checks are not an audit or a formal proof.

The implementation follows Solidity's documented [withdrawal pattern](https://docs.soliditylang.org/en/v0.8.30/common-patterns.html#withdrawal-from-contracts) and [checks-effects-interactions guidance](https://docs.soliditylang.org/en/v0.8.30/security-considerations.html#reentrancy). No license grant has been chosen; source files use `SPDX-License-Identifier: UNLICENSED` consistently with the private repository.

## Known limits before any live-money work

- No production deployment, independent security audit, formal verification, key recovery, multi-signature governance or operational monitoring has been done.
- Distinct addresses do not prove independent people. The contract cannot detect role collusion or an operator impersonating a system owner.
- A lost beneficiary key, or a contract beneficiary unable to invoke `withdrawTo`, can still strand its own credit. No administrator can take that credit.
- Ordinary unsolicited transfers revert, but Ethereum can force native currency into a contract. Such unattributed currency is outside award accounting and has no sweep function. `totalLocked + totalWithdrawable` tracks funded obligations, not every possible unit of forced balance.
- On-chain settlement makes payment metadata public. The prototype has no confidentiality layer, and its commitments do not certify that a private record remains available.
- A template alone cannot establish legal authority or bind third parties. An independently authenticated owner offer records a conditional commitment concerning that owner's own claims and reward; it does not grant advance access permission or guarantee immunity. A repair claim or escrow does not establish the absence of theft. Preventive repair remains eligible; causing compromise is never a contract prerequisite.
