docs: define Product CASH settlement boundary - #162
Conversation
✅ Deploy Preview for muzinga ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ecfb51494
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (isHexAddress(quote.payerH160) && typeof quote.payerProductPublicKey === 'string' && /^0x[0-9a-fA-F]{64}$/.test(quote.payerProductPublicKey)) { | ||
| pass(gates, 'quote:payer', 'Payer binding', 'Quote binds the Product account public key and derived H160 runtime identity.', source); |
There was a problem hiding this comment.
Verify the public-key-to-H160 payer mapping
When payerH160 is a valid address belonging to one account and payerProductPublicKey is a valid key belonging to another, this gate still passes because it validates the two formats independently without deriving and comparing the H160 address. Consequently, the harness does not actually reject the valid-but-wrong payer case required by W16; use the existing Product deriveH160 mapping to verify the relationship.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
| if (finality.peopleParaId !== PRODUCT_CASH_TOPOLOGY.peopleParaId) { | ||
| fail(gates, 'finality:chain', 'Finality chain', 'Finality must be observed on People para 1004.', source); | ||
| } else if (finality.status === 'finalized' && isHexHash(finality.blockHash) && finality.reorgSafe === true) { | ||
| pass(gates, 'finality:chain', 'Finality chain', 'People-chain CASH settlement is finalized and reorg-safe.', source); |
There was a problem hiding this comment.
Bind finality to the quoted payment
For operator evidence containing any finalized, reorg-safe block from People para 1004, this gate reports that CASH settlement is finalized even though evaluateFinality receives neither the quote nor the Host payment and verifies no transaction or extrinsic in that block. An unrelated finalized block can therefore satisfy the finality check; the proof needs to identify the CASH transfer and bind its payer, recipient, asset, and amount to the receipt and quote.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
| if ( | ||
| isRecord(quote) && | ||
| sameText(entitlement.runtimeAddress, quote.runtimeAddress) && | ||
| sameText(entitlement.contentHash, quote.contentHash) && | ||
| sameText(entitlement.listenerAddress, quote.payerH160) |
There was a problem hiding this comment.
Correlate the entitlement with the CASH receipt
When the listener already has access to the same track from an earlier native-runtime purchase, that existing hasPaid/canAccess state satisfies this binding for a later CASH evidence file. The entitlement transaction hash, block, and timing are never correlated with the Host payment or stable receipt, so the harness cannot establish its claimed invariant that one real CASH receipt produced the entitlement rather than merely finding pre-existing access.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
💡 Codex Reviewdotify/web/scripts/product-cash-settlement-readiness.mjs Lines 245 to 246 in 0ecfb51 When AGENTS.md reference: AGENTS.md:L77-L77 dotify/web/scripts/product-cash-settlement-readiness.mjs Lines 308 to 311 in 0ecfb51 For operator evidence containing any finalized, reorg-safe block from People para 1004, this gate reports that CASH settlement is finalized even though AGENTS.md reference: AGENTS.md:L77-L77 dotify/web/scripts/product-cash-settlement-readiness.mjs Lines 331 to 335 in 0ecfb51 When the listener already has access to the same track from an earlier native-runtime purchase, that existing AGENTS.md reference: AGENTS.md:L77-L77 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
0ecfb51 to
e2fcf20
Compare
|
Addressed the review feedback in e2fcf20: Product public-key-to-H160 derivation is now verified, People finality must bind the exact CASH transfer/quote/payment, and Asset Hub entitlement must correlate to the same receipt/finality so pre-existing access cannot satisfy CASH evidence. CI is green. |
Outcome
This PR establishes an evidence-backed Product CASH settlement boundary. It
confirms that the current Product Host payment API cannot safely grant Dotify's
Asset Hub listening entitlement, keeps CASH unavailable, and adds a read-only
readiness harness for reevaluating that decision when Product exposes an
authoritative proof.
Issue and context
Refs #85. Implements the research/unsupported-result scope in
W16-product-cash-settlement.md.CASH is spent through Coinage on People chain, while Classic access is recorded
inside each artist SmartRuntime on Asset Hub. The current Host API returns an
opaque payment id and a
Processing,Completed, orFailedstatus, but nochain transaction, finalized block, or proof tying that payment to one runtime
entitlement. Treating
Completedas access would make the key service trust anunverifiable signal.
This is a partial slice of the Product compatibility epic. It must not close
#85: real CASH settlement remains dependent on a Product-supported bridge or
attestation.
Architecture and key concepts
The harness has two independent inputs:
product-cashis still unsupported and runtimewriters accept only executable native-payment intents;
release, finality, entitlement, idempotency, replay, and reconciliation.
Even a perfectly shaped future evidence file remains blocked in this build.
Only a later implementation based on an actual Product authority may enable the
rail.
How it works
smoke:product-cash-settlementreads the checked-in package pins, paymentmodel, runtime writer port, and Product architecture boundary.
cash-settlement-unavailablewith theexternal dependency named explicitly.
unreconciled settlement stays blocked.
using the existing native runtime write and authoritative read-back.
Design decisions and tradeoffs
Completedas entitlement because it lacks a verifiable bindingto the runtime/content/listener tuple.
accounting, replay, and availability trust that is not Product-native.
bridge exists.
the platform dependency testable without claiming the feature shipped.
The harness is intentionally strict and tied to the current DevNet topology. A
future network reset must update the decision and constants before evidence can
be evaluated.
Security, failure, and operations
The artist SmartRuntime remains the access authority. A Host receipt alone
never reaches the content-key service. Wrong payer, recipient, asset, chain,
reused receipt, duplicate retry, failed payment, reorg-unsafe finality, missing
entitlement, or unreconciled payment cannot produce a supported result.
No secret, permission, environment variable, hosted setting, contract, key, or
storage schema changes. The harness is read-only and reads optional evidence
from a local operator-selected JSON file. Rollback is a code revert; no data
rollback is needed.
Review guide
Suggested order
docs/design/product-cash-settlement-decision.mdfor the platform facts,rejected trust models, and required future authority.
web/scripts/product-cash-settlement-readiness.mjsfor fail-closedgate semantics and the absence of transaction side effects.
web/scripts/product-cash-settlement-readiness.test.mjsagainst theW16 acceptance matrix.
paymentModel.ts, the runbook, and architecture docs to confirm theexecutable/native boundary remains coherent.
docs/backlog/implementation/evidence/W16.mdfor the exact validationrecord and remaining external gate.
Verify carefully
Completedstatus yieldcash-settlement-supported?Product-supported authority?
Validation
npm --prefix web run test:product-cash-settlement(11/11)npm --prefix web run smoke:product-cash-settlement(6 pass / 0 fail / 1 blocked / 1 not run)--evidencefile exits 1npm --prefix web run test:unit(54 files / 430 tests)npm --prefix web run lintApp.tsxandArtistShell.tsx.npm --prefix web run fmt:checknpm --prefix web run buildCATALOG_API_URL=http://127.0.0.1:9 npm --prefix web run build:product-devnetnode scripts/backlog-sync.mjs --check --offlinegit diff --check origin/dev...HEADImplementation SHA tested:
52369d590783d18ca9d8e80867f00b801588e326.Known limitations and follow-ups
authoritative cross-chain entitlement mechanism does not exist in the
documented API.
support/refund ownership, add a disabled-by-default adapter, and prove one
funded receipt creates exactly one matching entitlement.
Metadata checklist
Dotify sprints)