# Vaultfire V3 deterministic partner sandbox

> **MOCK / SOURCE-REVIEW ONLY — CANNOT BROADCAST.**
>
> This is not a blockchain emulator, deployment, testnet, wallet, payment
> facilitator, or production API. It never uses RPC, a wallet, network funds,
> credentials, secrets, or personal data. Values named `assets`, `funding`,
> `credits`, and `amount` are integer fixture units with no monetary value.

This isolated, post-tag sandbox demonstrates the intended V3 lifecycle with a
deterministic local state machine. It does not modify or stand in for frozen
contracts, public machine-discovery documents, generated schemas, OpenAPI
documents, route handlers, or the V3 website.

## Requirements and clean start

The verified environment is **Node 20.20.1**, **npm 10.8.2**, and Linux x86_64.
There are no runtime or development dependencies.

```bash
tar -xzf vaultfire-v3-partner-sandbox.tar.gz
cd vaultfire-v3-partner-sandbox
npm ci --offline --ignore-scripts --no-audit --no-fund
npm run build
npm test
npm run reset
npm start
```

The archive has one top-level `vaultfire-v3-partner-sandbox` directory and a
zero-dependency lockfile, so this install/test flow does not contact a package
registry.

The server binds only to `127.0.0.1:4317`. `PORT` may select another local
port; the host is intentionally not configurable. State is atomically persisted
under ignored `.local/state.json`, so receipts survive a restart. `npm run
reset` restores the checked-in deterministic fixture.

## Lifecycle operations

All mutations use `POST /v3/operations` with exactly:

```json
{"operationId":"op-001","type":"partnership.create","payload":{}}
```

`operationId` is consumed after success and cannot be reused. Unknown fields,
free-form actor values, invalid amounts, overfunding, invalid transitions, and
late operations fail closed. Supported operation types are:

- `partnership.create`, `partnership.approve`, `partnership.fund`,
  `partnership.cancel`, `partnership.expire`, `partnership.forceExit`
- `accountability.create`, `accountability.fund`,
  `accountability.activate`, `accountability.attest`,
  `accountability.expire`, `accountability.forceExit`
- `dispute.open`, `dispute.resolve` (`rejected` or `upheld`)
- `protocol.pause`, `protocol.unpause`, `credits.withdraw`, `clock.advance`

The tests cover bilateral approval, partial and full funding, activation,
attestation thresholds, both dispute outcomes, deadlines, expiry,
pre-activation cancellation, pause-safe pull-credit withdrawal, force exit,
solvency, durable receipts, mock x402, and replay rejection.

[`examples/sandbox-client.mjs`](./examples/sandbox-client.mjs) is a minimal
Node client that checks the no-wallet/no-network safety flags before creating a
local partnership. Run it only after `npm start`, and reset first if reusing its
fixed operation ID:

```bash
npm run reset
node examples/sandbox-client.mjs
```

## Curl walkthrough

Reset and inspect:

```bash
curl -sS -X POST http://127.0.0.1:4317/reset
curl -sS http://127.0.0.1:4317/v3/state
curl -sS http://127.0.0.1:4317/v3/solvency
```

Create a partnership, approve bilaterally, fund partially, then fully activate:

```bash
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-001","type":"partnership.create","payload":{"bondId":"partner-demo","partyAStake":60,"partyBStake":40,"proposalSeconds":60,"activeSeconds":300}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-002","type":"partnership.approve","payload":{"bondId":"partner-demo","actor":"partyA"}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-003","type":"partnership.approve","payload":{"bondId":"partner-demo","actor":"partyB"}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-004","type":"partnership.fund","payload":{"bondId":"partner-demo","actor":"partyA","amount":20}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-005","type":"partnership.fund","payload":{"bondId":"partner-demo","actor":"partyA","amount":40}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations \
  -H 'content-type: application/json' \
  -d '{"operationId":"p-006","type":"partnership.fund","payload":{"bondId":"partner-demo","actor":"partyB","amount":40}}'
```

Create and activate an accountability bond, submit two threshold attestations,
then open and uphold a bounded dispute:

```bash
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-001","type":"accountability.create","payload":{"bondId":"accountability-demo","stake":100,"attestationThreshold":2,"activeSeconds":300}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-002","type":"accountability.fund","payload":{"bondId":"accountability-demo","amount":100}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-003","type":"accountability.activate","payload":{"bondId":"accountability-demo"}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-004","type":"accountability.attest","payload":{"bondId":"accountability-demo","attester":"attester-1","evidenceId":"evidence-1"}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-005","type":"accountability.attest","payload":{"bondId":"accountability-demo","attester":"attester-2","evidenceId":"evidence-2"}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-006","type":"dispute.open","payload":{"disputeId":"dispute-1","bondId":"accountability-demo","responseSeconds":60,"slashAmount":25}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"a-007","type":"dispute.resolve","payload":{"disputeId":"dispute-1","result":"upheld"}}'
```

Pause-safe withdrawal and receipt retrieval:

```bash
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"safe-001","type":"protocol.pause","payload":{}}'
curl -sS -X POST http://127.0.0.1:4317/v3/operations -H 'content-type: application/json' \
  -d '{"operationId":"safe-002","type":"credits.withdraw","payload":{"actor":"counterparty","amount":25}}'
curl -sS http://127.0.0.1:4317/v3/receipts/receipt-0001
```

## Mock V3 x402 challenge

The 402 is synthetic. **Do not send funds.** The displayed proof is a local
fixture string, not a signature or payment authorization.

```bash
curl -i -X POST http://127.0.0.1:4317/v3/x402/challenges \
  -H 'content-type: application/json' \
  -d '{"operationId":"x-001","resource":"partnership:create"}'
curl -sS -X POST http://127.0.0.1:4317/v3/x402/fulfill \
  -H 'content-type: application/json' \
  -d '{"operationId":"x-002","challengeId":"challenge-0001","proof":"MOCK_ACCEPT:challenge-0001"}'
```

Reusing either operation ID returns `DUPLICATE_OPERATION`; presenting the same
proof under a new operation ID returns `REPLAYED_PROOF`. Challenge and
fulfillment receipts are stored in the same hash-linked local receipt journal.

## Safety boundary

- The server has no outbound network code and accepts no URLs, addresses,
  private keys, tokens, signatures, names, emails, or arbitrary metadata.
- Only fixed fixture actors are accepted.
- Every response repeats `MOCK SOURCE-REVIEW ONLY. CANNOT BROADCAST.`
- HTTP 402 is an educational protocol shape only; the amount is zero `MOCK`.
- Simulated conservation is checked after every successful operation:
  `assets >= locked principal + pull credits`.
- This state machine is deliberately not imported by release discovery,
  production handlers, schemas, or the website.

See [SDK_ONBOARDING.md](./SDK_ONBOARDING.md) for public SDK review guidance and
the V2/V3 separation.
