# Purchase workflow audit — Issue 11

## Baseline and limits

Local HEADs verified against live origin/main: coordination `b6f20cbb094f3815ced9854729f56190d9c8ea31`, DApp `ba03534197f89052570108b6a49cd6600f7f98a2`, Protocol `01da184efb25d209fe7d324f610d12d5f3812bd7`. Root and Protocol clean at inspection; DApp unrelated untracked files preserved. Source inspection only: no tests, deployments, or network writes performed.

Issues https://github.com/jdelos/ceba-matt/issues/11, https://github.com/jdelos/vsc-protocol/issues/65, and https://github.com/jdelos/ceba-dapp-clean/issues/27 remain open with no comments at inspection. No issue changed.

## Landed work versus remaining evidence

Protocol compatibility producer/validator already exists in `workspace/repos/vsc-protocol/product/protocol/scripts/local-stack-compatibility.ts`; artifact synchronization exists in `workspace/repos/vsc-protocol/.github/workflows/sync-ceba-artifacts.yml`. Do not rebuild this infrastructure. Existing contribution ABI accepts a caller-supplied bytes32 contribution ID, so backend issuance does not itself require a Solidity change.

Issue 65 still needs executed protocol/artifact checks and current deployment compatibility evidence linked to purchase assumptions. Workflow tests belong to DApp work, not a prerequisite requiring the finished workflow before DApp starts. No protocol ABI change justified by inspection.

`workspace/repos/ceba-dapp-clean/scripts/vsc-protocol-local-check.ts:112-149` can send `setRealDepositsEnabled(...)`; do not treat every validation command as read-only. Shared-chain lifecycle/state changes require explicit scope and safe isolation.

## DApp findings

- `workspace/repos/ceba-dapp-clean/src/components/react/vsc-protocol-join.tsx:210-227` uses client preview; backend quote identity/expiry required by spec is missing. Current contribution IDs originate client-side at lines 142-144.
- `workspace/repos/ceba-dapp-clean/src/lib/vscContributionIntake.ts:333-338` records submission request before wallet invocation. UI cancellation cannot prove no broadcast. Existing intake remains transaction-safety boundary.
- `workspace/repos/ceba-dapp-clean/src/components/react/vsc-protocol-join.tsx:337-382` restores transaction journal. No XState snapshot persistence must not mean removing this safety evidence.
- `workspace/repos/ceba-dapp-clean/src/lib/vscContributionIntake.ts:193-207` separates chain, record, and email statuses. UI currently derives confirmation from chain status even when record pending/failed. Success must instead require backend acceptance of validated chain evidence.
- `workspace/repos/ceba-dapp-clean/src/pages/api/vsc-protocol-confirm.ts:125-142` requires original contribution ID alongside transaction hash. Journal loss recovery needs an explicit scope decision; hash-only recovery cannot assume a new contribution ID.
- Local registry self-enrollment is fixture-only. Production eligibility must not be inferred from registration request or KYC approval alone.

## Superseding product decisions

The decisions below supersede the earlier explicit quote-review/requote conclusions in this audit. Issue https://github.com/jdelos/ceba-matt/issues/11 is the current product contract.

1. Buyer edits token quantity or euro amount. Last edited field remains intent; current executable pricing updates the corresponding field.
2. Expired or changed pricing refreshes silently. Buy remains disabled until a current executable value exists. Do not show payment ceilings, quote review, requote warnings, expiry notices, or price-update ceremony.
3. Purchase signer is always the authenticated user's Dynamic embedded wallet. External wallets may authenticate or link but never sign purchases or act as fallback.
4. One Buy allows at most one user authorization. Approval, fixture-only enrollment, and contribution must execute atomically; failure must leave no partial allowance, enrollment, or contribution.
5. Preserve transaction journal and read-only reconciliation after refresh. Never automatically submit another payment.
6. Purchase success means backend-recorded, validated chain contribution. Email failure is non-fatal. Backend-record retry must never resend payment.
7. Lost-journal recovery remains authenticated and user-initiated from validated transaction evidence. No automatic purchase discovery, replacement contribution ID, or payment resend.

## Current implementation boundary

DApp implementation proceeds under https://github.com/jdelos/ceba-dapp-clean/issues/27. Protocol compatibility and atomic-mechanism proof remain under https://github.com/jdelos/vsc-protocol/issues/65; no protocol ABI change is justified until that validation runs.
