You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
M2-06: Implement capability construction, amount conversion and integrity #27
report amount = smallest-unit integer string
Moss action amount = human decimal string
conversion = viem parseUnits/formatUnits only
never JavaScript Number
action return -> exact raw Capability retained
-> independent canonical snapshot + digest
snapshot may be deeply frozen
original Moss object/value must not be frozen/modified/replaced
simulator receives exact action-return object/value
post-simulation digest must equal pre-simulation digest
The #26 merged dependency is satisfied. Issue #27 may begin planning from this exact latest-main baseline.
Ready means dependency-ready only. It is not SCOPE_CONFIRMED, implementation authorization, QA, Maintainer Review, READY_TO_MERGE, or merge authorization. A closed Work Plan must be submitted and receive a separate Maintainer Scope Gate before any implementation branch, worktree, code change, commit, or PR is created. Issue #27 must not alter the already merged #26 Quote-selection contract outside a separately approved boundary.
planned branch after SCOPE_CONFIRMED: codex/issue-27-capability-integrity
planned isolated worktree after SCOPE_CONFIRMED: /Users/qy/Documents/moss-mini-demo-issue-27
writable paths: not yet authorized; they must be proposed as an exact closed set in the Work Plan
first required evidence: a closed Work Plan plus an exact-main contract and trust-boundary fact list
Project In Progress records planning ownership only. It does not authorize creating the branch/worktree, changing repository files, committing, opening a PR, requesting review, or entering a Merge Gate. Builder must wait for an explicit Maintainer SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED record.
Issue #23 remains Ready/unassigned and must not consume this P0 Builder slot. Issue #28 and later dependency-bound work remain Blocked.
origin/main@65753ada85156716e263b660eeab72c42d293431
feat: collect and deterministically select quotes (#73)
At publication time Issue #27 is Open, assigned to pillowtalk-Qy, Project In Progress, and there are no open PRs. Project In Progress records planning ownership only.
Proposed implementation branch after authorization:
codex/issue-27-capability-integrity
Proposed isolated worktree after authorization:
/Users/qy/Documents/moss-mini-demo-issue-27
This comment requests a new Maintainer Scope Gate. It does not claim SCOPE_CONFIRMED or IMPLEMENTATION_AUTHORIZED. No branch, worktree, repository file, dependency, lockfile, commit, or PR may be created until an explicit Maintainer record grants both.
2. Exact-main contract and trust-boundary facts
The plan is based on these facts from the exact baseline:
@moss-mini-demo/moss-adapter has one public package entry and already exports collectAndSelectQuotesV0_1.
Quote selection returns a discriminated QuoteCollectionResultV0_1. A SELECTED result contains the catalog snapshot, all candidate outcomes, selected protocolId, and selected RFC 8785 SHA-256 digest.
The matching ELIGIBLE outcome contains method, account, input and output assets, smallest-unit inputAmount and outputAmount, inputDecimals and outputDecimals, catalog digest, block window, and pinned Moss source identity.
MossPort.action currently retains the exact binding action-return object at mossOriginal.value and creates an independent deeply frozen snapshot, but integrity remains NOT_EVALUATED / DEFERRED_TO_M2_06.
The pinned Moss Capability contract has a capability root with protocol, method, params, and children; children may be capability or transaction nodes. Transaction nodes expose from, to, data, and value.
Current main has rules requiring Maintainer confirmation for protocol, token, spender, and other security-sensitive addresses, but it does not contain a production address approval record that this implementation can truthfully invent or hardcode.
If any of these facts changes before implementation, or origin/main no longer equals the frozen baseline, implementation stops and a revised Scope Gate is required.
3. Single goal
Call Moss action for the already selected protocol, convert the selected smallest-unit input amount into the exact human decimal required by Moss, preserve the exact action-return Capability object, create a separately owned immutable snapshot, calculate the frozen capability digest, expose node-count and address observations, and provide an integrity guard that can prove whether the exact raw object still matches the pre-simulation digest.
This work constructs and observes Capability evidence. It does not decide whether execution is safe, approved, authorized, guaranteed, or permitted to sign.
4. Closed writable path set
Exactly these 15 paths are requested. No wildcard is implied.
pnpm-lock.yaml
packages/moss-adapter/package.json
packages/moss-adapter/src/types.ts
packages/moss-adapter/src/source-bindings.ts
packages/moss-adapter/src/amount.ts
packages/moss-adapter/src/integrity.ts
packages/moss-adapter/src/capability.ts
packages/moss-adapter/src/index.ts
packages/moss-adapter/test/contracts.test.ts
packages/moss-adapter/test/production.test.ts
packages/moss-adapter/test/fake.test.ts
packages/moss-adapter/test/amount.test.ts
packages/moss-adapter/test/capability.test.ts
packages/moss-adapter/test/public-entry.smoke.mjs
packages/moss-adapter/test/server-only.test.ts
Path responsibilities:
package.json adds the sole new dependency.
pnpm-lock.yaml records only the corresponding importer and registry-resolved dependency graph.
types.ts defines the closed public type contract and the internal evidence shapes.
source-bindings.ts provides same-port exact action-return identity handoff while preserving the existing hostile-input boundary.
integrity.ts contains capability-specific RFC 8785, digest, immutable snapshot verification, tree count, and address observation helpers.
capability.ts contains the only new public runtime operation.
index.ts exports only the authorized public surface.
contracts.test.ts contains compile-time and public-contract negative cases.
production.test.ts and fake.test.ts prove exact action-to-simulate identity for both ports without implementing simulation mapping.
amount.test.ts and capability.test.ts contain the focused runtime matrices.
public-entry.smoke.mjs and server-only.test.ts update the exact public runtime export and browser exclusion assertions.
The following are explicitly not writable: root package.json, pnpm-workspace.yaml, any report-schema path, any quote-selection source or test, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README files, and all Issue #28 files.
A need for a sixteenth path is a stop condition and requires a replacement closed plan.
5. Dependencies and supply-chain boundary
One new direct dependency is requested:
viem: 2.55.11
It is added only to packages/moss-adapter/package.json. The lockfile may add the exact viem 2.55.11 resolution and the transitive graph selected by pnpm 11.16.0. It must not refresh unrelated importers or versions.
Existing canonicalize 3.0.0 remains the RFC 8785 implementation. Existing Node SHA-256 support remains the hash implementation. No second canonicalization or hashing package is added.
No new install or build-script permission is authorized. pnpm-workspace.yaml and its current allowBuilds policy remain unchanged. The lockfile diff must be reviewed for unexpected lifecycle-script permissions or unrelated churn before commit.
No direct dependency on legacy @themoss/core, no copy of vendor/moss source, and no change to the pinned Moss submodule are allowed.
6. Exact public API change
The only new runtime export from @moss-mini-demo/moss-adapter is:
No amount helper, canonicalization helper, digest helper, tree walker, address helper, class, Schema, error class, or alternate package subpath is public. MossPort keeps the same five methods and the same TypeScript method signatures. Existing runtime exports are unchanged.
The public import smoke test must prove that the package root exposes exactly the existing runtime exports plus constructCapabilityV0_1. Type-only exports must not appear at runtime.
7. Strict input and selected-quote association
The operation accepts SELECTED only at compile time and validates all runtime values as untrusted input. A cast NOT_SELECTED object, throwing getter, hostile Proxy, revoked Proxy, cyclic object, unsupported prototype, lone surrogate, or unexpected key fails before port.action is called.
The implementation takes an adapter-owned clone of selection, quoteRequest, and policy. It never relies on a caller-owned property after validation.
It must locate exactly one ELIGIBLE outcome whose protocolId equals selection.selected.protocolId. The selected digest must match a fresh RFC 8785 digest of that exact eligible outcome under the already merged #26 digest contract. The following values must agree across quoteRequest, matching normalized outcome, selected digest payload, catalog snapshot, and policy where applicable:
chainId 143
protocolId
method
account
input asset
output asset
smallest-unit input amount
input and output decimals
catalog identity and digest
selected raw quote and Moss source identity
Zero or multiple matching ELIGIBLE outcomes, any mismatch, a changed selected digest, an unknown catalog entry, unknown decimals, a stale catalog, or an unauthorized protocol/asset fails with the existing stable MossAdapterError boundary before action delegation. Invalid caller input uses INVALID_INPUT with operation action. A malformed or contradictory adapter/source result uses SOURCE_CONTRACT_VIOLATION with operation action. Neither error contains cause, source messages, URLs, headers, accounts, parameters, secrets, or raw payloads.
This validation does not re-run quote selection, alter ranking, rename deterministic candidate selection as a best trade, or modify #26 outcomes.
8. Amount contract and viem boundary
The report and selected-quote amount is a canonical positive smallest-unit base-10 integer string:
grammar is 0 or [1-9][0-9]*, with this operation requiring a positive value
no sign, decimal point, exponent, whitespace, separators, or leading zero
value is parsed only with BigInt
range is 1 through 2^256 - 1 inclusive
JavaScript Number is never used for an amount
Decimals are taken from the matching immutable #26 catalog snapshot, not from token symbol, UI input, Quote prose, or a guessed default. Decimals must be an integer in the already merged catalog range 0 through 255. Unknown decimals fail closed.
The Moss action amount is the canonical human decimal returned by:
Both functions are imported from the public viem 2.55.11 entry. A local hand-written decimal converter is forbidden.
Any external human decimal accepted by an internal validator is checked before parseUnits. The strict grammar rejects signs, exponent form, whitespace, empty integer/fraction components, redundant leading zeros, trailing decimal points, and more fractional digits than decimals. This precheck is mandatory because viem may round excess fractional precision; #27 must reject excess precision rather than round it.
Frozen examples:
smallest 1000000000000000000, decimals 18 -> human 1 -> smallest 1000000000000000000
smallest 1, decimals 18 -> human 0.000000000000000001 -> smallest 1
decimals 0 emits an integer human string
2^256 - 1 is accepted and round-trips
zero, 2^256, negative, exponent, floating smallest-unit input, and excess precision are rejected
The action input is a new adapter-owned ordinary object. It preserves validated protocol-specific additional quoteInput.params fields, replaces inputAsset and outputAsset with the validated canonical assets, and replaces amountIn with the derived human decimal. Method and account come from the validated quote request. The source quote request is not modified.
9. Maintainer-approved catalog and address source
Asset identity remains structural:
native asset is { kind: "NATIVE" }
token asset is { kind: "ERC20", address: EIP-55 address }
CapabilityConstructionPolicyV0_1 is a strict server-owned policy input, never request-body data. It contains:
schemaVersion 0.1
policyId and sourceVersion
chainId 143
exact allowed protocolId
exact selected catalog digest
approved input and output assets
expected capability-node, transaction-node, and total-node counts
approved transaction target addresses with explicit role PROTOCOL, SPENDER, or TOKEN
a correlated source union:
MAINTAINER_APPROVED with repository, exact 40-character commit, and tracked recordPath
SYNTHETIC_TEST with no approval record
Production composition may use MAINTAINER_APPROVED only when the referenced tracked record exists at the stated commit and contains the same addresses. SYNTHETIC_TEST is accepted only in tests and is never represented as production approval or real-chain evidence.
Current main has no such production address record. Therefore this Work Plan does not invent an address, infer one from a symbol, copy an address from Moss code, or add a hidden list. The requested Scope Gate must confirm that this injected, immutable-source policy is the approved #27 boundary. If Maintainer instead requires a repository address record to be added now, this 15-path plan is insufficient and implementation must stop for a revised path list and contract.
10. Exact raw identity, owned snapshot, and simulator handoff
For a successful Moss action:
action is called exactly once with the adapter-owned ActionInput.
mossOriginal.value is the exact object returned by the underlying Moss action binding, verified with object identity.
The original object is not frozen, cloned into its place, modified, normalized, decorated, or replaced.
An independent structured clone is created immediately after action return.
The clone is validated as finite, acyclic, lone-surrogate-free JSON data and as an observable Moss Capability tree.
Only the independent clone and Mini-Demo-owned evidence wrappers are recursively frozen.
Mutating the original after return cannot mutate the snapshot.
The result exposes simulatorInput as the exact same object as mossOriginal.value.
source-bindings.ts may maintain a per-port private WeakSet of exact objects returned by that same port action call. When the same registered object is supplied to that same port simulate method, the binding receives that exact object without a clone. An unregistered, cross-port, hostile, revoked, or invalid simulate input retains the current defensive snapshot-and-validation behavior and never reaches the binding on validation failure. The WeakSet is private, is not a public API, and does not keep objects alive.
This is the only simulate-related change in #27. It establishes identity transport. It does not interpret or map simulation output.
CapabilityConstructionResultV0_1 also exposes a bound verifyCurrentIntegrity operation. It recomputes the capability digest from the current exact raw object and returns one of:
MATCH with expected and actual digest
MISMATCH with expected and actual digest
UNPROVABLE with expected digest and no raw error text
The bound operation does not freeze or mutate the raw object. #28 must call it immediately before and after using simulatorInput. The #27 tests call the existing port simulate only to prove identity and post-call MATCH. If the source simulator mutates the object, the post-call result is MISMATCH. No simulation receipt, outcome, warning, coverage, ordering, continuity, block, or Decision data is produced.
11. Snapshot, tree, and address observations
The independent snapshot preserves the entire raw action-return Capability, including unknown JSON fields. No raw node or field is dropped from the snapshot or digest.
The observer follows the pinned Moss node discriminants:
capability node: kind capability, protocol, method, params, children
The policy requires expected values whose total equals capabilityNodes plus transactionNodes. A valid tree with different actual counts remains observable as nodeCount.status UNEXPECTED with both expected and actual values. It is not silently repaired, discarded, or converted to a STOP decision in #27. A malformed tree fails as SOURCE_CONTRACT_VIOLATION; it is not presented as valid Capability evidence.
Transaction addresses are parsed as EIP-55 identifiers and retained in stable first-observed order plus a deterministic deduplicated observation. The result records EXPECTED or UNEXPECTED and identifies unexpected targets without declaring safety. Source account and target addresses are not logged in errors.
Node-count or address mismatch does not authorize execution and does not become Alignment or Decision output in this Issue. Those observations remain evidence for downstream fail-closed handling.
The snapshot and raw action return have byte-equivalent canonical content at acquisition time. The digest is calculated from the independent acquisition snapshot so later mutation of the original cannot rewrite recorded evidence. verifyCurrentIntegrity canonicalizes the current original separately.
Tests must compare independently frozen expected text, lengths, domain hex, and digest. They must also prove canonicalize 3.0.0 produces the expected canonical text bytes. The expected digest must not be generated by the implementation under test.
Non-finite numbers, cycles, unsupported prototypes, throwing getters, Proxy failures, and lone surrogates are rejected or reported UNPROVABLE through stable secret-safe behavior. No approximate key sorter is allowed.
13. Test matrix
amount.test.ts:
1 MON with 18 decimals in both directions
one smallest unit with 18 decimals
decimals 0
2^256 - 1
repeated round-trip across representative decimals and boundary values
zero and values above uint256
leading zero, sign, whitespace, exponent, decimal smallest-unit amount
human excess precision rejected before viem can round
malformed and hostile values produce stable INVALID_INPUT
no source input mutation
no JavaScript Number amount path
capability.test.ts:
valid SELECTED result and exact matching ELIGIBLE outcome
exact selected digest recomputation and catalog association
policy correlated source union rejects production-without-record and synthetic-with-record
result discriminants narrow correctly
no extra runtime helper is public
MossPort still has exactly five methods and unchanged signatures
public-entry.smoke.mjs and server-only.test.ts:
Node 22 imports constructCapabilityV0_1 from the sole public package root
exact runtime export set is old set plus that one function
browser import still fails at server-only boundary
no Moss, capability raw data, address policy, canonicalization code, or secret-capable adapter code enters the browser bundle
All tests use synthetic identifiers and payloads only. They do not use a real Moss endpoint, Monad RPC, wallet, key, API key, transaction, receipt, quote, or chain evidence.
14. Determinism, ownership, and mutation rules
The operation is offline except for the supplied MossPort.action call. It does not read RPC, wall-clock data, random values, environment secrets, or browser state.
For identical validated selection, quote request, policy, and action-return JSON content:
action input is byte-equivalent
snapshot canonical bytes are identical
digest is identical
count and address observations are identical
input ordering does not alter deterministic normalized observations where an order is not evidentiary
All caller inputs are cloned before use and never modified. Raw Moss ownership stays with Moss. Snapshot and derived wrappers are owned by Mini-Demo. Only Mini-Demo-owned values are frozen. No operation mutates #26 outcomes, selected digest payload, quote request, policy, action return, or simulation return.
create Alignment, Decision, STOP, or MANUAL_REVIEW output
claim post-simulation success based only on digest equality
#28 remains responsible for calling the simulator in the product flow, mapping the output, and invoking the #27 integrity guard before and after that exact call.
16. Non-goals
No Quote collection or deterministic selection change.
No selected Quote versus Capability cryptographic binding beyond recording the selected digest in construction evidence.
No Capability safety assessment or authorization.
No simulation mapping.
No Alignment, Decision, STOP, or MANUAL_REVIEW behavior.
No Web/API orchestration.
No RPC or live-chain access.
No wallet, signing, transaction construction, submission, or receipt handling.
No Clear402.
No frontend or backend feature.
No real address or real-chain Fixture.
No report-schema or Decision Engine change.
No Moss fork, submodule, source, build-info, or pin change.
No workflow, branch protection, required check, Issue, Project, Milestone, permission, review, ready, merge-gate, or merge operation.
17. Implementation sequence after authorization
Fetch origin and require origin/main to equal the exact frozen SHA.
Require a clean state and create only the approved branch and isolated worktree.
Add viem 2.55.11 to the adapter package with pnpm 11.16.0; inspect the lockfile before any source work.
Add amount tests and strict viem conversion helpers.
Add capability golden-vector, snapshot, mutation, node-count, address, and hostile-input tests.
Add exact per-port action-return identity registration and simulate forwarding without changing MossPort signatures.
Implement constructCapabilityV0_1 and the two type exports.
Update only the public import and server-only assertions needed by the new runtime export.
Run the focused and full validation matrix from a clean, no-dist state.
lockfile installation can introduce unrelated churn
Controls are the strict prevalidator, BigInt-only values, independent frozen snapshot, current-integrity verifier, per-port WeakSet, byte-level vectors, explicit mismatch observations, synthetic-only tests, and exact path/dependency checks.
Rollback is one feature-branch revert before merge. No migration, database, deployment, chain state, transaction, or secret is created. If the public shape or address source is rejected, discard the branch rather than retaining a compatibility alias or partial implementation.
20. Stop conditions
Stop without implementation or further mutation if:
The 15-path list, sole proposed direct dependency viem@2.55.11, BigInt-only amount boundary, #26 file exclusion, and explicit #28 isolation are directionally closed. The frozen capability vector was independently recomputed and matches the plan exactly: 31-byte domain, 306-byte canonical text, 337-byte digest input, and sha256:0d251a152143187d0a50d9481330aef30fbf5ee03a011be2f936e5805ee9ad89.
Scope is not authorized because the following trust-boundary gaps remain.
1. MAINTAINER_APPROVED is currently caller-asserted, not authority-backed
The proposed public operation receives CapabilityConstructionPolicyV0_1 from its caller. A structurally valid object containing MAINTAINER_APPROVED, repository, commit and recordPath does not prove that a Maintainer approved those addresses.
Current main contains no tracked production address-authority record, and the proposed 15 paths contain neither such a record nor a verifier anchored to one. A runtime shape check can therefore validate metadata syntax while accepting a fabricated authority claim. SERVER_CONFIGURED catalog provenance must not be treated as Maintainer approval.
A revised plan must choose and fully specify one fail-closed contract:
add exact tracked Maintainer-owned policy record path(s), format, ownership, immutable revision/digest and verification path; or
make this release explicitly synthetic-only and reject every MAINTAINER_APPROVED production claim until that trust anchor exists.
If production authority remains supported, tests must reject nonexistent records, wrong repository/commit/path, content/digest mismatch, unapproved roles/addresses, duplicate or contradictory entries, and caller-supplied metadata that merely claims approval. Any new record or loader path must be included in a replacement closed writable-path list.
2. The authoritative acquisition snapshot is ambiguous
Current main already creates the independent frozen Mini-Demo snapshot inside the action source boundary before MossPort.action returns:
The plan separately says to clone again “immediately after action return” and calls that the acquisition snapshot. Because the raw Moss object remains mutable, a later clone cannot silently replace or redefine the earlier source-boundary evidence.
The revised plan must name one authoritative acquisition snapshot and ordering. Prefer reusing RawCapabilityEvidence.miniDemoDerived.snapshot, or explicitly move the atomic capture/digest boundary. It must require a fail-closed comparison between that immutable acquisition evidence and the current exact raw object before returning successful construction evidence. The recorded digest and all wrappers must remain explicitly MINI_DEMO_DERIVED; the raw object remains MOSS_ORIGINAL. Add a mutation-between-boundaries regression test.
3. WeakSet membership does not prove current input validity
Current simulate defensively snapshots and validates before delegation:
The proposed same-port WeakSet proves identity/provenance only. A registered raw object may be mutated after action acquisition into a cycle, accessor/throwing getter, unsupported prototype, lone surrogate, non-finite value or otherwise invalid payload. Membership must not bypass the hostile-input boundary.
The revised plan must require non-cloning current-value validation immediately before delegation for a registered object. Valid registered input must reach the binding by exact identity; invalid registered input must fail before delegate count changes. Add explicit registered-after-mutation tests for each hostile class. verifyCurrentIntegrity returning UNPROVABLE is not sufficient enforcement because MossPort.simulate remains independently callable.
4. #26 selected-digest verification must reuse the merged contract
Current main owns the exact selected payload and digest construction in createSelectedQuoteDigest:
The revised plan must explicitly reuse this existing internal helper against the unique matching ELIGIBLE outcome, rather than copy a second selected-Quote payload/canonicalization implementation into #27. This preserves the #26 Quote contract and prevents drift while keeping quote-selection files read-only.
Required next step: publish a replacement Work Plan that resolves all four items and restates the exact path/dependency set. Do not edit the frozen v1 comment in place.
No SCOPE_CONFIRMED or IMPLEMENTATION_AUTHORIZED is granted. Do not create the #27 branch/worktree, modify files, commit, or open a PR. Issue #28 and later dependency-bound work remain Blocked; Issue #23 remains Ready/unassigned.
v1 is not edited or deleted. This v2 supersedes v1 for any future implementation discussion only. It does not grant implementation authority.
The exact planning baseline remains:
origin/main@65753ada85156716e263b660eeab72c42d293431
feat: collect and deterministically select quotes (#73)
At this re-check, Issue #27 is Open, assigned to pillowtalk-Qy, Project In Progress, and no PR is open. The dependency gate records #26 merged into this exact main. Project status and assignment do not authorize implementation.
The proposed branch and worktree are still only names:
They have not been created. Until a separate Maintainer comment explicitly says SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED, the Builder must not create them, modify files, install dependencies, update a lockfile, commit, push, open a PR, request review, enter Merge Gate, or merge.
2. Four trust-boundary resolutions
2.1 No caller-asserted production authority in this release
The v1 MAINTAINER_APPROVED policy branch is removed. v2 is explicitly synthetic-only.
CapabilityConstructionPolicyV0_1 has exactly:
provenance: "SYNTHETIC_TEST"
It has no MAINTAINER_APPROVED discriminator and no field that can claim Maintainer authorization. Production input is rejected, including a cast object with provenance MAINTAINER_APPROVED, SERVER_CONFIGURED catalog provenance, pinned-submodule Moss provenance, an invented repository/commit/path, or a caller-supplied approval string.
The policy sourceReference must use the synthetic test grammar and is evidence of test construction only. expectedTransactionTargets are synthetic expected observations, not approved protocol, spender, token, or destination addresses. They never authorize a call, signing, execution, or real-chain action.
The selected catalog must have provenance SYNTHETIC_TEST and the matching selected outcome and action source must have SYNTHETIC_FAKE provenance. SERVER_CONFIGURED catalog entries and PINNED_SUBMODULE action provenance fail closed in this release.
The current main has no tracked production address-authority record. v2 therefore does not invent one or add one implicitly. A future production release requires a new Scope Gate with a precise Maintainer-owned record path, format, immutable revision, content digest, loader, and verification tests. That future work is outside this v2 and is a stop condition.
2.2 One authoritative acquisition snapshot
The authoritative acquisition snapshot is the object already produced inside the existing source boundary:
RawCapabilityEvidence.miniDemoDerived.snapshot
source-bindings.ts creates this independent structured clone and deep freeze before MossPort.action returns. v2 reuses that exact snapshot by identity. capability.ts must not clone the raw object again and must not create a second competing acquisition snapshot.
The construction sequence is fixed:
The source boundary validates the Moss action result and atomically creates the immutable Mini-Demo snapshot.
It returns the exact Moss original object and that authoritative snapshot in RawCapabilityEvidence.
constructCapabilityV0_1 verifies that the evidence layers are correctly labeled MOSS_ORIGINAL and MINI_DEMO_DERIVED.
Before returning success, it computes the digest from the authoritative snapshot and separately validates and canonicalizes the current exact raw object.
The current raw canonical bytes must equal the authoritative snapshot canonical bytes at this boundary. If they differ, the operation fails closed with SOURCE_CONTRACT_VIOLATION and returns no successful construction evidence.
The result snapshot is the same object as RawCapabilityEvidence.miniDemoDerived.snapshot, not a later clone.
A regression test mutates or replaces the raw value between source-boundary snapshot creation and capability construction. The mismatch must be observed and must not produce a successful result. The raw Moss object remains MOSS_ORIGINAL, while every snapshot, digest, count, and wrapper is MINI_DEMO_DERIVED.
2.3 WeakSet membership never bypasses current validation
The private per-port registration set records provenance only. It is not a validity grant.
Immediately before delegating a registered object to MossSourceBindings.simulate, source-bindings.ts must perform non-cloning current-value validation. The validator:
catches revoked Proxy and all reflective traps
requires an ordinary object with Object.prototype or null prototype
rejects accessor descriptors and throwing getters
walks own enumerable data values without structuredClone
rejects cycles, unsupported prototypes, non-finite numbers, lone surrogate keys or strings, and non-JSON values
completes synchronously and has no await or clone between the final validation and the binding call
A registered and currently valid object reaches the binding by exact identity. A registered object that was changed after action acquisition fails with INVALID_INPUT, operation simulate, before delegate count changes. No cause, raw exception, source message, URL, header, account, parameter, or secret is exposed.
The explicit regression matrix mutates a registered action-return object into each of these cases:
cycle
accessor that throws
hostile Proxy
revoked Proxy
unsupported prototype
non-finite value
lone surrogate
Each case must have zero simulate-binding calls. Unregistered valid input retains the existing defensive owned-snapshot path. Cross-port objects are unregistered and never receive exact forwarding.
capability.ts imports this existing internal helper and calls it exactly once for the unique matching ELIGIBLE outcome. It does not copy the selected payload field list, canonicalization call, or hash implementation. quote.ts and selection.ts remain read-only.
The helper output is compared byte-for-byte with selection.selected.digest, including algorithm, serialized lowercase SHA-256 value, and canonical payload content. A mismatch fails before action delegation. This preserves #26 semantics and makes future changes to the merged helper visible to #27 instead of allowing a shadow implementation.
3. Goal and explicit product boundary
Call Moss action for a validated, already selected synthetic protocol; convert smallest-unit amount to Moss human decimal; retain the exact action-return Capability; reuse the existing immutable acquisition snapshot; calculate the fixed RFC 8785 plus SHA-256 integrity digest; expose non-decisional node and target observations; and expose a current-integrity guard for #28.
This is synthetic development evidence and adapter integrity infrastructure only. It is not an application, protocol integration, wallet, authorization, safety conclusion, real-chain evidence, signing permission, execution guarantee, or Decision result.
4. Exact closed writable paths
Exactly 15 paths are authorized by this proposal. No wildcard, directory-wide, or “approved skeleton” is implied.
pnpm-lock.yaml
packages/moss-adapter/package.json
packages/moss-adapter/src/types.ts
packages/moss-adapter/src/source-bindings.ts
packages/moss-adapter/src/amount.ts
packages/moss-adapter/src/integrity.ts
packages/moss-adapter/src/capability.ts
packages/moss-adapter/src/index.ts
packages/moss-adapter/test/contracts.test.ts
packages/moss-adapter/test/production.test.ts
packages/moss-adapter/test/fake.test.ts
packages/moss-adapter/test/amount.test.ts
packages/moss-adapter/test/capability.test.ts
packages/moss-adapter/test/public-entry.smoke.mjs
packages/moss-adapter/test/server-only.test.ts
Path responsibilities:
package.json adds the sole direct dependency.
pnpm-lock.yaml adds only the viem importer and its exact resolved graph.
types.ts defines the two new public types and internal result details.
source-bindings.ts adds private exact-action registration and current-value validation before simulate delegation, without changing the five-method MossPort interface.
amount.ts contains non-public strict amount wrappers around viem.
integrity.ts contains non-public snapshot comparison, RFC 8785 digest, tree observation, and address observation.
capability.ts contains constructCapabilityV0_1.
index.ts adds the one runtime export and two type exports.
contracts.test.ts covers compile-time and runtime public contract boundaries.
production.test.ts and fake.test.ts cover exact identity and defensive simulation input behavior.
amount.test.ts and capability.test.ts cover the complete focused matrix.
public-entry.smoke.mjs and server-only.test.ts update the exact export and server-only assertions.
Explicitly not writable: root package.json, pnpm-workspace.yaml, every report-schema path, quote.ts, selection.ts, asset-catalog.ts, quote-selection tests, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README or other documentation, and all Issue #28 paths.
A sixteenth path is a hard stop and requires another replacement Work Plan.
5. Dependency and package boundary
The only new direct dependency is:
viem: 2.55.11
Existing dependencies remain unchanged. canonicalize 3.0.0 remains the only RFC 8785 implementation. Node built-in SHA-256 remains the only hash primitive. No dependency is copied into vendor/moss, and legacy @themoss/core is not added.
The lockfile may add only the viem 2.55.11 importer and the registry-resolved viem graph selected by pnpm 11.16.0. It must not refresh unrelated versions. No new install script or build-script permission is allowed; pnpm-workspace.yaml and its current sharp policy remain byte-for-byte unchanged.
6. Public API and type contract
Only one new runtime export is added from the package root:
CapabilityConstructionPolicyV0_1 is a closed synthetic-only object containing schemaVersion 0.1, policyId, sourceVersion, provenance SYNTHETIC_TEST, synthetic sourceReference, chainId 143, selected catalog digest, exactly one protocolId, exact input/output assets, expected capability/transaction/total node counts, and synthetic expected transaction targets with explicit roles.
CapabilityConstructionResultV0_1 is a closed result containing:
status CONSTRUCTED_SYNTHETIC
operation evidence from the selected Moss action
actionInput with derived human amount
mossOriginal.value and simulatorInput pointing to the same exact action-return object
miniDemoDerived.snapshot pointing to the authoritative source-boundary snapshot
RFC8785-SHA256 integrity record
non-decisional node-count and transaction-target observations
verifyCurrentIntegrity(), returning MATCH, MISMATCH, or UNPROVABLE
The result must not contain approval, authorization, safety, execution, signing, Decision, STOP, MANUAL_REVIEW, simulation-success, receipt, or RPC claims.
MossPort retains exactly five methods with unchanged signatures. No helper, Schema, digest function, address loader, class, alternate package entry, or sixth method is public.
7. Input validation and selected outcome association
All four arguments are untrusted runtime values even though TypeScript narrows the selection to SELECTED. Validation is performed against adapter-owned data before action delegation. A cast NOT_SELECTED value, unexpected key, accessor, hostile or revoked Proxy, unsupported prototype, cycle, non-finite number, lone surrogate, stale catalog, or contradictory digest fails with INVALID_INPUT and zero action calls.
The validator requires exactly one ELIGIBLE outcome with protocolId equal to selection.selected.protocolId. It calls createSelectedQuoteDigest on that owned unique outcome and compares the resulting algorithm, payload bytes, and serialized digest to selection.selected.digest. It then requires agreement across quoteRequest, the outcome, catalog snapshot, and synthetic policy for:
chainId 143
protocolId and method
EVM account
input/output asset identity
smallest-unit input amount
input/output decimals
catalog ID, version, source, and digest
Moss source provenance and build identity
Only the matching synthetic catalog and SYNTHETIC_FAKE source are accepted. Zero or multiple matches, any disagreement, unknown asset, unknown decimals, stale validity window, or policy mismatch fails before port.action.
The action request is adapter-owned, preserves validated additional quote parameters, replaces only the canonical asset fields and amountIn, and never mutates quoteRequest or selection.
8. Exact amount conversion
The smallest-unit amount is a positive canonical decimal string, parsed only with BigInt, in the inclusive range 1 through 2^256 - 1. JavaScript Number is prohibited for amount values.
Decimals are the known integer from the matching #26 catalog snapshot, range 0 through 255. No symbol, UI value, Quote prose, or inferred default can supply decimals. Unknown assets and decimals fail closed.
Both functions come only from viem 2.55.11. A strict pre-validator rejects signs, whitespace, exponent notation, empty components, redundant leading zeroes, trailing decimal points, and any fractional precision above decimals before calling parseUnits. This prevents viem rounding from accepting a lossy value.
Required vectors include 1 MON and 10^18, one smallest unit, decimals 0, uint256 maximum, exact round-trip, zero, uint256 overflow, malformed integer strings, and excess human precision.
9. Authoritative snapshot and exact identity
source-bindings.ts remains the only acquisition boundary. It keeps the exact Moss action-return object at mossOriginal.value and creates the one authoritative deeply frozen snapshot at miniDemoDerived.snapshot before MossPort.action returns.
constructCapabilityV0_1 reuses that snapshot by identity. It does not clone again, replace it, or freeze the raw object. It separately validates and canonicalizes the current raw object and requires equality with the authoritative snapshot before successful return. A mutation between the source-boundary snapshot and construction fails closed with SOURCE_CONTRACT_VIOLATION.
The construction result labels the raw object MOSS_ORIGINAL and all snapshot/digest/observation wrappers MINI_DEMO_DERIVED. Unknown JSON fields are retained in the snapshot and participate in the digest.
The private per-port registration set records exact raw objects returned by action. It proves provenance only. Immediately before a registered object reaches the simulate binding, a synchronous non-cloning validator walks the current value and:
catches all Proxy traps and revoked Proxy access
requires ordinary Object.prototype or null-prototype objects
A valid registered object reaches the binding by exact identity with no await or clone between final validation and invocation. An invalid registered object fails with INVALID_INPUT, operation simulate, and zero delegate calls. Unregistered valid input follows the existing defensive clone path. Cross-port objects are unregistered.
The regression matrix mutates a registered object into cycle, throwing accessor, hostile Proxy, revoked Proxy, unsupported prototype, non-finite value, and lone-surrogate cases. Every case is rejected before delegation.
10. Integrity digest contract
The digest is calculated from the authoritative frozen snapshot:
Tests compare independent expected text, lengths, domain hex, canonicalize 3.0.0 output bytes, and digest. They do not generate the expected value from the implementation under test. Invalid Unicode, cycles, accessors, Proxy traps, unsupported prototypes, and non-finite values fail closed without raw error text.
11. Node and address observations
The observer uses only the pinned Moss public node shape:
capability: kind, protocol, method, params, children
It records capabilityNodes, transactionNodes, totalNodes, and compares them with the synthetic policy expected values. A valid tree with a mismatch returns nodeCount.status UNEXPECTED with expected and actual counts. A malformed tree returns SOURCE_CONTRACT_VIOLATION and is never presented as valid evidence.
Transaction targets are parsed as EIP-55 addresses and retained in deterministic first-observed and deduplicated forms. They are compared only with synthetic expectedTransactionTargets. The result can say EXPECTED or UNEXPECTED; it cannot say approved, safe, authorized, or permitted.
No production address, real chain address, token, spender, protocol, or wallet address is added. A future production address authority requires a separate Scope Gate and a tracked Maintainer-owned record with immutable revision and content verification.
12. Determinism and ownership
The operation is offline except for the one supplied MossPort.action call. It uses no RPC, wall clock, randomness, environment secret, browser state, or Number-based amount path.
For identical validated inputs and identical action-return JSON content, action input, snapshot bytes, digest, counts, and address observations are identical. All inputs are cloned before use and no caller-owned input is mutated. Only Mini-Demo-owned snapshots and wrappers are frozen. The raw Moss object remains mutable and original.
verifyCurrentIntegrity recomputes current raw content independently:
MATCH means current raw canonical bytes equal the authoritative snapshot bytes
MISMATCH means both are valid but differ
UNPROVABLE means current raw validation/canonicalization fails
Mutation changes the current computed digest or makes it UNPROVABLE; it never changes the recorded snapshot or digest.
13. Complete test matrix
amount.test.ts covers:
1 MON and 10^18 in both directions
one smallest unit
decimals 0
uint256 maximum and overflow
exact round-trips at representative decimals
zero, signs, whitespace, exponent, leading zero, decimal smallest-unit input
human excess precision rejected before parseUnits
synthetic-only input and no mutation
no JavaScript Number amount handling
capability.test.ts covers:
valid synthetic SELECTED result and one matching ELIGIBLE outcome
reuse of createSelectedQuoteDigest and exact selected-digest comparison
SERVER_CONFIGURED catalog, PINNED_SUBMODULE source, and MAINTAINER_APPROVED policy all rejected
synthetic policy with malformed sourceReference, duplicate targets, contradictory target roles, or invalid address rejected
every invalid case has zero action calls and secret-safe MossAdapterError
canonical human action amount and preserved additional parameters
exact action-return identity and unchanged raw object
result snapshot identity equals source-boundary snapshot, deep independence, and deep freeze
mutation between boundary snapshot and construct fails closed
simulatorInput exact identity
digest golden vector, exact domain bytes, canonical bytes, lowercase hash
mutation changes current verification but not recorded evidence
same-port valid simulate exact identity and post-call MATCH
registered cycle, accessor, hostile Proxy, revoked Proxy, unsupported prototype, non-finite value, and lone surrogate rejected before simulate delegate
valid and unexpected node counts observed
expected and unexpected synthetic transaction targets observed
malformed tree is not represented as evidence
unknown raw fields retained and digest-relevant
constructCapabilityV0_1 never acquires or maps simulation output
production.test.ts and fake.test.ts cover the per-port registration boundary, valid exact forwarding, defensive unregistered input, cross-port rejection, all registered-after-mutation hostile classes, zero delegate calls on invalid values, no cause, and no sensitive text.
contracts.test.ts covers the two new type exports, SELECTED-only narrowing, synthetic-only policy union, result discriminants, unchanged five-method MossPort, and absence of any additional runtime helper.
public-entry.smoke.mjs and server-only.test.ts prove Node 22 public-root import, exactly one added runtime export, type-only exports absent at runtime, and no browser bundle leakage.
All inputs are synthetic. No real Moss, Monad, RPC, wallet, key, API key, transaction, receipt, Quote, or chain evidence is used.
#27 may change only the exact action-to-simulate identity transport, expose simulatorInput, and expose verifyCurrentIntegrity for pre/post-use checks. It may use synthetic simulate calls in tests only.
#27 must not acquire production simulation, map RawSimulationEvidence, define simulation request/response contracts, create Receipt, Outcome, Warning, Coverage, Ordering, StateContinuity, block, RPC, provider, Alignment, Decision, STOP, or MANUAL_REVIEW evidence, or claim simulation success from digest equality.
#28 remains responsible for calling the simulator in the product flow, mapping simulation output, preserving simulation evidence, and deciding how pre/post integrity failure affects its own contract.
15. Explicit non-goals
No change to #26 quote collection, normalization, ranking, timeout, selected digest, or source references.
No Capability safety, authorization, approval, signing permission, execution guarantee, Decision, STOP, MANUAL_REVIEW, or risk adjudication.
No production address authority.
No RPC, live chain, wallet, signing, transaction submission, receipt, backend, frontend, Web/API orchestration, database, deployment, or Clear402.
No report-schema, decision-engine, Moss source, submodule, build-info, workflow, dependency policy, branch protection, required check, governance document, Issue, Project, Milestone, review, ready, Merge Gate, or merge change.
16. Implementation and clean-checkout verification after approval
Only after Maintainer authorization:
fetch origin and require exact origin/main baseline
create the proposed branch and isolated worktree
add viem 2.55.11 and inspect only its lockfile graph
implement amount boundary and tests
implement source-boundary identity registration and current validation
implement capability construction by reusing createSelectedQuoteDigest
implement snapshot comparison, digest, observations, and integrity guard
update only the public-entry and server-only assertions
Acceptance requires Node 22.23.1, pnpm 11.16.0, frozen install from no dist, all tests green, exactly the 15 paths, only viem 2.55.11 direct addition, no unrelated lockfile churn, public package smoke success, exact identity, independent snapshot, golden digest, amount boundaries, hostile registered-input rejection, no #28 mapping, and exact-head quality-gate SUCCESS.
17. Risks, rollback, and stop conditions
Risks are viem excess-precision rounding, raw-object mutation, identity forwarding without current validation, canonicalization failure, misleading node/address observations, accidental #28 absorption, and unrelated lockfile churn.
Controls are strict prevalidation, synthetic-only policy, existing source-boundary snapshot reuse, current-value non-cloning validation, BigInt-only conversion, existing canonicalize helper, exact byte vectors, per-port registration, no sensitive errors, and exact path/dependency review.
Rollback is a feature-branch revert before merge. No deployment, chain state, transaction, database, or secret is created.
Stop immediately and request a revised Scope Gate if:
One trust-boundary blocker remains, so implementation is not authorized.
Registered exact input is not yet JSON-descriptor closed
Section 2.3 requires the current-value validator to “walk own enumerable data values.” That is insufficient for an exact raw object that is forwarded unchanged to the simulator.
A registered object can be mutated after acquisition with:
a non-enumerable own data property;
an own Symbol-keyed property;
a sparse array element/hole or an extra non-index array property.
RFC 8785 / JSON serialization and the proposed enumerable-value walk can ignore or normalize that state, while the underlying simulator receives the exact object and can still observe it. The recorded snapshot/current digest can therefore remain MATCH even though the simulator-visible object contains state that was never represented by the Mini-Demo evidence. WeakSet membership does not close this gap.
A replacement Work Plan must require one shared JSON-exact current-value validator for both verifyCurrentIntegrity and the registered simulate path:
inspect every own key with Reflect.ownKeys under trap-safe handling;
for records, allow only enumerable string-keyed data descriptors and reject Symbols, non-enumerable properties and accessors;
for arrays, require a dense canonical index set plus the standard length descriptor, reject holes, Symbols, extra named properties, accessors and other non-enumerable properties;
recursively enforce the same rules before canonicalization and immediately before exact-identity delegation;
return UNPROVABLE from integrity verification and fail INVALID_INPUT / simulate with zero delegate calls when the descriptor closure is violated.
Add explicit registered-after-acquisition regression tests for non-enumerable data properties, Symbol keys, sparse arrays and extra array properties. Each must prove zero simulator delegation; the integrity check must not report MATCH.
Publish v3 as a new immutable comment; do not edit v2 in place. The path and dependency set may remain unchanged if this correction fits the existing authorized proposal paths.
No SCOPE_CONFIRMED or IMPLEMENTATION_AUTHORIZED is granted. Do not create the #27 branch/worktree, install viem, modify files, commit, push, or open a PR. Issue #23 remains Ready/unassigned; Issue #28 and later dependency-bound work remain Blocked.
Neither v1 nor v2 is edited or deleted. This v3 supersedes both only for future implementation discussion. It is a full self-contained plan, not a delta or patch note, and it does not authorize implementation.
The exact planning baseline was fetched again and remains:
origin/main@65753ada85156716e263b660eeab72c42d293431
feat: collect and deterministically select quotes (#73)
Issue #27 remains Open, assigned to pillowtalk-Qy, Project In Progress, with no open PR. The proposed implementation resources remain names only:
They do not exist and must not be created before a new Maintainer comment explicitly records SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED.
2. Goal and product boundary
The only goal is to call Moss action for a validated already-selected synthetic protocol, convert the selected smallest-unit input amount to the exact human decimal required by Moss, preserve the exact action-return Capability object, reuse the one authoritative source-boundary snapshot, calculate the fixed Capability integrity digest, record non-decisional node and address observations, and expose a current-integrity check that #28 can use around exact-identity simulation.
This is synthetic development evidence and adapter integrity infrastructure only. It is not an application, production Moss or Monad integration, approval, authorization, safety conclusion, signing permission, execution guarantee, wallet behavior, real-chain evidence, or Decision result.
3. Exact-main trust-boundary facts
The v3 plan is bound to these facts from the exact baseline:
@moss-mini-demo/moss-adapter has one public package entry and currently exposes five MossPort methods.
createSelectedQuoteDigest in packages/moss-adapter/src/quote.ts is the merged sole constructor for the selected-Quote digest contract.
MossPort.action retains the exact binding action-return object at mossOriginal.value and creates an independent deeply frozen miniDemoDerived.snapshot inside source-bindings.ts before returning.
MossPort.simulate currently clones and validates its input before binding delegation.
The pinned Moss Capability model has capability and transaction nodes, while raw unknown JSON fields must remain preserved.
Current main has no production Maintainer-owned address authority record.
If any fact or origin/main changes before implementation, this Scope Gate expires and Builder stops.
4. Resolved trust-boundary decisions
4.1 Synthetic-only authority
CapabilityConstructionPolicyV0_1 has exactly:
provenance: "SYNTHETIC_TEST"
There is no MAINTAINER_APPROVED branch and no field capable of claiming Maintainer authorization. The selected catalog must be SYNTHETIC_TEST and the action source must be SYNTHETIC_FAKE. SERVER_CONFIGURED catalog provenance, PINNED_SUBMODULE action provenance, MAINTAINER_APPROVED, invented repository/commit/path metadata, and caller-provided approval prose are rejected.
sourceReference identifies synthetic test construction only. expectedTransactionTargets are synthetic expectations, not approved protocol, spender, token, wallet, or destination addresses. A future production authority requires a separate tracked Maintainer-owned record, loader, immutable revision/digest verification, new closed paths, and a new Scope Gate.
4.2 One authoritative acquisition snapshot
The sole authoritative acquisition snapshot is:
RawCapabilityEvidence.miniDemoDerived.snapshot
It is created inside source-bindings.ts before MossPort.action returns. constructCapabilityV0_1 reuses that same snapshot by identity. It does not create, substitute, or relabel a second acquisition snapshot.
Before successful construction evidence is returned, current exact raw bytes and authoritative snapshot canonical bytes must agree. Mutation between source-boundary acquisition and construction fails with SOURCE_CONTRACT_VIOLATION. The exact raw object remains MOSS_ORIGINAL. Snapshot, digest, count, address, and wrapper evidence remain MINI_DEMO_DERIVED.
4.3 One shared JSON-exact validator
There is exactly one internal current-value validator implementation in integrity.ts. source-bindings.ts imports and invokes that same function for registered exact simulate input. verifyCurrentIntegrity invokes that same function before canonicalization.
No second validator, reduced validator, enumerable-only walker, JSON.stringify precheck, structuredClone substitute, or divergent simulate-only implementation is permitted.
The validator returns adapter-owned inspection data only after the complete object graph passes. It does not modify, freeze, clone, normalize, replace, or invoke a getter on the raw input.
4.4 Direct reuse of the merged #26 selected digest
capability.ts imports the existing internal createSelectedQuoteDigest from quote.ts and calls it for the unique matching ELIGIBLE outcome. It must not copy the selected payload list, canonicalizer, hash call, or serialization contract.
The fresh helper output is compared exactly with selection.selected.digest. quote.ts, selection.ts, asset-catalog.ts, and their tests remain read-only.
5. Closed writable path set
Exactly these 15 paths are requested. No wildcard or directory-wide permission is implied.
pnpm-lock.yaml
packages/moss-adapter/package.json
packages/moss-adapter/src/types.ts
packages/moss-adapter/src/source-bindings.ts
packages/moss-adapter/src/amount.ts
packages/moss-adapter/src/integrity.ts
packages/moss-adapter/src/capability.ts
packages/moss-adapter/src/index.ts
packages/moss-adapter/test/contracts.test.ts
packages/moss-adapter/test/production.test.ts
packages/moss-adapter/test/fake.test.ts
packages/moss-adapter/test/amount.test.ts
packages/moss-adapter/test/capability.test.ts
packages/moss-adapter/test/public-entry.smoke.mjs
packages/moss-adapter/test/server-only.test.ts
Path responsibilities:
package.json adds the sole direct dependency.
pnpm-lock.yaml records only the corresponding adapter importer and resolved graph.
types.ts defines the two new public types and internal result details.
source-bindings.ts records exact same-port action identities and calls the shared JSON-exact validator immediately before registered simulate delegation.
integrity.ts contains the single shared JSON-exact validator, authoritative snapshot comparison, RFC 8785 capability digest, tree observation, and address observation.
capability.ts contains the sole new public runtime operation and directly reuses createSelectedQuoteDigest.
index.ts adds one runtime and two type exports.
contracts.test.ts covers compile-time and public contract boundaries.
production.test.ts and fake.test.ts cover exact identity, JSON-exact simulate enforcement, and defensive unregistered input behavior.
amount.test.ts and capability.test.ts cover the focused conversion, construction, digest, descriptor, ownership, and observation matrices.
public-entry.smoke.mjs and server-only.test.ts update exact package-root and browser exclusion assertions.
Explicitly read-only: root package.json, pnpm-workspace.yaml, all report-schema paths, quote.ts, selection.ts, asset-catalog.ts, quote-selection tests, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README and other documentation, and every Issue #28 path.
The JSON-exact correction fits the existing integrity.ts, source-bindings.ts, and approved tests. No sixteenth path is requested. Requiring one is a stop condition.
6. Dependency and supply-chain boundary
The sole new direct dependency remains:
viem: 2.55.11
It is added only to packages/moss-adapter/package.json. pnpm-lock.yaml may add only the adapter importer change and the exact viem 2.55.11 transitive graph selected by pnpm 11.16.0. Unrelated lockfile refresh is prohibited.
Existing canonicalize 3.0.0 remains the sole RFC 8785 implementation. Existing Node SHA-256 support remains the sole hash primitive. Node built-in util.types.isProxy may be used to reject every Proxy without adding a dependency.
No install/build lifecycle permission is added. pnpm-workspace.yaml and its current sharp permission remain byte-for-byte unchanged. No legacy @themoss/core dependency, vendor source copy, Moss pin change, or second canonical/hash implementation is allowed.
CapabilityConstructionPolicyV0_1 is a closed synthetic-only object containing schemaVersion 0.1, policyId, sourceVersion, provenance SYNTHETIC_TEST, synthetic sourceReference, chainId 143, selected catalog digest, exactly one protocolId, canonical input/output assets, expected capability/transaction/total node counts, and synthetic expected transaction targets with explicit observation roles.
CapabilityConstructionResultV0_1 contains:
status CONSTRUCTED_SYNTHETIC
selected Moss action operation evidence
adapter-owned actionInput with the derived human amount
mossOriginal.value and simulatorInput as the same exact action-return object
miniDemoDerived.snapshot as the same authoritative source-boundary snapshot
RFC8785-SHA256 integrity record
non-decisional node-count and transaction-target observations
verifyCurrentIntegrity(), returning MATCH, MISMATCH, or UNPROVABLE
No public amount helper, validator, canonicalizer, digest helper, tree walker, address helper, error class, runtime Schema, alternate entry, or sixth MossPort method is added. MossPort signatures remain unchanged. Runtime smoke tests require the old exact export set plus constructCapabilityV0_1 only.
8. Strict selected-input association
All arguments are untrusted at runtime. The port shape is checked, and selection, quoteRequest, and policy are inspected into adapter-owned validated values before action delegation.
A cast NOT_SELECTED input, unexpected key, accessor, Symbol, non-enumerable property, sparse array, extra array property, hostile or revoked Proxy, unsupported prototype, cycle, repeated object alias, non-finite number, lone surrogate, stale catalog, or contradiction fails before action.
Exactly one ELIGIBLE outcome must match selection.selected.protocolId. createSelectedQuoteDigest is called for that exact outcome and must match selection.selected.digest in algorithm, canonical payload content, and lowercase serialized SHA-256 value.
The following must agree across the quote request, matching normalized outcome, selected digest, catalog snapshot, and synthetic policy:
chainId 143
protocolId and method
EVM account
input and output asset identity
smallest-unit input amount
input and output decimals
catalog ID, source version, provenance, sourceReference, and digest
Moss source provenance and build identity
Only SYNTHETIC_TEST catalog and SYNTHETIC_FAKE source are accepted. Zero/multiple matches, unknown asset/decimals, changed selected digest, or any disagreement produces existing secret-safe MossAdapterError before action, with delegate count zero.
The action input is an adapter-owned ordinary object. It preserves validated additional quoteInput.params fields, replaces only canonical inputAsset, outputAsset, and amountIn, and does not modify any input.
9. Amount conversion contract
The selected/report amount is a positive canonical smallest-unit decimal integer string:
grammar [1-9][0-9]*
BigInt only
inclusive range 1 through 2^256 - 1
no sign, point, exponent, whitespace, separator, or leading zero
never JavaScript Number for an amount
Decimals come only from the matching immutable #26 catalog snapshot and must be known in the existing range 0 through 255. Symbol, UI input, prose, and guessed defaults are never decimals authorities.
Both functions come only from viem 2.55.11. Before any parseUnits call, strict human-decimal grammar rejects signs, whitespace, exponent notation, empty components, redundant leading zeroes, trailing decimal point, and fractional precision greater than decimals. This prevents viem rounding from accepting a lossy value.
Required vectors include 1 MON with 10^18, one smallest unit, decimals 0, uint256 maximum, representative exact round-trips, zero, overflow, malformed strings, and excess precision.
10. JSON-exact validator contract
The single internal validator enforces the following recursively for the entire raw graph before either integrity canonicalization or registered exact simulate delegation.
10.1 Trap and graph safety
All Object.getPrototypeOf, Reflect.ownKeys, Reflect.getOwnPropertyDescriptor, array classification, and descriptor reads execute inside a fail-closed boundary.
Any Proxy detected through Node util.types.isProxy is rejected, including nested, hostile, revoked, or stateful Proxy objects.
Any thrown trap or reflective operation is rejected.
Cycles and repeated object aliases are rejected because JSON cannot preserve simulator-observable graph identity.
Only null, boolean, finite number, lone-surrogate-free string, strict ordinary record, and strict array values are accepted.
undefined, bigint, symbol, function, non-finite number, Date, Map, Set, typed array, class instance, unsupported prototype, and other non-JSON values are rejected.
String values and every string key are checked for lone surrogates.
10.2 Ordinary record closure
For a non-array record:
Prototype must be exactly Object.prototype or null.
Reflect.ownKeys inspects every own key under trap-safe handling.
Every own key must be a string. Any Symbol key is rejected.
Reflect.getOwnPropertyDescriptor must return a descriptor for every key.
Every descriptor must be an enumerable data descriptor.
Any non-enumerable property is rejected.
Any accessor, getter, setter, or descriptor without a data value is rejected.
Recursion uses descriptor.value rather than invoking property access.
The same complete rules apply to every nested value.
No Object.keys, Object.entries, for-in, spread, JSON.stringify, or canonicalizer is used as a substitute for Reflect.ownKeys descriptor closure.
10.3 Array closure
For an array:
It must be a genuine non-Proxy Array with prototype exactly Array.prototype.
Reflect.ownKeys must return exactly the dense canonical string indices 0 through length - 1 in canonical order, followed only by length.
Every expected index must exist. A hole or sparse index set is rejected.
Index keys must use canonical decimal spelling. Noncanonical numeric-looking keys are rejected.
Every index descriptor must be an enumerable data descriptor.
The only permitted non-enumerable own property is length.
length must have the standard Array length data descriptor: string key length, value equal to the array length, writable true, enumerable false, configurable false, with no getter or setter.
Any Symbol key is rejected.
Any extra named property is rejected.
Any accessor index, accessor property, extra non-enumerable property, or modified length descriptor is rejected.
Every element descriptor.value is recursively checked by the same validator.
This makes the accepted current value exactly representable by JSON/RFC 8785 without simulator-visible own-key, descriptor, sparseness, alias, or Proxy state being omitted.
11. Shared failure semantics and ordering
verifyCurrentIntegrity and the registered simulate path call the same validator implementation.
verifyCurrentIntegrity ordering:
validate current exact raw through the shared JSON-exact validator
if validation fails, return UNPROVABLE
only after success, RFC 8785 canonicalize and compute current digest
return MATCH only if the current canonical bytes/digest equal the authoritative snapshot record
otherwise return MISMATCH
A descriptor, key, array, graph, Proxy, Unicode, or JSON violation can never return MATCH, even if JSON.stringify would omit it or canonicalize would produce the same text.
Registered simulate ordering:
confirm same-port exact action-return identity
synchronously run the shared JSON-exact validator
on any validation failure, throw MossAdapterError with code INVALID_INPUT and operation simulate
confirm there has been no await, clone, normalization, or replacement after validation
invoke the binding synchronously with the exact registered object
only the returned Promise is then awaited
Every failure occurs before simulator delegation. Delegate count remains zero. No cause, raw trap exception, URL, header, account, parameter, secret, key, or source message is retained or exposed.
Unregistered valid input keeps the current defensive structuredClone and validation path. Cross-port input is unregistered. WeakSet membership proves acquisition provenance only and never bypasses current validation.
12. Exact raw identity and authoritative evidence
MossPort.action is invoked exactly once. The exact source action-return object remains at mossOriginal.value and is also simulatorInput by strict identity.
The raw object is never frozen, modified, normalized, decorated, cloned into its place, or replaced. The source-boundary snapshot remains a different, independent, deeply frozen Mini-Demo-owned object. constructCapabilityV0_1 uses that snapshot by identity and does not clone again.
Before returning CONSTRUCTED_SYNTHETIC, the shared validator and canonical comparison prove that current raw content is JSON-exact and equal to the authoritative acquisition snapshot. A source-retained mutation between acquisition and construction returns SOURCE_CONTRACT_VIOLATION rather than successful evidence.
Unknown valid JSON fields remain in the snapshot and capability digest. Later valid raw mutation produces MISMATCH. Later JSON-exact violation produces UNPROVABLE. Neither changes the recorded snapshot or recorded digest.
13. Capability digest contract
The digest is calculated from the authoritative frozen snapshot:
Tests compare independently frozen expected text, length, domain hex, canonicalize 3.0.0 bytes, and digest. Expected constants are not generated by the implementation under test.
14. Node and address observations
The observer uses only the pinned Moss public node shape:
capability node: kind, protocol, method, params, children
It records capabilityNodes, transactionNodes, and totalNodes. A valid tree with actual counts different from synthetic expected counts returns nodeCount.status UNEXPECTED with both values. It is not silently repaired or converted into Decision output. A malformed tree returns SOURCE_CONTRACT_VIOLATION.
Transaction targets are parsed as EIP-55 identifiers and retained in stable first-observed and deterministic deduplicated forms. Comparison is only against synthetic expectedTransactionTargets. Status is EXPECTED or UNEXPECTED, never approved, safe, authorized, or permitted.
No production or real-chain address is introduced. Requiring one is a stop condition and a future Maintainer-owned address authority task.
15. Complete test matrix
amount.test.ts:
1 MON and 10^18 in both directions
one smallest unit
decimals 0
uint256 maximum and overflow
representative exact round-trips
zero, sign, whitespace, exponent, leading zero, decimal smallest-unit input
human excess precision rejected before parseUnits
no JavaScript Number amount path
no input mutation
capability.test.ts:
valid synthetic SELECTED result with exactly one matching ELIGIBLE outcome
direct createSelectedQuoteDigest reuse and exact selected digest match
stable INVALID_INPUT / simulate with no cause or sensitive text
existing action and simulation evidence layering remains unchanged
contracts.test.ts:
only SELECTED is accepted statically
only SYNTHETIC_TEST policy is representable
result discriminants and integrity states narrow correctly
MossPort keeps five unchanged methods
no validator or helper becomes a runtime package export
public-entry.smoke.mjs and server-only.test.ts:
Node 22 package-root import succeeds
exact runtime export set adds only constructCapabilityV0_1
type-only exports are absent at runtime
browser import remains blocked by server-only
no raw Capability, synthetic policy, validator, Moss, or secret-capable code leaks into the browser bundle
All test values, addresses, ProtocolIds, Quotes, and Capabilities are synthetic. They are not Moss, Monad, RPC, wallet, transaction, receipt, or real-chain evidence.
16. Determinism, ownership, and errors
The construction operation is offline except for one supplied MossPort.action call. It uses no RPC, wall clock, randomness, environment secret, or browser state.
For equal validated input and equal action-return JSON content, action input, authoritative snapshot bytes, digest, counts, and address observations are identical.
All caller values are treated as untrusted. Selection, quoteRequest, and policy are validated into adapter-owned values. The raw Moss object retains Moss ownership. Only Mini-Demo-owned snapshot and evidence wrappers are frozen.
Invalid caller input is stable MossAdapterError INVALID_INPUT / action before action delegation. Contradictory or malformed action evidence is SOURCE_CONTRACT_VIOLATION / action. Invalid current registered simulate input is INVALID_INPUT / simulate before simulator delegation. Integrity verification never throws raw validation details; it returns UNPROVABLE. No failure preserves cause or source-sensitive text.
claim that MATCH proves safety, authorization, execution success, or signing permission
Issue #28 remains solely responsible for invoking simulation in the product flow, preserving and mapping simulation evidence, and using the #27 guard before and after the exact call. A #28 contract change is not absorbed into #27.
18. Explicit non-goals
No #26 Quote collection, normalization, timeout, ranking, digest, outcome, or source-reference change.
No production address authority.
No Capability approval, safety conclusion, authorization, signing permission, execution guarantee, Alignment, Decision, STOP, MANUAL_REVIEW, or risk adjudication.
No simulation mapping or evidence construction.
No RPC, live chain, wallet, signing, transaction submission, receipt, backend, frontend, Web/API orchestration, database, deployment, or Clear402.
No report-schema, decision-engine, Moss source, git submodule, build-info, workflow, branch protection, required check, governance document, Issue, Project, Milestone, Review, Ready, Merge Gate, or merge operation.
No real address, private key, API key, endpoint, Quote, simulation, receipt, or transaction evidence.
19. Implementation sequence after authorization
Only after explicit Maintainer authorization:
fetch origin and require exact origin/main
verify clean state
create only the approved branch and isolated worktree
add viem 2.55.11 and inspect the lockfile before source changes
add amount tests and strict conversion
add shared JSON-exact validator tests, including all four mandatory descriptor regressions
implement the single validator in integrity.ts
call that exact validator from verifyCurrentIntegrity and registered simulate
add per-port exact identity registration and fail-closed immediate validation
implement capability construction with the authoritative snapshot and direct createSelectedQuoteDigest reuse
add digest, ownership, mutation, count, and address tests
update only the authorized public-entry and server-only assertions
integrity verification and registered exact simulate input use the same single JSON-exact validator from integrity.ts;
the validator enforces trap-safe Reflect.ownKeys closure, string-only enumerable data descriptors for records, genuine dense arrays with only canonical indices and the standard length descriptor, Proxy rejection, graph/Unicode/JSON closure, and recursive descriptor-value inspection;
after a registered exact object passes validation, it reaches the binding synchronously by exact identity with no await, clone, normalization, replacement or getter invocation;
the four mandatory descriptor regressions cover non-enumerable own data, Symbol key, sparse array/hole and extra named array property; each must prove integrity UNPROVABLE, INVALID_INPUT / simulate, and zero simulator delegation;
Both must start from the exact authorized baseline. Builder may install only the authorized dependency and implement only the frozen v3 scope. Any baseline, path, dependency, export, validator, authority, #26 contract or #28 boundary change invalidates this authorization and requires a new Scope Gate.
This record authorizes implementation scope only. It is not QA PASS, Review approval, READY_TO_MERGE, Merge Gate or merge authorization. The implementation must be delivered as a Draft PR closing #27, obtain exact-head quality-gate SUCCESS and complete QA/review on the frozen head.
Issue #28 and later dependency-bound work remain Blocked. Issue #23 remains Ready/unassigned and does not consume the active P0 Builder slot.
Activity
feat: collect and deterministically select quotes (#73)
pillowtalk-Qy commentedon Aug 6, 2026
DEPENDENCY_GATE_CLEARED
Issue #26 has been squash-merged through PR #73 into
main@65753ada85156716e263b660eeab72c42d293431.97e2806d43caae1881adae9b1c620a2b79d8ce84main@a0f3a3e8605812c9f0997059b4a30ea7a736022cThe #26 merged dependency is satisfied. Issue #27 may begin planning from this exact latest-main baseline.
Ready means dependency-ready only. It is not
SCOPE_CONFIRMED, implementation authorization, QA, Maintainer Review,READY_TO_MERGE, or merge authorization. A closed Work Plan must be submitted and receive a separate Maintainer Scope Gate before any implementation branch, worktree, code change, commit, or PR is created. Issue #27 must not alter the already merged #26 Quote-selection contract outside a separately approved boundary.pillowtalk-Qy commentedon Aug 6, 2026
BUILDER_CLAIM / WORK_PLAN_REQUIRED
Maintainer assigns the single active P0 planning slot to
pillowtalk-Qyfor Issue #27.origin/main@65753ada85156716e263b660eeab72c42d293431SCOPE_CONFIRMED:codex/issue-27-capability-integritySCOPE_CONFIRMED:/Users/qy/Documents/moss-mini-demo-issue-27Project
In Progressrecords planning ownership only. It does not authorize creating the branch/worktree, changing repository files, committing, opening a PR, requesting review, or entering a Merge Gate. Builder must wait for an explicit MaintainerSCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZEDrecord.Issue #23 remains Ready/unassigned and must not consume this P0 Builder slot. Issue #28 and later dependency-bound work remain Blocked.
pillowtalk-Qy commentedon Aug 6, 2026
Final Implementation Work Plan v1 - M2-06 Capability Construction, Amount Conversion, and Integrity - Awaiting Maintainer Scope Confirmation
1. Authority, state, and exact baseline
This is a planning-only Work Plan for Issue #27. It is submitted under the planning authorization recorded in:
Exact planning baseline:
At publication time Issue #27 is Open, assigned to pillowtalk-Qy, Project In Progress, and there are no open PRs. Project In Progress records planning ownership only.
Proposed implementation branch after authorization:
Proposed isolated worktree after authorization:
This comment requests a new Maintainer Scope Gate. It does not claim SCOPE_CONFIRMED or IMPLEMENTATION_AUTHORIZED. No branch, worktree, repository file, dependency, lockfile, commit, or PR may be created until an explicit Maintainer record grants both.
2. Exact-main contract and trust-boundary facts
The plan is based on these facts from the exact baseline:
If any of these facts changes before implementation, or origin/main no longer equals the frozen baseline, implementation stops and a revised Scope Gate is required.
3. Single goal
Call Moss action for the already selected protocol, convert the selected smallest-unit input amount into the exact human decimal required by Moss, preserve the exact action-return Capability object, create a separately owned immutable snapshot, calculate the frozen capability digest, expose node-count and address observations, and provide an integrity guard that can prove whether the exact raw object still matches the pre-simulation digest.
This work constructs and observes Capability evidence. It does not decide whether execution is safe, approved, authorized, guaranteed, or permitted to sign.
4. Closed writable path set
Exactly these 15 paths are requested. No wildcard is implied.
Path responsibilities:
The following are explicitly not writable: root package.json, pnpm-workspace.yaml, any report-schema path, any quote-selection source or test, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README files, and all Issue #28 files.
A need for a sixteenth path is a stop condition and requires a replacement closed plan.
5. Dependencies and supply-chain boundary
One new direct dependency is requested:
It is added only to packages/moss-adapter/package.json. The lockfile may add the exact viem 2.55.11 resolution and the transitive graph selected by pnpm 11.16.0. It must not refresh unrelated importers or versions.
Existing canonicalize 3.0.0 remains the RFC 8785 implementation. Existing Node SHA-256 support remains the hash implementation. No second canonicalization or hashing package is added.
No new install or build-script permission is authorized. pnpm-workspace.yaml and its current allowBuilds policy remain unchanged. The lockfile diff must be reviewed for unexpected lifecycle-script permissions or unrelated churn before commit.
No direct dependency on legacy @themoss/core, no copy of vendor/moss source, and no change to the pinned Moss submodule are allowed.
6. Exact public API change
The only new runtime export from @moss-mini-demo/moss-adapter is:
Exact planned signature:
The only new type exports are:
No amount helper, canonicalization helper, digest helper, tree walker, address helper, class, Schema, error class, or alternate package subpath is public. MossPort keeps the same five methods and the same TypeScript method signatures. Existing runtime exports are unchanged.
The public import smoke test must prove that the package root exposes exactly the existing runtime exports plus constructCapabilityV0_1. Type-only exports must not appear at runtime.
7. Strict input and selected-quote association
The operation accepts SELECTED only at compile time and validates all runtime values as untrusted input. A cast NOT_SELECTED object, throwing getter, hostile Proxy, revoked Proxy, cyclic object, unsupported prototype, lone surrogate, or unexpected key fails before port.action is called.
The implementation takes an adapter-owned clone of selection, quoteRequest, and policy. It never relies on a caller-owned property after validation.
It must locate exactly one ELIGIBLE outcome whose protocolId equals selection.selected.protocolId. The selected digest must match a fresh RFC 8785 digest of that exact eligible outcome under the already merged #26 digest contract. The following values must agree across quoteRequest, matching normalized outcome, selected digest payload, catalog snapshot, and policy where applicable:
Zero or multiple matching ELIGIBLE outcomes, any mismatch, a changed selected digest, an unknown catalog entry, unknown decimals, a stale catalog, or an unauthorized protocol/asset fails with the existing stable MossAdapterError boundary before action delegation. Invalid caller input uses INVALID_INPUT with operation action. A malformed or contradictory adapter/source result uses SOURCE_CONTRACT_VIOLATION with operation action. Neither error contains cause, source messages, URLs, headers, accounts, parameters, secrets, or raw payloads.
This validation does not re-run quote selection, alter ranking, rename deterministic candidate selection as a best trade, or modify #26 outcomes.
8. Amount contract and viem boundary
The report and selected-quote amount is a canonical positive smallest-unit base-10 integer string:
Decimals are taken from the matching immutable #26 catalog snapshot, not from token symbol, UI input, Quote prose, or a guessed default. Decimals must be an integer in the already merged catalog range 0 through 255. Unknown decimals fail closed.
The Moss action amount is the canonical human decimal returned by:
The implementation must then require:
Both functions are imported from the public viem 2.55.11 entry. A local hand-written decimal converter is forbidden.
Any external human decimal accepted by an internal validator is checked before parseUnits. The strict grammar rejects signs, exponent form, whitespace, empty integer/fraction components, redundant leading zeros, trailing decimal points, and more fractional digits than decimals. This precheck is mandatory because viem may round excess fractional precision; #27 must reject excess precision rather than round it.
Frozen examples:
The action input is a new adapter-owned ordinary object. It preserves validated protocol-specific additional quoteInput.params fields, replaces inputAsset and outputAsset with the validated canonical assets, and replaces amountIn with the derived human decimal. Method and account come from the validated quote request. The source quote request is not modified.
9. Maintainer-approved catalog and address source
Asset identity remains structural:
CapabilityConstructionPolicyV0_1 is a strict server-owned policy input, never request-body data. It contains:
Production composition may use MAINTAINER_APPROVED only when the referenced tracked record exists at the stated commit and contains the same addresses. SYNTHETIC_TEST is accepted only in tests and is never represented as production approval or real-chain evidence.
Current main has no such production address record. Therefore this Work Plan does not invent an address, infer one from a symbol, copy an address from Moss code, or add a hidden list. The requested Scope Gate must confirm that this injected, immutable-source policy is the approved #27 boundary. If Maintainer instead requires a repository address record to be added now, this 15-path plan is insufficient and implementation must stop for a revised path list and contract.
10. Exact raw identity, owned snapshot, and simulator handoff
For a successful Moss action:
source-bindings.ts may maintain a per-port private WeakSet of exact objects returned by that same port action call. When the same registered object is supplied to that same port simulate method, the binding receives that exact object without a clone. An unregistered, cross-port, hostile, revoked, or invalid simulate input retains the current defensive snapshot-and-validation behavior and never reaches the binding on validation failure. The WeakSet is private, is not a public API, and does not keep objects alive.
This is the only simulate-related change in #27. It establishes identity transport. It does not interpret or map simulation output.
CapabilityConstructionResultV0_1 also exposes a bound verifyCurrentIntegrity operation. It recomputes the capability digest from the current exact raw object and returns one of:
The bound operation does not freeze or mutate the raw object. #28 must call it immediately before and after using simulatorInput. The #27 tests call the existing port simulate only to prove identity and post-call MATCH. If the source simulator mutates the object, the post-call result is MISMATCH. No simulation receipt, outcome, warning, coverage, ordering, continuity, block, or Decision data is produced.
11. Snapshot, tree, and address observations
The independent snapshot preserves the entire raw action-return Capability, including unknown JSON fields. No raw node or field is dropped from the snapshot or digest.
The observer follows the pinned Moss node discriminants:
It records exact nonnegative safe-integer counts:
The policy requires expected values whose total equals capabilityNodes plus transactionNodes. A valid tree with different actual counts remains observable as nodeCount.status UNEXPECTED with both expected and actual values. It is not silently repaired, discarded, or converted to a STOP decision in #27. A malformed tree fails as SOURCE_CONTRACT_VIOLATION; it is not presented as valid Capability evidence.
Transaction addresses are parsed as EIP-55 identifiers and retained in stable first-observed order plus a deterministic deduplicated observation. The result records EXPECTED or UNEXPECTED and identifies unexpected targets without declaring safety. Source account and target addresses are not logged in errors.
Node-count or address mismatch does not authorize execution and does not become Alignment or Decision output in this Issue. Those observations remain evidence for downstream fail-closed handling.
12. Frozen RFC 8785 and SHA-256 byte contract
Digest contract:
The domain is exactly 31 UTF-8 bytes. It ends with one LF byte 0a. There is no CR, NUL, BOM, JSON quoting, length prefix, or extra separator.
Domain UTF-8 hex:
The snapshot and raw action return have byte-equivalent canonical content at acquisition time. The digest is calculated from the independent acquisition snapshot so later mutation of the original cannot rewrite recorded evidence. verifyCurrentIntegrity canonicalizes the current original separately.
Capability-specific golden raw value:
Expected canonical text, as one byte-exact line:
Frozen lengths and digest:
Tests must compare independently frozen expected text, lengths, domain hex, and digest. They must also prove canonicalize 3.0.0 produces the expected canonical text bytes. The expected digest must not be generated by the implementation under test.
Non-finite numbers, cycles, unsupported prototypes, throwing getters, Proxy failures, and lone surrogates are rejected or reported UNPROVABLE through stable secret-safe behavior. No approximate key sorter is allowed.
13. Test matrix
amount.test.ts:
capability.test.ts:
production.test.ts and fake.test.ts:
contracts.test.ts:
public-entry.smoke.mjs and server-only.test.ts:
All tests use synthetic identifiers and payloads only. They do not use a real Moss endpoint, Monad RPC, wallet, key, API key, transaction, receipt, quote, or chain evidence.
14. Determinism, ownership, and mutation rules
The operation is offline except for the supplied MossPort.action call. It does not read RPC, wall-clock data, random values, environment secrets, or browser state.
For identical validated selection, quote request, policy, and action-return JSON content:
All caller inputs are cloned before use and never modified. Raw Moss ownership stays with Moss. Snapshot and derived wrappers are owned by Mini-Demo. Only Mini-Demo-owned values are frozen. No operation mutates #26 outcomes, selected digest payload, quote request, policy, action return, or simulation return.
15. Strict #28 isolation
Issue #27 may:
Issue #27 must not:
#28 remains responsible for calling the simulator in the product flow, mapping the output, and invoking the #27 integrity guard before and after that exact call.
16. Non-goals
No Quote collection or deterministic selection change.
No selected Quote versus Capability cryptographic binding beyond recording the selected digest in construction evidence.
No Capability safety assessment or authorization.
No simulation mapping.
No Alignment, Decision, STOP, or MANUAL_REVIEW behavior.
No Web/API orchestration.
No RPC or live-chain access.
No wallet, signing, transaction construction, submission, or receipt handling.
No Clear402.
No frontend or backend feature.
No real address or real-chain Fixture.
No report-schema or Decision Engine change.
No Moss fork, submodule, source, build-info, or pin change.
No workflow, branch protection, required check, Issue, Project, Milestone, permission, review, ready, merge-gate, or merge operation.
17. Implementation sequence after authorization
18. Clean-checkout verification
Use exactly Node 22.23.1 and pnpm 11.16.0 from a fresh isolated worktree with no dist directories:
Acceptance:
19. Risks and rollback
Risks:
Controls are the strict prevalidator, BigInt-only values, independent frozen snapshot, current-integrity verifier, per-port WeakSet, byte-level vectors, explicit mismatch observations, synthetic-only tests, and exact path/dependency checks.
Rollback is one feature-branch revert before merge. No migration, database, deployment, chain state, transaction, or secret is created. If the public shape or address source is rejected, discard the branch rather than retaining a compatibility alias or partial implementation.
20. Stop conditions
Stop without implementation or further mutation if:
21. Maintainer confirmation requested
Please record SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED only if all of the following are accepted:
Until that record exists, status is:
pillowtalk-Qy commentedon Aug 6, 2026
SCOPE_CHANGES_REQUESTED
Frozen Scope Gate object:
5205821730updated_at:2026-08-06T14:11:54Z65753ada85156716e263b660eeab72c42d293431The 15-path list, sole proposed direct dependency
viem@2.55.11, BigInt-only amount boundary, #26 file exclusion, and explicit #28 isolation are directionally closed. The frozen capability vector was independently recomputed and matches the plan exactly: 31-byte domain, 306-byte canonical text, 337-byte digest input, andsha256:0d251a152143187d0a50d9481330aef30fbf5ee03a011be2f936e5805ee9ad89.Scope is not authorized because the following trust-boundary gaps remain.
1.
MAINTAINER_APPROVEDis currently caller-asserted, not authority-backedThe proposed public operation receives
CapabilityConstructionPolicyV0_1from its caller. A structurally valid object containingMAINTAINER_APPROVED, repository, commit and recordPath does not prove that a Maintainer approved those addresses.Current main contains no tracked production address-authority record, and the proposed 15 paths contain neither such a record nor a verifier anchored to one. A runtime shape check can therefore validate metadata syntax while accepting a fabricated authority claim.
SERVER_CONFIGUREDcatalog provenance must not be treated as Maintainer approval.A revised plan must choose and fully specify one fail-closed contract:
MAINTAINER_APPROVEDproduction claim until that trust anchor exists.If production authority remains supported, tests must reject nonexistent records, wrong repository/commit/path, content/digest mismatch, unapproved roles/addresses, duplicate or contradictory entries, and caller-supplied metadata that merely claims approval. Any new record or loader path must be included in a replacement closed writable-path list.
2. The authoritative acquisition snapshot is ambiguous
Current main already creates the independent frozen Mini-Demo snapshot inside the action source boundary before
MossPort.actionreturns:https://github.com/Moss-Mini-Demo/moss-mini-demo/blob/65753ada85156716e263b660eeab72c42d293431/packages/moss-adapter/src/source-bindings.ts#L460-L478
The plan separately says to clone again “immediately after action return” and calls that the acquisition snapshot. Because the raw Moss object remains mutable, a later clone cannot silently replace or redefine the earlier source-boundary evidence.
The revised plan must name one authoritative acquisition snapshot and ordering. Prefer reusing
RawCapabilityEvidence.miniDemoDerived.snapshot, or explicitly move the atomic capture/digest boundary. It must require a fail-closed comparison between that immutable acquisition evidence and the current exact raw object before returning successful construction evidence. The recorded digest and all wrappers must remain explicitlyMINI_DEMO_DERIVED; the raw object remainsMOSS_ORIGINAL. Add a mutation-between-boundaries regression test.3. WeakSet membership does not prove current input validity
Current
simulatedefensively snapshots and validates before delegation:https://github.com/Moss-Mini-Demo/moss-mini-demo/blob/65753ada85156716e263b660eeab72c42d293431/packages/moss-adapter/src/source-bindings.ts#L483-L491
The proposed same-port WeakSet proves identity/provenance only. A registered raw object may be mutated after action acquisition into a cycle, accessor/throwing getter, unsupported prototype, lone surrogate, non-finite value or otherwise invalid payload. Membership must not bypass the hostile-input boundary.
The revised plan must require non-cloning current-value validation immediately before delegation for a registered object. Valid registered input must reach the binding by exact identity; invalid registered input must fail before delegate count changes. Add explicit registered-after-mutation tests for each hostile class.
verifyCurrentIntegrityreturningUNPROVABLEis not sufficient enforcement becauseMossPort.simulateremains independently callable.4. #26 selected-digest verification must reuse the merged contract
Current main owns the exact selected payload and digest construction in
createSelectedQuoteDigest:https://github.com/Moss-Mini-Demo/moss-mini-demo/blob/65753ada85156716e263b660eeab72c42d293431/packages/moss-adapter/src/quote.ts#L464-L493
The revised plan must explicitly reuse this existing internal helper against the unique matching ELIGIBLE outcome, rather than copy a second selected-Quote payload/canonicalization implementation into #27. This preserves the #26 Quote contract and prevents drift while keeping quote-selection files read-only.
Required next step: publish a replacement Work Plan that resolves all four items and restates the exact path/dependency set. Do not edit the frozen v1 comment in place.
No
SCOPE_CONFIRMEDorIMPLEMENTATION_AUTHORIZEDis granted. Do not create the #27 branch/worktree, modify files, commit, or open a PR. Issue #28 and later dependency-bound work remain Blocked; Issue #23 remains Ready/unassigned.pillowtalk-Qy commentedon Aug 6, 2026
Final Implementation Work Plan v2 - M2-06 Capability Construction, Amount Conversion, and Integrity - Scope Changes Resolved
1. Status, history, and authority
This is a new, planning-only replacement proposal for Issue #27. Work Plan v1 remains immutable historical record:
#27 (comment)
The v1 Scope Gate response is preserved here. Its status is SCOPE_CHANGES_REQUESTED:
#27 (comment)
v1 is not edited or deleted. This v2 supersedes v1 for any future implementation discussion only. It does not grant implementation authority.
The exact planning baseline remains:
At this re-check, Issue #27 is Open, assigned to pillowtalk-Qy, Project In Progress, and no PR is open. The dependency gate records #26 merged into this exact main. Project status and assignment do not authorize implementation.
The proposed branch and worktree are still only names:
They have not been created. Until a separate Maintainer comment explicitly says SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED, the Builder must not create them, modify files, install dependencies, update a lockfile, commit, push, open a PR, request review, enter Merge Gate, or merge.
2. Four trust-boundary resolutions
2.1 No caller-asserted production authority in this release
The v1 MAINTAINER_APPROVED policy branch is removed. v2 is explicitly synthetic-only.
CapabilityConstructionPolicyV0_1 has exactly:
It has no MAINTAINER_APPROVED discriminator and no field that can claim Maintainer authorization. Production input is rejected, including a cast object with provenance MAINTAINER_APPROVED, SERVER_CONFIGURED catalog provenance, pinned-submodule Moss provenance, an invented repository/commit/path, or a caller-supplied approval string.
The policy sourceReference must use the synthetic test grammar and is evidence of test construction only. expectedTransactionTargets are synthetic expected observations, not approved protocol, spender, token, or destination addresses. They never authorize a call, signing, execution, or real-chain action.
The selected catalog must have provenance SYNTHETIC_TEST and the matching selected outcome and action source must have SYNTHETIC_FAKE provenance. SERVER_CONFIGURED catalog entries and PINNED_SUBMODULE action provenance fail closed in this release.
The current main has no tracked production address-authority record. v2 therefore does not invent one or add one implicitly. A future production release requires a new Scope Gate with a precise Maintainer-owned record path, format, immutable revision, content digest, loader, and verification tests. That future work is outside this v2 and is a stop condition.
2.2 One authoritative acquisition snapshot
The authoritative acquisition snapshot is the object already produced inside the existing source boundary:
source-bindings.ts creates this independent structured clone and deep freeze before MossPort.action returns. v2 reuses that exact snapshot by identity. capability.ts must not clone the raw object again and must not create a second competing acquisition snapshot.
The construction sequence is fixed:
A regression test mutates or replaces the raw value between source-boundary snapshot creation and capability construction. The mismatch must be observed and must not produce a successful result. The raw Moss object remains MOSS_ORIGINAL, while every snapshot, digest, count, and wrapper is MINI_DEMO_DERIVED.
2.3 WeakSet membership never bypasses current validation
The private per-port registration set records provenance only. It is not a validity grant.
Immediately before delegating a registered object to MossSourceBindings.simulate, source-bindings.ts must perform non-cloning current-value validation. The validator:
A registered and currently valid object reaches the binding by exact identity. A registered object that was changed after action acquisition fails with INVALID_INPUT, operation simulate, before delegate count changes. No cause, raw exception, source message, URL, header, account, parameter, or secret is exposed.
The explicit regression matrix mutates a registered action-return object into each of these cases:
Each case must have zero simulate-binding calls. Unregistered valid input retains the existing defensive owned-snapshot path. Cross-port objects are unregistered and never receive exact forwarding.
2.4 Reuse the merged #26 selected digest contract
The merged #26 helper remains the sole selected-Quote digest constructor:
capability.ts imports this existing internal helper and calls it exactly once for the unique matching ELIGIBLE outcome. It does not copy the selected payload field list, canonicalization call, or hash implementation. quote.ts and selection.ts remain read-only.
The helper output is compared byte-for-byte with selection.selected.digest, including algorithm, serialized lowercase SHA-256 value, and canonical payload content. A mismatch fails before action delegation. This preserves #26 semantics and makes future changes to the merged helper visible to #27 instead of allowing a shadow implementation.
3. Goal and explicit product boundary
Call Moss action for a validated, already selected synthetic protocol; convert smallest-unit amount to Moss human decimal; retain the exact action-return Capability; reuse the existing immutable acquisition snapshot; calculate the fixed RFC 8785 plus SHA-256 integrity digest; expose non-decisional node and target observations; and expose a current-integrity guard for #28.
This is synthetic development evidence and adapter integrity infrastructure only. It is not an application, protocol integration, wallet, authorization, safety conclusion, real-chain evidence, signing permission, execution guarantee, or Decision result.
4. Exact closed writable paths
Exactly 15 paths are authorized by this proposal. No wildcard, directory-wide, or “approved skeleton” is implied.
Path responsibilities:
Explicitly not writable: root package.json, pnpm-workspace.yaml, every report-schema path, quote.ts, selection.ts, asset-catalog.ts, quote-selection tests, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README or other documentation, and all Issue #28 paths.
A sixteenth path is a hard stop and requires another replacement Work Plan.
5. Dependency and package boundary
The only new direct dependency is:
Existing dependencies remain unchanged. canonicalize 3.0.0 remains the only RFC 8785 implementation. Node built-in SHA-256 remains the only hash primitive. No dependency is copied into vendor/moss, and legacy @themoss/core is not added.
The lockfile may add only the viem 2.55.11 importer and the registry-resolved viem graph selected by pnpm 11.16.0. It must not refresh unrelated versions. No new install script or build-script permission is allowed; pnpm-workspace.yaml and its current sharp policy remain byte-for-byte unchanged.
6. Public API and type contract
Only one new runtime export is added from the package root:
Its exact planned signature is:
Only these new type names are exported:
CapabilityConstructionPolicyV0_1 is a closed synthetic-only object containing schemaVersion 0.1, policyId, sourceVersion, provenance SYNTHETIC_TEST, synthetic sourceReference, chainId 143, selected catalog digest, exactly one protocolId, exact input/output assets, expected capability/transaction/total node counts, and synthetic expected transaction targets with explicit roles.
CapabilityConstructionResultV0_1 is a closed result containing:
The result must not contain approval, authorization, safety, execution, signing, Decision, STOP, MANUAL_REVIEW, simulation-success, receipt, or RPC claims.
MossPort retains exactly five methods with unchanged signatures. No helper, Schema, digest function, address loader, class, alternate package entry, or sixth method is public.
7. Input validation and selected outcome association
All four arguments are untrusted runtime values even though TypeScript narrows the selection to SELECTED. Validation is performed against adapter-owned data before action delegation. A cast NOT_SELECTED value, unexpected key, accessor, hostile or revoked Proxy, unsupported prototype, cycle, non-finite number, lone surrogate, stale catalog, or contradictory digest fails with INVALID_INPUT and zero action calls.
The validator requires exactly one ELIGIBLE outcome with protocolId equal to selection.selected.protocolId. It calls createSelectedQuoteDigest on that owned unique outcome and compares the resulting algorithm, payload bytes, and serialized digest to selection.selected.digest. It then requires agreement across quoteRequest, the outcome, catalog snapshot, and synthetic policy for:
Only the matching synthetic catalog and SYNTHETIC_FAKE source are accepted. Zero or multiple matches, any disagreement, unknown asset, unknown decimals, stale validity window, or policy mismatch fails before port.action.
The action request is adapter-owned, preserves validated additional quote parameters, replaces only the canonical asset fields and amountIn, and never mutates quoteRequest or selection.
8. Exact amount conversion
The smallest-unit amount is a positive canonical decimal string, parsed only with BigInt, in the inclusive range 1 through 2^256 - 1. JavaScript Number is prohibited for amount values.
Decimals are the known integer from the matching #26 catalog snapshot, range 0 through 255. No symbol, UI value, Quote prose, or inferred default can supply decimals. Unknown assets and decimals fail closed.
The Moss action amount is:
The implementation must check:
Both functions come only from viem 2.55.11. A strict pre-validator rejects signs, whitespace, exponent notation, empty components, redundant leading zeroes, trailing decimal points, and any fractional precision above decimals before calling parseUnits. This prevents viem rounding from accepting a lossy value.
Required vectors include 1 MON and 10^18, one smallest unit, decimals 0, uint256 maximum, exact round-trip, zero, uint256 overflow, malformed integer strings, and excess human precision.
9. Authoritative snapshot and exact identity
source-bindings.ts remains the only acquisition boundary. It keeps the exact Moss action-return object at mossOriginal.value and creates the one authoritative deeply frozen snapshot at miniDemoDerived.snapshot before MossPort.action returns.
constructCapabilityV0_1 reuses that snapshot by identity. It does not clone again, replace it, or freeze the raw object. It separately validates and canonicalizes the current raw object and requires equality with the authoritative snapshot before successful return. A mutation between the source-boundary snapshot and construction fails closed with SOURCE_CONTRACT_VIOLATION.
The construction result labels the raw object MOSS_ORIGINAL and all snapshot/digest/observation wrappers MINI_DEMO_DERIVED. Unknown JSON fields are retained in the snapshot and participate in the digest.
The private per-port registration set records exact raw objects returned by action. It proves provenance only. Immediately before a registered object reaches the simulate binding, a synchronous non-cloning validator walks the current value and:
A valid registered object reaches the binding by exact identity with no await or clone between final validation and invocation. An invalid registered object fails with INVALID_INPUT, operation simulate, and zero delegate calls. Unregistered valid input follows the existing defensive clone path. Cross-port objects are unregistered.
The regression matrix mutates a registered object into cycle, throwing accessor, hostile Proxy, revoked Proxy, unsupported prototype, non-finite value, and lone-surrogate cases. Every case is rejected before delegation.
10. Integrity digest contract
The digest is calculated from the authoritative frozen snapshot:
The domain is exactly 31 UTF-8 bytes ending in one LF byte 0a. There is no CR, NUL, BOM, JSON quoting, length prefix, or extra separator.
Domain bytes:
Golden synthetic raw Capability:
Expected canonical text is the byte-exact one-line value:
Frozen vector:
Tests compare independent expected text, lengths, domain hex, canonicalize 3.0.0 output bytes, and digest. They do not generate the expected value from the implementation under test. Invalid Unicode, cycles, accessors, Proxy traps, unsupported prototypes, and non-finite values fail closed without raw error text.
11. Node and address observations
The observer uses only the pinned Moss public node shape:
It records capabilityNodes, transactionNodes, totalNodes, and compares them with the synthetic policy expected values. A valid tree with a mismatch returns nodeCount.status UNEXPECTED with expected and actual counts. A malformed tree returns SOURCE_CONTRACT_VIOLATION and is never presented as valid evidence.
Transaction targets are parsed as EIP-55 addresses and retained in deterministic first-observed and deduplicated forms. They are compared only with synthetic expectedTransactionTargets. The result can say EXPECTED or UNEXPECTED; it cannot say approved, safe, authorized, or permitted.
No production address, real chain address, token, spender, protocol, or wallet address is added. A future production address authority requires a separate Scope Gate and a tracked Maintainer-owned record with immutable revision and content verification.
12. Determinism and ownership
The operation is offline except for the one supplied MossPort.action call. It uses no RPC, wall clock, randomness, environment secret, browser state, or Number-based amount path.
For identical validated inputs and identical action-return JSON content, action input, snapshot bytes, digest, counts, and address observations are identical. All inputs are cloned before use and no caller-owned input is mutated. Only Mini-Demo-owned snapshots and wrappers are frozen. The raw Moss object remains mutable and original.
verifyCurrentIntegrity recomputes current raw content independently:
Mutation changes the current computed digest or makes it UNPROVABLE; it never changes the recorded snapshot or digest.
13. Complete test matrix
amount.test.ts covers:
capability.test.ts covers:
production.test.ts and fake.test.ts cover the per-port registration boundary, valid exact forwarding, defensive unregistered input, cross-port rejection, all registered-after-mutation hostile classes, zero delegate calls on invalid values, no cause, and no sensitive text.
contracts.test.ts covers the two new type exports, SELECTED-only narrowing, synthetic-only policy union, result discriminants, unchanged five-method MossPort, and absence of any additional runtime helper.
public-entry.smoke.mjs and server-only.test.ts prove Node 22 public-root import, exactly one added runtime export, type-only exports absent at runtime, and no browser bundle leakage.
All inputs are synthetic. No real Moss, Monad, RPC, wallet, key, API key, transaction, receipt, Quote, or chain evidence is used.
14. Strict Issue #28 boundary
#27 may change only the exact action-to-simulate identity transport, expose simulatorInput, and expose verifyCurrentIntegrity for pre/post-use checks. It may use synthetic simulate calls in tests only.
#27 must not acquire production simulation, map RawSimulationEvidence, define simulation request/response contracts, create Receipt, Outcome, Warning, Coverage, Ordering, StateContinuity, block, RPC, provider, Alignment, Decision, STOP, or MANUAL_REVIEW evidence, or claim simulation success from digest equality.
#28 remains responsible for calling the simulator in the product flow, mapping simulation output, preserving simulation evidence, and deciding how pre/post integrity failure affects its own contract.
15. Explicit non-goals
No change to #26 quote collection, normalization, ranking, timeout, selected digest, or source references.
No Capability safety, authorization, approval, signing permission, execution guarantee, Decision, STOP, MANUAL_REVIEW, or risk adjudication.
No production address authority.
No RPC, live chain, wallet, signing, transaction submission, receipt, backend, frontend, Web/API orchestration, database, deployment, or Clear402.
No report-schema, decision-engine, Moss source, submodule, build-info, workflow, dependency policy, branch protection, required check, governance document, Issue, Project, Milestone, review, ready, Merge Gate, or merge change.
16. Implementation and clean-checkout verification after approval
Only after Maintainer authorization:
fetch origin and require exact origin/main baseline
create the proposed branch and isolated worktree
add viem 2.55.11 and inspect only its lockfile graph
implement amount boundary and tests
implement source-boundary identity registration and current validation
implement capability construction by reusing createSelectedQuoteDigest
implement snapshot comparison, digest, observations, and integrity guard
update only the public-entry and server-only assertions
inspect exact path diff and run:
node --version
pnpm --version
pnpm install --frozen-lockfile
pnpm --filter @moss-mini-demo/report-schema build
pnpm --filter @moss-mini-demo/moss-adapter build
pnpm --filter @moss-mini-demo/moss-adapter typecheck
pnpm exec vitest run packages/moss-adapter/test/amount.test.ts
pnpm exec vitest run packages/moss-adapter/test/capability.test.ts
pnpm exec vitest run packages/moss-adapter/test
pnpm test:package-import
pnpm check
pnpm test:web:bundle
pnpm test:web:production
git diff --check origin/main...HEAD
git diff --name-only origin/main...HEAD
git status --short
Acceptance requires Node 22.23.1, pnpm 11.16.0, frozen install from no dist, all tests green, exactly the 15 paths, only viem 2.55.11 direct addition, no unrelated lockfile churn, public package smoke success, exact identity, independent snapshot, golden digest, amount boundaries, hostile registered-input rejection, no #28 mapping, and exact-head quality-gate SUCCESS.
17. Risks, rollback, and stop conditions
Risks are viem excess-precision rounding, raw-object mutation, identity forwarding without current validation, canonicalization failure, misleading node/address observations, accidental #28 absorption, and unrelated lockfile churn.
Controls are strict prevalidation, synthetic-only policy, existing source-boundary snapshot reuse, current-value non-cloning validation, BigInt-only conversion, existing canonicalize helper, exact byte vectors, per-port registration, no sensitive errors, and exact path/dependency review.
Rollback is a feature-branch revert before merge. No deployment, chain state, transaction, database, or secret is created.
Stop immediately and request a revised Scope Gate if:
18. Maintainer Scope Gate request
Please leave a new explicit SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED record only if all of the following are accepted:
Until that explicit record exists:
pillowtalk-Qy commentedon Aug 6, 2026
SCOPE_CHANGES_REQUESTED - Work Plan v2
Frozen review object:
5206053438updated_at:2026-08-06T14:30:42Zc70046d4df0734e6ea99ee8fbb3b075a385c171d68e626da556c4d8114cde7b165753ada85156716e263b660eeab72c42d293431The following v1 blockers are resolved:
SYNTHETIC_TESTonly and rejects every production/approval claim;miniDemoDerived.snapshotis the sole authoritative acquisition snapshot;createSelectedQuoteDigesthelper;viem@2.55.11direct dependency and strict M2-07: Implement simulation and lossless evidence mapping #28 isolation remain closed.One trust-boundary blocker remains, so implementation is not authorized.
Registered exact input is not yet JSON-descriptor closed
Section 2.3 requires the current-value validator to “walk own enumerable data values.” That is insufficient for an exact raw object that is forwarded unchanged to the simulator.
A registered object can be mutated after acquisition with:
RFC 8785 / JSON serialization and the proposed enumerable-value walk can ignore or normalize that state, while the underlying simulator receives the exact object and can still observe it. The recorded snapshot/current digest can therefore remain
MATCHeven though the simulator-visible object contains state that was never represented by the Mini-Demo evidence. WeakSet membership does not close this gap.A replacement Work Plan must require one shared JSON-exact current-value validator for both
verifyCurrentIntegrityand the registered simulate path:Reflect.ownKeysunder trap-safe handling;lengthdescriptor, reject holes, Symbols, extra named properties, accessors and other non-enumerable properties;UNPROVABLEfrom integrity verification and failINVALID_INPUT / simulatewith zero delegate calls when the descriptor closure is violated.Add explicit registered-after-acquisition regression tests for non-enumerable data properties, Symbol keys, sparse arrays and extra array properties. Each must prove zero simulator delegation; the integrity check must not report
MATCH.Publish v3 as a new immutable comment; do not edit v2 in place. The path and dependency set may remain unchanged if this correction fits the existing authorized proposal paths.
No
SCOPE_CONFIRMEDorIMPLEMENTATION_AUTHORIZEDis granted. Do not create the #27 branch/worktree, installviem, modify files, commit, push, or open a PR. Issue #23 remains Ready/unassigned; Issue #28 and later dependency-bound work remain Blocked.pillowtalk-Qy commentedon Aug 6, 2026
Final Implementation Work Plan v3 - JSON-Exact Descriptor Boundary Closed - Awaiting Maintainer Scope Confirmation
1. Status, immutable history, and exact baseline
This is a new, complete, planning-only replacement Work Plan for Issue #27.
Work Plan v1 remains an immutable historical record:
#27 (comment)
Its Scope Gate response remains preserved:
#27 (comment)
Work Plan v2 also remains an immutable historical record:
#27 (comment)
Its Scope Gate response is SCOPE_CHANGES_REQUESTED and remains preserved:
#27 (comment)
Neither v1 nor v2 is edited or deleted. This v3 supersedes both only for future implementation discussion. It is a full self-contained plan, not a delta or patch note, and it does not authorize implementation.
The exact planning baseline was fetched again and remains:
Issue #27 remains Open, assigned to pillowtalk-Qy, Project In Progress, with no open PR. The proposed implementation resources remain names only:
They do not exist and must not be created before a new Maintainer comment explicitly records SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED.
2. Goal and product boundary
The only goal is to call Moss action for a validated already-selected synthetic protocol, convert the selected smallest-unit input amount to the exact human decimal required by Moss, preserve the exact action-return Capability object, reuse the one authoritative source-boundary snapshot, calculate the fixed Capability integrity digest, record non-decisional node and address observations, and expose a current-integrity check that #28 can use around exact-identity simulation.
This is synthetic development evidence and adapter integrity infrastructure only. It is not an application, production Moss or Monad integration, approval, authorization, safety conclusion, signing permission, execution guarantee, wallet behavior, real-chain evidence, or Decision result.
3. Exact-main trust-boundary facts
The v3 plan is bound to these facts from the exact baseline:
If any fact or origin/main changes before implementation, this Scope Gate expires and Builder stops.
4. Resolved trust-boundary decisions
4.1 Synthetic-only authority
CapabilityConstructionPolicyV0_1 has exactly:
There is no MAINTAINER_APPROVED branch and no field capable of claiming Maintainer authorization. The selected catalog must be SYNTHETIC_TEST and the action source must be SYNTHETIC_FAKE. SERVER_CONFIGURED catalog provenance, PINNED_SUBMODULE action provenance, MAINTAINER_APPROVED, invented repository/commit/path metadata, and caller-provided approval prose are rejected.
sourceReference identifies synthetic test construction only. expectedTransactionTargets are synthetic expectations, not approved protocol, spender, token, wallet, or destination addresses. A future production authority requires a separate tracked Maintainer-owned record, loader, immutable revision/digest verification, new closed paths, and a new Scope Gate.
4.2 One authoritative acquisition snapshot
The sole authoritative acquisition snapshot is:
It is created inside source-bindings.ts before MossPort.action returns. constructCapabilityV0_1 reuses that same snapshot by identity. It does not create, substitute, or relabel a second acquisition snapshot.
Before successful construction evidence is returned, current exact raw bytes and authoritative snapshot canonical bytes must agree. Mutation between source-boundary acquisition and construction fails with SOURCE_CONTRACT_VIOLATION. The exact raw object remains MOSS_ORIGINAL. Snapshot, digest, count, address, and wrapper evidence remain MINI_DEMO_DERIVED.
4.3 One shared JSON-exact validator
There is exactly one internal current-value validator implementation in integrity.ts. source-bindings.ts imports and invokes that same function for registered exact simulate input. verifyCurrentIntegrity invokes that same function before canonicalization.
No second validator, reduced validator, enumerable-only walker, JSON.stringify precheck, structuredClone substitute, or divergent simulate-only implementation is permitted.
The validator returns adapter-owned inspection data only after the complete object graph passes. It does not modify, freeze, clone, normalize, replace, or invoke a getter on the raw input.
4.4 Direct reuse of the merged #26 selected digest
capability.ts imports the existing internal createSelectedQuoteDigest from quote.ts and calls it for the unique matching ELIGIBLE outcome. It must not copy the selected payload list, canonicalizer, hash call, or serialization contract.
The fresh helper output is compared exactly with selection.selected.digest. quote.ts, selection.ts, asset-catalog.ts, and their tests remain read-only.
5. Closed writable path set
Exactly these 15 paths are requested. No wildcard or directory-wide permission is implied.
Path responsibilities:
Explicitly read-only: root package.json, pnpm-workspace.yaml, all report-schema paths, quote.ts, selection.ts, asset-catalog.ts, quote-selection tests, vendor/moss, .gitmodules, apps/web, workflow files, ADRs, README and other documentation, and every Issue #28 path.
The JSON-exact correction fits the existing integrity.ts, source-bindings.ts, and approved tests. No sixteenth path is requested. Requiring one is a stop condition.
6. Dependency and supply-chain boundary
The sole new direct dependency remains:
It is added only to packages/moss-adapter/package.json. pnpm-lock.yaml may add only the adapter importer change and the exact viem 2.55.11 transitive graph selected by pnpm 11.16.0. Unrelated lockfile refresh is prohibited.
Existing canonicalize 3.0.0 remains the sole RFC 8785 implementation. Existing Node SHA-256 support remains the sole hash primitive. Node built-in util.types.isProxy may be used to reject every Proxy without adding a dependency.
No install/build lifecycle permission is added. pnpm-workspace.yaml and its current sharp permission remain byte-for-byte unchanged. No legacy @themoss/core dependency, vendor source copy, Moss pin change, or second canonical/hash implementation is allowed.
7. Exact public API
The only new runtime package-root export is:
Exact signature:
The only new exported type names are:
CapabilityConstructionPolicyV0_1 is a closed synthetic-only object containing schemaVersion 0.1, policyId, sourceVersion, provenance SYNTHETIC_TEST, synthetic sourceReference, chainId 143, selected catalog digest, exactly one protocolId, canonical input/output assets, expected capability/transaction/total node counts, and synthetic expected transaction targets with explicit observation roles.
CapabilityConstructionResultV0_1 contains:
No public amount helper, validator, canonicalizer, digest helper, tree walker, address helper, error class, runtime Schema, alternate entry, or sixth MossPort method is added. MossPort signatures remain unchanged. Runtime smoke tests require the old exact export set plus constructCapabilityV0_1 only.
8. Strict selected-input association
All arguments are untrusted at runtime. The port shape is checked, and selection, quoteRequest, and policy are inspected into adapter-owned validated values before action delegation.
A cast NOT_SELECTED input, unexpected key, accessor, Symbol, non-enumerable property, sparse array, extra array property, hostile or revoked Proxy, unsupported prototype, cycle, repeated object alias, non-finite number, lone surrogate, stale catalog, or contradiction fails before action.
Exactly one ELIGIBLE outcome must match selection.selected.protocolId. createSelectedQuoteDigest is called for that exact outcome and must match selection.selected.digest in algorithm, canonical payload content, and lowercase serialized SHA-256 value.
The following must agree across the quote request, matching normalized outcome, selected digest, catalog snapshot, and synthetic policy:
Only SYNTHETIC_TEST catalog and SYNTHETIC_FAKE source are accepted. Zero/multiple matches, unknown asset/decimals, changed selected digest, or any disagreement produces existing secret-safe MossAdapterError before action, with delegate count zero.
The action input is an adapter-owned ordinary object. It preserves validated additional quoteInput.params fields, replaces only canonical inputAsset, outputAsset, and amountIn, and does not modify any input.
9. Amount conversion contract
The selected/report amount is a positive canonical smallest-unit decimal integer string:
Decimals come only from the matching immutable #26 catalog snapshot and must be known in the existing range 0 through 255. Symbol, UI input, prose, and guessed defaults are never decimals authorities.
The Moss action human amount is:
The implementation requires:
Both functions come only from viem 2.55.11. Before any parseUnits call, strict human-decimal grammar rejects signs, whitespace, exponent notation, empty components, redundant leading zeroes, trailing decimal point, and fractional precision greater than decimals. This prevents viem rounding from accepting a lossy value.
Required vectors include 1 MON with 10^18, one smallest unit, decimals 0, uint256 maximum, representative exact round-trips, zero, overflow, malformed strings, and excess precision.
10. JSON-exact validator contract
The single internal validator enforces the following recursively for the entire raw graph before either integrity canonicalization or registered exact simulate delegation.
10.1 Trap and graph safety
10.2 Ordinary record closure
For a non-array record:
No Object.keys, Object.entries, for-in, spread, JSON.stringify, or canonicalizer is used as a substitute for Reflect.ownKeys descriptor closure.
10.3 Array closure
For an array:
This makes the accepted current value exactly representable by JSON/RFC 8785 without simulator-visible own-key, descriptor, sparseness, alias, or Proxy state being omitted.
11. Shared failure semantics and ordering
verifyCurrentIntegrity and the registered simulate path call the same validator implementation.
verifyCurrentIntegrity ordering:
A descriptor, key, array, graph, Proxy, Unicode, or JSON violation can never return MATCH, even if JSON.stringify would omit it or canonicalize would produce the same text.
Registered simulate ordering:
Every failure occurs before simulator delegation. Delegate count remains zero. No cause, raw trap exception, URL, header, account, parameter, secret, key, or source message is retained or exposed.
Unregistered valid input keeps the current defensive structuredClone and validation path. Cross-port input is unregistered. WeakSet membership proves acquisition provenance only and never bypasses current validation.
12. Exact raw identity and authoritative evidence
MossPort.action is invoked exactly once. The exact source action-return object remains at mossOriginal.value and is also simulatorInput by strict identity.
The raw object is never frozen, modified, normalized, decorated, cloned into its place, or replaced. The source-boundary snapshot remains a different, independent, deeply frozen Mini-Demo-owned object. constructCapabilityV0_1 uses that snapshot by identity and does not clone again.
Before returning CONSTRUCTED_SYNTHETIC, the shared validator and canonical comparison prove that current raw content is JSON-exact and equal to the authoritative acquisition snapshot. A source-retained mutation between acquisition and construction returns SOURCE_CONTRACT_VIOLATION rather than successful evidence.
Unknown valid JSON fields remain in the snapshot and capability digest. Later valid raw mutation produces MISMATCH. Later JSON-exact violation produces UNPROVABLE. Neither changes the recorded snapshot or recorded digest.
13. Capability digest contract
The digest is calculated from the authoritative frozen snapshot:
The domain is exactly 31 UTF-8 bytes ending in one LF byte 0a. It has no CR, NUL, BOM, JSON quoting, length prefix, or extra separator.
Domain UTF-8 hex:
Golden synthetic Capability:
Expected canonical text:
Frozen vector:
Tests compare independently frozen expected text, length, domain hex, canonicalize 3.0.0 bytes, and digest. Expected constants are not generated by the implementation under test.
14. Node and address observations
The observer uses only the pinned Moss public node shape:
It records capabilityNodes, transactionNodes, and totalNodes. A valid tree with actual counts different from synthetic expected counts returns nodeCount.status UNEXPECTED with both values. It is not silently repaired or converted into Decision output. A malformed tree returns SOURCE_CONTRACT_VIOLATION.
Transaction targets are parsed as EIP-55 identifiers and retained in stable first-observed and deterministic deduplicated forms. Comparison is only against synthetic expectedTransactionTargets. Status is EXPECTED or UNEXPECTED, never approved, safe, authorized, or permitted.
No production or real-chain address is introduced. Requiring one is a stop condition and a future Maintainer-owned address authority task.
15. Complete test matrix
amount.test.ts:
capability.test.ts:
The four mandatory registered-after-acquisition descriptor regressions each perform both assertions before any successful simulator call:
Additional registered mutation cases retain the same integrity and zero-delegation assertions:
production.test.ts and fake.test.ts:
contracts.test.ts:
public-entry.smoke.mjs and server-only.test.ts:
All test values, addresses, ProtocolIds, Quotes, and Capabilities are synthetic. They are not Moss, Monad, RPC, wallet, transaction, receipt, or real-chain evidence.
16. Determinism, ownership, and errors
The construction operation is offline except for one supplied MossPort.action call. It uses no RPC, wall clock, randomness, environment secret, or browser state.
For equal validated input and equal action-return JSON content, action input, authoritative snapshot bytes, digest, counts, and address observations are identical.
All caller values are treated as untrusted. Selection, quoteRequest, and policy are validated into adapter-owned values. The raw Moss object retains Moss ownership. Only Mini-Demo-owned snapshot and evidence wrappers are frozen.
Invalid caller input is stable MossAdapterError INVALID_INPUT / action before action delegation. Contradictory or malformed action evidence is SOURCE_CONTRACT_VIOLATION / action. Invalid current registered simulate input is INVALID_INPUT / simulate before simulator delegation. Integrity verification never throws raw validation details; it returns UNPROVABLE. No failure preserves cause or source-sensitive text.
17. Strict Issue #28 isolation
Issue #27 may only:
Issue #27 must not:
Issue #28 remains solely responsible for invoking simulation in the product flow, preserving and mapping simulation evidence, and using the #27 guard before and after the exact call. A #28 contract change is not absorbed into #27.
18. Explicit non-goals
No #26 Quote collection, normalization, timeout, ranking, digest, outcome, or source-reference change.
No production address authority.
No Capability approval, safety conclusion, authorization, signing permission, execution guarantee, Alignment, Decision, STOP, MANUAL_REVIEW, or risk adjudication.
No simulation mapping or evidence construction.
No RPC, live chain, wallet, signing, transaction submission, receipt, backend, frontend, Web/API orchestration, database, deployment, or Clear402.
No report-schema, decision-engine, Moss source, git submodule, build-info, workflow, branch protection, required check, governance document, Issue, Project, Milestone, Review, Ready, Merge Gate, or merge operation.
No real address, private key, API key, endpoint, Quote, simulation, receipt, or transaction evidence.
19. Implementation sequence after authorization
Only after explicit Maintainer authorization:
20. Clean-checkout verification and acceptance
Use Node 22.23.1 and pnpm 11.16.0 in a fresh isolated worktree with no dist:
Acceptance requires:
21. Risks and rollback
Risks:
Controls:
Rollback is a feature-branch revert before merge. No deployment, database migration, chain state, transaction, or secret is created.
22. Stop conditions
Stop without implementation and request a replacement Scope Gate if:
23. Maintainer Scope Gate request
Please record a new explicit SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED comment only if all of these are accepted:
Until that explicit record exists:
pillowtalk-Qy commentedon Aug 6, 2026
SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED
Frozen authorization object:
5206374384updated_at:2026-08-06T14:51:21Zd53b3d458640286079fae2ad4eabf0f39b702a97ab7ff48487feedb6b0d6a766origin/main@65753ada85156716e263b660eeab72c42d293431Maintainer confirms the complete v3 scope.
Authorized writable paths, exactly:
pnpm-lock.yamlpackages/moss-adapter/package.jsonpackages/moss-adapter/src/types.tspackages/moss-adapter/src/source-bindings.tspackages/moss-adapter/src/amount.tspackages/moss-adapter/src/integrity.tspackages/moss-adapter/src/capability.tspackages/moss-adapter/src/index.tspackages/moss-adapter/test/contracts.test.tspackages/moss-adapter/test/production.test.tspackages/moss-adapter/test/fake.test.tspackages/moss-adapter/test/amount.test.tspackages/moss-adapter/test/capability.test.tspackages/moss-adapter/test/public-entry.smoke.mjspackages/moss-adapter/test/server-only.test.tsAuthorized dependency and public surface:
viem@2.55.11; no lifecycle/build permission or unrelated lockfile change;constructCapabilityV0_1;CapabilityConstructionPolicyV0_1andCapabilityConstructionResultV0_1;Frozen trust-boundary requirements:
SYNTHETIC_TESTonly and rejects every production or Maintainer-approval claim;RawCapabilityEvidence.miniDemoDerived.snapshotis the one authoritative acquisition snapshot and is reused by identity;createSelectedQuoteDigest; quote.ts, selection.ts and asset-catalog.ts remain read-only;Reflect.ownKeysclosure, string-only enumerable data descriptors for records, genuine dense arrays with only canonical indices and the standard length descriptor, Proxy rejection, graph/Unicode/JSON closure, and recursive descriptor-value inspection;UNPROVABLE,INVALID_INPUT / simulate, and zero simulator delegation;Builder is now authorized to create only:
codex/issue-27-capability-integrity/Users/qy/Documents/moss-mini-demo-issue-27Both must start from the exact authorized baseline. Builder may install only the authorized dependency and implement only the frozen v3 scope. Any baseline, path, dependency, export, validator, authority, #26 contract or #28 boundary change invalidates this authorization and requires a new Scope Gate.
This record authorizes implementation scope only. It is not QA PASS, Review approval,
READY_TO_MERGE, Merge Gate or merge authorization. The implementation must be delivered as a Draft PR closing #27, obtain exact-head quality-gate SUCCESS and complete QA/review on the frozen head.Issue #28 and later dependency-bound work remain Blocked. Issue #23 remains Ready/unassigned and does not consume the active P0 Builder slot.
feat: construct synthetic Capability integrity evidence (#74)