Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/COMPOSITION_MANIFEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ All ports conform to frozen definitions in `@oneshot/contracts`:

### 2. `production` Profile (Targeted for Gate P4 Convergence)

- **Settlement**: Arc Settlement Adapter (`@oneshot/adapter-arc`, owned by Coder B)
- **Authorization**: Privy Authorization Adapter (`@oneshot/adapter-privy`, owned by Coder B)
- **Settlement**: `ArcSettlementAdapter` (`@oneshot/privy-adapter`, owned by Coder B)
- **Authorization**: `PrivyAuthorizationAdapter` (`@oneshot/privy-adapter`, owned by Coder B)
- **Reconciliation**: Subgraph MCP Recovery Engine (`@oneshot/reconciliation-subgraph`, owned by Coder C)

## Environment Configuration
Expand Down
21 changes: 15 additions & 6 deletions docs/GATE_P4_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ At Gate P4, checked simulators are replaced with real reviewed package versions,
| Domain Models | `@oneshot/domain@0.1.0` | Lane A | Pinned |
| PostgreSQL Storage | `@oneshot/storage-postgres@0.1.0` | Lane A | Pinned (Schema Digest: `5d5888894ff0f4f44049579f1c8ffca2a24e0b61c3af65aabdbcd78f06020d65`) |
| Settlement Worker | `@oneshot/worker@0.1.0` | Lane A | Composed |
| Arc Settlement Adapter | `@oneshot/adapter-arc` | Lane B | Simulated via `SimulatorSettlementPort` |
| Privy Authorization Adapter | `@oneshot/adapter-privy` | Lane B | Simulated via `SimulatorAuthorizationPort` |
| Arc Settlement Adapter | `@oneshot/privy-adapter` (`ArcSettlementAdapter`) | Lane B | Simulated via `SimulatorSettlementPort` |
| Privy Authorization Adapter | `@oneshot/privy-adapter` (`PrivyAuthorizationAdapter`) | Lane B | Simulated via `SimulatorAuthorizationPort` |
| Subgraph MCP Recovery | `@oneshot/reconciliation` | Lane C | Simulated via `c01-simulator-v1` scenarios |

Both lane-B adapters ship from `@oneshot/privy-adapter` rather than from
separate packages: settlement is a Privy wallet action carrying an Arc
transfer, so splitting them would put half of one call path in each package.
`@oneshot/arc-adapter` holds the Arc profiles, money, receipt verification, and
readiness probing they build on. See
`docs/settlement/GATE_P4_LANE_B_READINESS.md` for the injection recipe.

## Replacement Instructions for Gate P4

1. **Replace Settlement Port**:
Expand All @@ -45,10 +52,12 @@ At Gate P4, checked simulators are replaced with real reviewed package versions,

## Verification Commands

Before P4, the Arc, Privy, and settlement testkit packages keep their reviewed npm
toolchains and are checked by the dedicated `settlement-packages` CI job. P4 may
consolidate them into the root pnpm workspace only after their package contracts and
tool versions are reconciled.
The Arc, Privy, and settlement testkit packages are full members of the root
pnpm workspace and are covered by the root `lint`, `typecheck`, `build`, and
`vitest` runs. The separate `settlement-packages` CI job and their package-local
npm toolchains were removed when they were consolidated, ahead of P4 rather than
during it, because their npm lockfiles broke `pnpm install --frozen-lockfile` on
`develop`.

Run the full verification matrix to validate integrated convergence:

Expand Down
105 changes: 105 additions & 0 deletions docs/settlement/GATE_P4_LANE_B_READINESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Gate P4 readiness, lane B

What lane B provides for Gate P4, what Coder A must change to use it, and the
one naming disagreement that needs settling before composition.

## 1. What to inject

`docs/GATE_P4_CHECKLIST.md` step 1 and 2 replace the simulator ports in
`apps/worker/src/composition.ts`. The replacements are:

| Checklist name | Actual export | Package |
| --------------------------- | --------------------------- | ------------------------ |
| `ArcSettlementAdapter` | `ArcSettlementAdapter` | `@oneshot/privy-adapter` |
| `PrivyAuthorizationAdapter` | `PrivyAuthorizationAdapter` | `@oneshot/privy-adapter` |

Both declare `contractVersion = '1.0.0'`, and the settlement adapter declares
`network = 'eip155:5042002'`, matching what `composeWorker` verifies.

```ts
import { ArcSettlementAdapter, PrivyAuthorizationAdapter } from '@oneshot/privy-adapter';
import { loadSettlementConfig } from '@oneshot/arc-adapter';

const config = loadSettlementConfig(process.env);

const settlementPort = new ArcSettlementAdapter(config, walletProvider);
const authorizationPort = new PrivyAuthorizationAdapter(config, reviewedBaseline, observeIdentity);
```

## 2. Naming disagreement to settle

The checklist reserves package slots `@oneshot/adapter-arc` and
`@oneshot/adapter-privy`. Lane B shipped `@oneshot/arc-adapter` and
`@oneshot/privy-adapter`, and those names are already merged, imported, and
referenced in `pnpm-workspace.yaml`, the root `tsconfig.json`, and the fixture
and documentation set.

Renaming is possible but touches every consumer. The names above are what
exists today. This needs an explicit decision rather than being discovered
during composition.

Both adapters live in `@oneshot/privy-adapter` rather than being split across
two packages, because settlement is a Privy wallet action that carries an Arc
transfer: splitting them would put half of one call path in each package.

## 3. Conformance is checked at compile time

`packages/privy-adapter/src/p4-conformance.ts` mirrors the worker's
`AuthorizationPort` and `SettlementPort` interfaces and statically asserts both
adapters satisfy them, including the `contractVersion` and `network` fields
that `composeWorker` reads.

It mirrors rather than imports, because importing `apps/worker` would break the
lane rule against depending on another owner's implementation package. The
mirror is verified to fail: renaming `submit` makes `tsc` report

```text
error TS2344: Type 'ArcSettlementAdapter' does not satisfy the constraint
'WorkerInjectableSettlementPort'.
```

If Coder A changes those interfaces, this file fails the build and the mismatch
surfaces here instead of during composition.

## 4. What A must supply

The adapters take their provider as an injected interface, so nothing in lane B
opens a socket or reads a credential.

`WalletProvider` needs two methods:

- `sendTransaction({ chainId, to, value, data, idempotencyKey, referenceId })`
signs and broadcasts, and **must pass `idempotencyKey` through to Privy** so a
duplicate collapses provider-side as well as in OneShot state.
- `getReceipt(transactionHash)` returns the receipt or `null`.

`PrivyAuthorizationAdapter` also needs a reviewed `SettlementBaseline` and an
`observeIdentity()` callback returning the currently deployed identity, so
policy drift is detected before authorization rather than during a payment.

## 5. Behaviour worth knowing before composition

- **Drift reports `UNAVAILABLE`, not `DENIED`.** A drifted policy makes every
answer untrustworthy rather than making this particular intent unauthorized.
Treat it as retryable-after-fix, not as a decision about the intent.
- **`POSSIBLY_SUBMITTED` is the default for doubt.** Only a proven pre-broadcast
failure or an on-chain revert returns `DEFINITELY_NOT_SUBMITTED`. Everything
else, including an unreadable receipt and a receipt that does not prove our
Transfer, is possibly submitted.
- **A successful receipt is not confirmation.** `CONFIRMED` requires exactly one
matching Transfer from the configured token to the expected recipient for the
exact amount.
- **Native value is always zero**, asserted by test.

## 6. Still not proven

Per `.agents/skills/sponsor-qualification/SKILL.md`, no sponsor claim may rest
on fixtures. These remain unverified against reality and are listed in
`COMPATIBILITY_MANIFEST.liveGapsForGateP4`:

- No Privy tenant has executed a policy denial or an allowed settlement.
- Arc receipt and Transfer log shapes are modelled from documentation.
- Privy wallet and policy identifier formats are shape-guessed.

`docs/settlement/LIVE_EVIDENCE.md` still reads `LIVE_NOT_RUN`. Privy and Arc
claims stay `NOT VERIFIED` until it does not.
3 changes: 2 additions & 1 deletion packages/privy-adapter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"@oneshot/arc-adapter": "workspace:*",
"viem": "2.56.3"
"viem": "2.56.3",
"@oneshot/contracts": "workspace:*"
}
}
Loading
Loading