Skip to content

M2-06: Implement capability construction, amount conversion and integrity #27

Closed

Description

@pillowtalk-Qy
Type: Moss Adapter Security Feature
Priority: P0 / trust boundary
Initial status: Blocked
Owner: Moss Integration
Depends on: M2-05 merged(M2-04 当然已合并)
Blocks: M2-07, M2-12
Writable: capability*, amount*, integrity*, tests; rebased export only

唯一目标

调用已选协议的 Moss action,保留 exact action-return Capability,并证明金额转换和 Capability 完整性。

固定 digest 合同

canonicalization = RFC 8785
digestAlgorithm = SHA-256
domain = "moss-mini-demo:capability:v0.1\n"
digestInput = UTF8(domain) || UTF8(RFC8785(rawCapability))
serializedDigest = "sha256:" + lowercaseHex(SHA256(digestInput))

实施规则

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

验收

[ ] 1 MON <-> 10^18、最小单位、上界、round-trip 精确
[ ] excess precision rejected
[ ] tested RFC8785,不是手写排序
[ ] exact domain bytes 测试
[ ] independent snapshot immutable
[ ] original object 未被 freeze/modify
[ ] simulator identity test 证明 exact object/value
[ ] mutation 会改变 digest
[ ] unexpected node count 可观察
[ ] 地址由 Maintainer 确认

验证

pnpm vitest run packages/moss-adapter/test/amount.test.ts
pnpm vitest run packages/moss-adapter/test/capability.test.ts
pnpm --filter @moss-mini-demo/moss-adapter build
pnpm check

Codex 指令

必须在 M2-05 merge 后 rebase。保留 exact action return;只冻结独立 evidence snapshot。
用 viem + RFC8785 + WebCrypto/approved SHA256 实现固定 bytes 合同,加入 identity/immutability tests。

Activity

  1. added and removed
    status:blockedBlocked by an unresolved dependency
    on Aug 6, 2026
  2. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    DEPENDENCY_GATE_CLEARED

    Issue #26 has been squash-merged through PR #73 into main@65753ada85156716e263b660eeab72c42d293431.

    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.

  3. self-assigned this
    on Aug 6, 2026
  4. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    BUILDER_CLAIM / WORK_PLAN_REQUIRED

    Maintainer assigns the single active P0 planning slot to pillowtalk-Qy for Issue #27.

    • exact planning base: origin/main@65753ada85156716e263b660eeab72c42d293431
    • 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.

  5. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    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:

    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:

    1. @moss-mini-demo/moss-adapter has one public package entry and already exports collectAndSelectQuotesV0_1.
    2. 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.
    3. 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.
    4. 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.
    5. MossPort.simulate currently clones its input before delegation. That behavior does not satisfy the Issue M2-06: Implement capability construction, amount conversion and integrity #27 requirement that a later simulator receive the exact same action-return object.
    6. 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.
    7. 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.
    8. Issue M2-07: Implement simulation and lossless evidence mapping #28 owns simulation acquisition/output mapping, receipts, outcomes, warnings, coverage, ordering, state continuity, block evidence, and RPC provenance. Issue M2-06: Implement capability construction, amount conversion and integrity #27 may establish the exact identity handoff and integrity recheck surface, but may not implement those M2-07: Implement simulation and lossless evidence mapping #28 behaviors.

    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.

    1. pnpm-lock.yaml
    2. packages/moss-adapter/package.json
    3. packages/moss-adapter/src/types.ts
    4. packages/moss-adapter/src/source-bindings.ts
    5. packages/moss-adapter/src/amount.ts
    6. packages/moss-adapter/src/integrity.ts
    7. packages/moss-adapter/src/capability.ts
    8. packages/moss-adapter/src/index.ts
    9. packages/moss-adapter/test/contracts.test.ts
    10. packages/moss-adapter/test/production.test.ts
    11. packages/moss-adapter/test/fake.test.ts
    12. packages/moss-adapter/test/amount.test.ts
    13. packages/moss-adapter/test/capability.test.ts
    14. packages/moss-adapter/test/public-entry.smoke.mjs
    15. 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.
    • amount.ts contains strict internal amount conversion helpers.
    • 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:

    constructCapabilityV0_1
    

    Exact planned signature:

    constructCapabilityV0_1(
      port: MossPort,
      selection: Extract<QuoteCollectionResultV0_1, { status: "SELECTED" }>,
      quoteRequest: QuoteCollectionRequestV0_1,
      policy: CapabilityConstructionPolicyV0_1
    ): Promise<CapabilityConstructionResultV0_1>
    

    The only new type exports are:

    CapabilityConstructionPolicyV0_1
    CapabilityConstructionResultV0_1
    

    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:

    formatUnits(BigInt(smallestUnit), decimals)
    

    The implementation must then require:

    parseUnits(humanDecimal, decimals) === BigInt(smallestUnit)
    

    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:

    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:

    1. action is called exactly once with the adapter-owned ActionInput.
    2. mossOriginal.value is the exact object returned by the underlying Moss action binding, verified with object identity.
    3. The original object is not frozen, cloned into its place, modified, normalized, decorated, or replaced.
    4. An independent structured clone is created immediately after action return.
    5. The clone is validated as finite, acyclic, lone-surrogate-free JSON data and as an observable Moss Capability tree.
    6. Only the independent clone and Mini-Demo-owned evidence wrappers are recursively frozen.
    7. Mutating the original after return cannot mutate the snapshot.
    8. 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
    • transaction node: kind transaction, transaction.from, transaction.to, transaction.data, transaction.value

    It records exact nonnegative safe-integer counts:

    • capabilityNodes
    • transactionNodes
    • totalNodes

    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:

    canonicalization = RFC 8785 through canonicalize 3.0.0
    digestAlgorithm = SHA-256
    domain text = moss-mini-demo:capability:v0.1\n
    digestInput = UTF8(domain text) || UTF8(RFC8785(snapshot))
    serializedDigest = sha256: + lowercase hexadecimal SHA-256
    

    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:

    6d6f73732d6d696e692d64656d6f3a6361706162696c6974793a76302e310a
    

    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:

    {
      "kind": "capability",
      "protocol": "synthetic-protocol",
      "method": "swap",
      "params": {
        "amountIn": "1",
        "inputAsset": { "kind": "NATIVE" }
      },
      "children": [
        {
          "kind": "transaction",
          "transaction": {
            "from": "0x1111111111111111111111111111111111111111",
            "to": "0x2222222222222222222222222222222222222222",
            "data": "0x",
            "value": "0x0"
          }
        }
      ]
    }
    

    Expected canonical text, as one byte-exact line:

    {"children":[{"kind":"transaction","transaction":{"data":"0x","from":"0x1111111111111111111111111111111111111111","to":"0x2222222222222222222222222222222222222222","value":"0x0"}}],"kind":"capability","method":"swap","params":{"amountIn":"1","inputAsset":{"kind":"NATIVE"}},"protocol":"synthetic-protocol"}
    

    Frozen lengths and digest:

    canonical UTF-8 length = 306
    digest input UTF-8 length = 337
    serialized digest = sha256:0d251a152143187d0a50d9481330aef30fbf5ee03a011be2f936e5805ee9ad89
    

    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
    • NOT_SELECTED cast, zero/multiple matching eligible outcomes, digest mismatch, protocol/method/account/asset/amount/decimals/catalog mismatch
    • invalid or stale policy, unapproved protocol/asset, and missing production approval record
    • every invalid caller case fails before action, with delegate count zero
    • action receives canonical human amount and preserved validated additional params
    • action called once for the selected protocol only
    • exact action-return object identity retained
    • original object remains mutable, unfrozen, unmodified, and unreplaced
    • independent snapshot has different identity, identical acquisition content, deep freeze, and no shared nested references
    • exact simulatorInput identity
    • digest domain bytes, canonical text, hash golden vector, and lowercase serialization
    • repeated construction with equivalent evidence is deterministic apart from no time field in the digest
    • mutation of the original changes current digest, leaves snapshot and recorded digest unchanged, and yields MISMATCH
    • same-port simulate receives exact action object and an unchanged simulator yields post-call MATCH
    • mutating simulator yields post-call MISMATCH
    • valid expected and unexpected node counts are separately observable
    • approved and unexpected target addresses are separately observable
    • unknown raw fields are retained and affect digest
    • malformed tree and unsnapshotable action result fail through SOURCE_CONTRACT_VIOLATION without secret leakage
    • verifyCurrentIntegrity returns UNPROVABLE rather than source text after hostile post-return mutation
    • constructCapabilityV0_1 never acquires or maps simulation data

    production.test.ts and fake.test.ts:

    • action exact-return identity is registered per port
    • the same registered object is delegated to simulate by exact identity
    • arbitrary valid unregistered input preserves defensive owned snapshot behavior
    • cross-port object is not treated as registered
    • revoked Proxy and throwing getter fail before simulate binding
    • no cause or sensitive source text leaks
    • existing action/simulate evidence layering remains unchanged

    contracts.test.ts:

    • only SELECTED input is accepted statically
    • 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.

    15. Strict #28 isolation

    Issue #27 may:

    • make the same-port action-to-simulate object identity path possible
    • expose simulatorInput as the exact action return
    • expose verifyCurrentIntegrity for pre/post-use comparison
    • use a synthetic simulate call in tests only to prove identity and mutation detection

    Issue #27 must not:

    • acquire production simulation data as part of constructCapabilityV0_1
    • normalize or map RawSimulationEvidence
    • add simulation request/response types
    • create Receipt, Outcome, Warning, Coverage, Ordering, StateContinuity, block, RPC, or provider evidence
    • interpret simulation success or failure
    • 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

    1. Fetch origin and require origin/main to equal the exact frozen SHA.
    2. Require a clean state and create only the approved branch and isolated worktree.
    3. Add viem 2.55.11 to the adapter package with pnpm 11.16.0; inspect the lockfile before any source work.
    4. Add amount tests and strict viem conversion helpers.
    5. Add capability golden-vector, snapshot, mutation, node-count, address, and hostile-input tests.
    6. Add exact per-port action-return identity registration and simulate forwarding without changing MossPort signatures.
    7. Implement constructCapabilityV0_1 and the two type exports.
    8. Update only the public import and server-only assertions needed by the new runtime export.
    9. Run the focused and full validation matrix from a clean, no-dist state.
    10. Inspect the exact 15-path diff, commit, push, and create a Draft PR with Closes M2-06: Implement capability construction, amount conversion and integrity #27 only.
    11. Wait for exact-head quality-gate SUCCESS, publish an Implementation Report and Pre-PR QA Handoff, then freeze the head.

    18. Clean-checkout verification

    Use exactly Node 22.23.1 and pnpm 11.16.0 from a fresh isolated worktree with no dist directories:

    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:

    • all commands pass
    • exact diff contains all and only the approved paths actually needed, with no sixteenth path
    • only viem 2.55.11 is added directly and no unrelated lockfile resolution changes
    • public package import works on Node 22
    • exact runtime export list has one addition
    • original action return remains exact and mutable
    • independent snapshot is immutable
    • golden digest bytes match
    • amount boundary matrix passes
    • same-port simulator binding receives exact action-return identity
    • no M2-07: Implement simulation and lossless evidence mapping #28 mapping behavior is present
    • exact-head quality-gate succeeds and retains the stable quality-gate job name

    19. Risks and rollback

    Risks:

    • viem rounds excess precision unless the adapter rejects it first
    • a mutable raw Capability may change after acquisition
    • identity forwarding can weaken the hostile-input boundary unless registration is scoped to the exact same port and exact action return
    • canonicalization can fail or normalize invalid Unicode unexpectedly unless JSON and surrogate validation happens first
    • a node-count match is not a safety proof
    • an address-policy label is not proof unless its immutable Maintainer record exists
    • accidental simulation mapping would absorb M2-07: Implement simulation and lossless evidence mapping #28
    • 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:

    • origin/main is not 65753ad
    • Maintainer does not explicitly approve the 15 paths, viem 2.55.11, one runtime export, two type exports, and identity handoff
    • a production address must be hardcoded or a repository approval record must be added outside this path list
    • a new dependency, lifecycle permission, package subpath, public helper, sixth MossPort method, or sixteenth path is required
    • M2-05: Implement quote collection and deterministic selection #26 selection or digest semantics must change
    • vendor/moss or pinned build information must change
    • exact raw identity cannot be preserved without exposing hostile inputs
    • post-use integrity cannot be checked without implementing M2-07: Implement simulation and lossless evidence mapping #28 mapping
    • a real address, endpoint, key, Quote, simulation, wallet, or transaction is requested
    • any contract conflict would require Builder-defined evidence or authorization semantics

    21. Maintainer confirmation requested

    Please record SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED only if all of the following are accepted:

    1. exact baseline and 15 writable paths
    2. sole new dependency viem 2.55.11 and no new lifecycle permission
    3. sole runtime export constructCapabilityV0_1 and the two named type exports
    4. four-argument public signature and exact selected-quote association
    5. strict smallest-unit to human-decimal contract and pre-rejection of excess precision
    6. exact raw action identity, independent snapshot, capability digest, and verifyCurrentIntegrity surface
    7. same-port WeakSet identity forwarding while retaining defensive behavior for all unregistered inputs
    8. observable but non-decisional node-count and address mismatches
    9. server-owned address policy with immutable Maintainer source record and synthetic-only test policy
    10. complete M2-07: Implement simulation and lossless evidence mapping #28 isolation and all stop conditions

    Until that record exists, status is:

    WORK_PLAN_SUBMITTED / AWAITING_MAINTAINER_SCOPE_CONFIRMATION
    
  6. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    SCOPE_CHANGES_REQUESTED

    Frozen Scope Gate object:

    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:

    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 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:

    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. 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:

    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_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.

  7. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    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:

    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:

    codex/issue-27-capability-integrity
    /Users/qy/Documents/moss-mini-demo-issue-27
    

    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:

    1. The source boundary validates the Moss action result and atomically creates the immutable Mini-Demo snapshot.
    2. It returns the exact Moss original object and that authoritative snapshot in RawCapabilityEvidence.
    3. constructCapabilityV0_1 verifies that the evidence layers are correctly labeled MOSS_ORIGINAL and MINI_DEMO_DERIVED.
    4. Before returning success, it computes the digest from the authoritative snapshot and separately validates and canonicalizes the current exact raw object.
    5. 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.
    6. 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.

    2.4 Reuse the merged #26 selected digest contract

    The merged #26 helper remains the sole selected-Quote digest constructor:

    packages/moss-adapter/src/quote.ts:createSelectedQuoteDigest
    

    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.

    1. pnpm-lock.yaml
    2. packages/moss-adapter/package.json
    3. packages/moss-adapter/src/types.ts
    4. packages/moss-adapter/src/source-bindings.ts
    5. packages/moss-adapter/src/amount.ts
    6. packages/moss-adapter/src/integrity.ts
    7. packages/moss-adapter/src/capability.ts
    8. packages/moss-adapter/src/index.ts
    9. packages/moss-adapter/test/contracts.test.ts
    10. packages/moss-adapter/test/production.test.ts
    11. packages/moss-adapter/test/fake.test.ts
    12. packages/moss-adapter/test/amount.test.ts
    13. packages/moss-adapter/test/capability.test.ts
    14. packages/moss-adapter/test/public-entry.smoke.mjs
    15. 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:

    constructCapabilityV0_1
    

    Its exact planned signature is:

    constructCapabilityV0_1(
      port: MossPort,
      selection: Extract<QuoteCollectionResultV0_1, { status: "SELECTED" }>,
      quoteRequest: QuoteCollectionRequestV0_1,
      policy: CapabilityConstructionPolicyV0_1
    ): Promise<CapabilityConstructionResultV0_1>
    

    Only these new type names are exported:

    CapabilityConstructionPolicyV0_1
    CapabilityConstructionResultV0_1
    

    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.

    The Moss action amount is:

    formatUnits(BigInt(smallestUnit), decimals)
    

    The implementation must check:

    parseUnits(humanDecimal, decimals) === BigInt(smallestUnit)
    

    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
    • rejects accessor descriptors and throwing getters
    • rejects cycles, unsupported prototypes, non-finite numbers, lone surrogates, and non-JSON values

    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:

    canonicalization = RFC 8785 through canonicalize 3.0.0
    digestAlgorithm = SHA-256
    domain text = moss-mini-demo:capability:v0.1\n
    digestInput = UTF8(domain text) || UTF8(RFC8785(snapshot))
    serializedDigest = sha256: + lowercaseHex(SHA256(digestInput))
    

    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:

    6d6f73732d6d696e692d64656d6f3a6361706162696c6974793a76302e310a
    

    Golden synthetic raw Capability:

    {
      "kind": "capability",
      "protocol": "synthetic-protocol",
      "method": "swap",
      "params": {
        "amountIn": "1",
        "inputAsset": { "kind": "NATIVE" }
      },
      "children": [
        {
          "kind": "transaction",
          "transaction": {
            "from": "0x1111111111111111111111111111111111111111",
            "to": "0x2222222222222222222222222222222222222222",
            "data": "0x",
            "value": "0x0"
          }
        }
      ]
    }
    

    Expected canonical text is the byte-exact one-line value:

    {"children":[{"kind":"transaction","transaction":{"data":"0x","from":"0x1111111111111111111111111111111111111111","to":"0x2222222222222222222222222222222222222222","value":"0x0"}}],"kind":"capability","method":"swap","params":{"amountIn":"1","inputAsset":{"kind":"NATIVE"}},"protocol":"synthetic-protocol"}
    

    Frozen vector:

    canonical UTF-8 length = 306
    digest input UTF-8 length = 337
    serialized digest = sha256:0d251a152143187d0a50d9481330aef30fbf5ee03a011be2f936e5805ee9ad89
    

    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
    • transaction: kind, transaction.from, transaction.to, transaction.data, transaction.value

    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
    • NOT_SELECTED cast, zero/multiple matches, digest mismatch, protocol/method/account/asset/amount/decimal/catalog mismatch
    • 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.

    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:

    1. fetch origin and require exact origin/main baseline

    2. create the proposed branch and isolated worktree

    3. add viem 2.55.11 and inspect only its lockfile graph

    4. implement amount boundary and tests

    5. implement source-boundary identity registration and current validation

    6. implement capability construction by reusing createSelectedQuoteDigest

    7. implement snapshot comparison, digest, observations, and integrity guard

    8. update only the public-entry and server-only assertions

    9. 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:

    1. exact baseline and closed 15-path list
    2. viem 2.55.11 as the only new direct dependency
    3. constructCapabilityV0_1 as the only runtime addition and the two named type exports
    4. synthetic-only policy that rejects every production authority claim
    5. source-boundary snapshot as the sole authoritative acquisition snapshot
    6. fail-closed raw-versus-snapshot comparison before success
    7. per-port registration plus current non-cloning validation before exact simulate delegation
    8. direct reuse of createSelectedQuoteDigest from M2-05: Implement quote collection and deterministic selection #26 with no copied payload/hash code
    9. synthetic node/address observations with no approval or safety semantics
    10. complete M2-07: Implement simulation and lossless evidence mapping #28 isolation, test matrix, validation, and stop conditions

    Until that explicit record exists:

    WORK_PLAN_V2_SUBMITTED / AWAITING_MAINTAINER_SCOPE_CONFIRMATION
    
  8. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    SCOPE_CHANGES_REQUESTED - Work Plan v2

    Frozen review object:

    The following v1 blockers are resolved:

    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:

    1. inspect every own key with Reflect.ownKeys under trap-safe handling;
    2. for records, allow only enumerable string-keyed data descriptors and reject Symbols, non-enumerable properties and accessors;
    3. 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;
    4. recursively enforce the same rules before canonicalization and immediately before exact-identity delegation;
    5. 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.

  9. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    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:

    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:

    branch: codex/issue-27-capability-integrity
    worktree: /Users/qy/Documents/moss-mini-demo-issue-27
    

    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:

    1. @moss-mini-demo/moss-adapter has one public package entry and currently exposes five MossPort methods.
    2. collectAndSelectQuotesV0_1 returns a discriminated QuoteCollectionResultV0_1 with the complete M2-05: Implement quote collection and deterministic selection #26 outcome set, catalog snapshot, selected protocol, and selected RFC 8785 SHA-256 digest.
    3. createSelectedQuoteDigest in packages/moss-adapter/src/quote.ts is the merged sole constructor for the selected-Quote digest contract.
    4. 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.
    5. MossPort.simulate currently clones and validates its input before binding delegation.
    6. The pinned Moss Capability model has capability and transaction nodes, while raw unknown JSON fields must remain preserved.
    7. Current main has no production Maintainer-owned address authority record.
    8. Issue M2-07: Implement simulation and lossless evidence mapping #28 owns simulation acquisition and mapping, receipts, outcomes, warnings, coverage, ordering, continuity, block/RPC evidence, and downstream treatment of integrity results.

    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.

    1. pnpm-lock.yaml
    2. packages/moss-adapter/package.json
    3. packages/moss-adapter/src/types.ts
    4. packages/moss-adapter/src/source-bindings.ts
    5. packages/moss-adapter/src/amount.ts
    6. packages/moss-adapter/src/integrity.ts
    7. packages/moss-adapter/src/capability.ts
    8. packages/moss-adapter/src/index.ts
    9. packages/moss-adapter/test/contracts.test.ts
    10. packages/moss-adapter/test/production.test.ts
    11. packages/moss-adapter/test/fake.test.ts
    12. packages/moss-adapter/test/amount.test.ts
    13. packages/moss-adapter/test/capability.test.ts
    14. packages/moss-adapter/test/public-entry.smoke.mjs
    15. 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.
    • amount.ts contains private strict viem conversion helpers.
    • 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.

    7. Exact public API

    The only new runtime package-root export is:

    constructCapabilityV0_1
    

    Exact signature:

    constructCapabilityV0_1(
      port: MossPort,
      selection: Extract<QuoteCollectionResultV0_1, { status: "SELECTED" }>,
      quoteRequest: QuoteCollectionRequestV0_1,
      policy: CapabilityConstructionPolicyV0_1
    ): Promise<CapabilityConstructionResultV0_1>
    

    The only new exported type names are:

    CapabilityConstructionPolicyV0_1
    CapabilityConstructionResultV0_1
    

    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.

    The Moss action human amount is:

    formatUnits(BigInt(smallestUnit), decimals)
    

    The implementation requires:

    parseUnits(humanDecimal, decimals) === BigInt(smallestUnit)
    

    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:

    1. Prototype must be exactly Object.prototype or null.
    2. Reflect.ownKeys inspects every own key under trap-safe handling.
    3. Every own key must be a string. Any Symbol key is rejected.
    4. Reflect.getOwnPropertyDescriptor must return a descriptor for every key.
    5. Every descriptor must be an enumerable data descriptor.
    6. Any non-enumerable property is rejected.
    7. Any accessor, getter, setter, or descriptor without a data value is rejected.
    8. Recursion uses descriptor.value rather than invoking property access.
    9. 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:

    1. It must be a genuine non-Proxy Array with prototype exactly Array.prototype.
    2. Reflect.ownKeys must return exactly the dense canonical string indices 0 through length - 1 in canonical order, followed only by length.
    3. Every expected index must exist. A hole or sparse index set is rejected.
    4. Index keys must use canonical decimal spelling. Noncanonical numeric-looking keys are rejected.
    5. Every index descriptor must be an enumerable data descriptor.
    6. The only permitted non-enumerable own property is length.
    7. 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.
    8. Any Symbol key is rejected.
    9. Any extra named property is rejected.
    10. Any accessor index, accessor property, extra non-enumerable property, or modified length descriptor is rejected.
    11. 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:

    1. validate current exact raw through the shared JSON-exact validator
    2. if validation fails, return UNPROVABLE
    3. only after success, RFC 8785 canonicalize and compute current digest
    4. return MATCH only if the current canonical bytes/digest equal the authoritative snapshot record
    5. 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:

    1. confirm same-port exact action-return identity
    2. synchronously run the shared JSON-exact validator
    3. on any validation failure, throw MossAdapterError with code INVALID_INPUT and operation simulate
    4. confirm there has been no await, clone, normalization, or replacement after validation
    5. invoke the binding synchronously with the exact registered object
    6. 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:

    canonicalization = RFC 8785 through canonicalize 3.0.0
    digestAlgorithm = SHA-256
    domain text = moss-mini-demo:capability:v0.1\n
    digestInput = UTF8(domain text) || UTF8(RFC8785(snapshot))
    serializedDigest = sha256: + lowercaseHex(SHA256(digestInput))
    

    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:

    6d6f73732d6d696e692d64656d6f3a6361706162696c6974793a76302e310a
    

    Golden synthetic Capability:

    {
      "kind": "capability",
      "protocol": "synthetic-protocol",
      "method": "swap",
      "params": {
        "amountIn": "1",
        "inputAsset": { "kind": "NATIVE" }
      },
      "children": [
        {
          "kind": "transaction",
          "transaction": {
            "from": "0x1111111111111111111111111111111111111111",
            "to": "0x2222222222222222222222222222222222222222",
            "data": "0x",
            "value": "0x0"
          }
        }
      ]
    }
    

    Expected canonical text:

    {"children":[{"kind":"transaction","transaction":{"data":"0x","from":"0x1111111111111111111111111111111111111111","to":"0x2222222222222222222222222222222222222222","value":"0x0"}}],"kind":"capability","method":"swap","params":{"amountIn":"1","inputAsset":{"kind":"NATIVE"}},"protocol":"synthetic-protocol"}
    

    Frozen vector:

    canonical UTF-8 length = 306
    digest input UTF-8 length = 337
    serialized digest = sha256:0d251a152143187d0a50d9481330aef30fbf5ee03a011be2f936e5805ee9ad89
    

    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
    • transaction node: kind, transaction.from, transaction.to, transaction.data, transaction.value

    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
    • NOT_SELECTED cast, zero/multiple matches, digest/protocol/method/account/asset/amount/decimal/catalog mismatch
    • SERVER_CONFIGURED, PINNED_SUBMODULE, MAINTAINER_APPROVED, and caller approval prose rejected
    • every pre-action invalid case has action delegate count zero
    • exact human action amount and preserved additional params
    • exact action-return identity, raw mutable/unfrozen/unmodified/unreplaced
    • authoritative snapshot reused by identity, deeply independent and frozen
    • mutation between acquisition snapshot and construction fails closed
    • exact simulatorInput identity
    • domain, canonical bytes, digest, and length golden vectors
    • valid later mutation returns MISMATCH and leaves recorded evidence unchanged
    • every JSON-exact violation returns UNPROVABLE and never MATCH
    • expected and unexpected synthetic node counts and transaction targets
    • malformed tree rejected
    • unknown valid JSON fields retained and digest-relevant
    • constructCapabilityV0_1 does not acquire or map simulation output

    The four mandatory registered-after-acquisition descriptor regressions each perform both assertions before any successful simulator call:

    1. non-enumerable own data property
      • verifyCurrentIntegrity returns UNPROVABLE, not MATCH
      • simulate throws INVALID_INPUT / simulate
      • simulator delegate count is zero
    2. own Symbol key
      • verifyCurrentIntegrity returns UNPROVABLE, not MATCH
      • simulate throws INVALID_INPUT / simulate
      • simulator delegate count is zero
    3. sparse array or array hole at a nested Capability location
      • verifyCurrentIntegrity returns UNPROVABLE, not MATCH
      • simulate throws INVALID_INPUT / simulate
      • simulator delegate count is zero
    4. extra named array property
      • verifyCurrentIntegrity returns UNPROVABLE, not MATCH
      • simulate throws INVALID_INPUT / simulate
      • simulator delegate count is zero

    Additional registered mutation cases retain the same integrity and zero-delegation assertions:

    • accessor or throwing getter
    • modified/nonstandard array length descriptor where constructible
    • non-enumerable array index
    • array Symbol key
    • array accessor index
    • cycle
    • repeated object alias
    • unsupported prototype
    • non-finite number
    • lone-surrogate key or value
    • nested hostile, stateful, or revoked Proxy

    production.test.ts and fake.test.ts:

    • same-port registration and valid exact identity forwarding
    • the exact shared validator behavior for both ports
    • each mandatory descriptor regression with zero simulator delegation
    • all additional registered hostile cases with zero delegation
    • unregistered valid input retains defensive owned clone
    • cross-port object remains unregistered
    • 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.

    17. Strict Issue #28 isolation

    Issue #27 may only:

    • establish exact same-port action-to-simulate identity transport
    • expose simulatorInput as the exact action return
    • expose verifyCurrentIntegrity for pre/post-use checks
    • use synthetic simulate calls in tests to prove identity, validation, and mutation behavior

    Issue #27 must not:

    • call production simulation from constructCapabilityV0_1
    • map RawSimulationEvidence
    • add simulation request/response types
    • create Receipt, Outcome, Warning, Coverage, Ordering, StateContinuity, block, RPC, provider, Alignment, Decision, STOP, or MANUAL_REVIEW evidence
    • interpret simulation success/failure
    • 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:

    1. fetch origin and require exact origin/main
    2. verify clean state
    3. create only the approved branch and isolated worktree
    4. add viem 2.55.11 and inspect the lockfile before source changes
    5. add amount tests and strict conversion
    6. add shared JSON-exact validator tests, including all four mandatory descriptor regressions
    7. implement the single validator in integrity.ts
    8. call that exact validator from verifyCurrentIntegrity and registered simulate
    9. add per-port exact identity registration and fail-closed immediate validation
    10. implement capability construction with the authoritative snapshot and direct createSelectedQuoteDigest reuse
    11. add digest, ownership, mutation, count, and address tests
    12. update only the authorized public-entry and server-only assertions
    13. inspect the exact 15-path diff
    14. run the complete clean-checkout matrix
    15. commit, push, and open a Draft PR with Closes M2-06: Implement capability construction, amount conversion and integrity #27 only
    16. wait for exact-head quality-gate SUCCESS, publish Implementation Report and Pre-PR QA Handoff, then freeze the head

    20. Clean-checkout verification and acceptance

    Use Node 22.23.1 and pnpm 11.16.0 in a fresh isolated worktree with no dist:

    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:

    • every command passes
    • exactly the authorized paths and no sixteenth path
    • viem 2.55.11 is the only direct dependency addition
    • no unrelated lockfile churn or lifecycle permission
    • exactly one runtime export addition
    • selected digest uses the merged helper
    • authoritative snapshot is reused
    • raw action identity is retained
    • valid registered raw reaches simulator by exact identity
    • every invalid registered raw fails before delegation
    • all four mandatory descriptor regressions return UNPROVABLE from integrity, INVALID_INPUT / simulate from simulate, and delegate count zero
    • amount and digest golden vectors pass
    • no M2-07: Implement simulation and lossless evidence mapping #28 behavior exists
    • exact-head quality-gate SUCCESS retains job name quality-gate

    21. Risks and rollback

    Risks:

    • viem may round excess precision unless rejected first
    • mutable raw state may diverge from evidence
    • enumerable-only traversal can omit simulator-visible state
    • arrays can hide holes or additional properties
    • Proxy behavior can change between reflective operations
    • a second validator can drift from simulator enforcement
    • canonicalization can hide unsupported descriptor state
    • node/address observations can be mistaken for safety
    • implementation can accidentally absorb M2-07: Implement simulation and lossless evidence mapping #28
    • lockfile installation can create unrelated churn

    Controls:

    • strict pre-parse amount validation
    • one shared JSON-exact validator
    • Reflect.ownKeys descriptor closure
    • Proxy rejection
    • dense canonical arrays
    • authoritative source-boundary snapshot
    • pre-construction canonical equality
    • pre-delegation synchronous validation
    • exact byte vectors
    • synthetic-only policy
    • stable secret-safe errors
    • exact path and dependency review

    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:

    • origin/main differs from 65753ad
    • Maintainer does not explicitly approve v3
    • any sixteenth writable path is required
    • any dependency beyond viem 2.55.11 is required
    • a lifecycle/build permission is required
    • any runtime export beyond constructCapabilityV0_1 or type export beyond the two named types is required
    • a second JSON validator or simulator-only weakened validator is required
    • exact Reflect.ownKeys descriptor closure cannot be implemented
    • exact registered identity cannot be forwarded without bypassing current validation
    • quote.ts, selection.ts, M2-05: Implement quote collection and deterministic selection #26 digest semantics, report-schema, Moss source, or workflow must change
    • production authority or a real address is requested
    • simulation mapping or any M2-07: Implement simulation and lossless evidence mapping #28-owned evidence must be added
    • a real endpoint, key, wallet, Quote, simulation, receipt, transaction, or chain datum is requested

    23. Maintainer Scope Gate request

    Please record a new explicit SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED comment only if all of these are accepted:

    1. exact baseline and unchanged 15-path set
    2. viem 2.55.11 as the only dependency addition
    3. one runtime export and two type exports
    4. synthetic-only authority
    5. one authoritative source-boundary snapshot
    6. direct reuse of createSelectedQuoteDigest
    7. one shared JSON-exact validator for integrity and registered simulate
    8. Reflect.ownKeys closure for every nested object
    9. strict record descriptors and strict dense arrays
    10. UNPROVABLE integrity semantics
    11. INVALID_INPUT / simulate and zero delegation semantics
    12. four mandatory descriptor regressions
    13. exact identity and digest contracts
    14. complete M2-07: Implement simulation and lossless evidence mapping #28 isolation, non-goals, verification, and stop conditions

    Until that explicit record exists:

    WORK_PLAN_V3_SUBMITTED / AWAITING_MAINTAINER_SCOPE_CONFIRMATION
    
  10. pillowtalk-Qy commented on Aug 6, 2026

    @pillowtalk-Qy
    ContributorAuthor

    SCOPE_CONFIRMED / IMPLEMENTATION_AUTHORIZED

    Frozen authorization object:

    Maintainer confirms the complete v3 scope.

    Authorized writable paths, exactly:

    1. pnpm-lock.yaml
    2. packages/moss-adapter/package.json
    3. packages/moss-adapter/src/types.ts
    4. packages/moss-adapter/src/source-bindings.ts
    5. packages/moss-adapter/src/amount.ts
    6. packages/moss-adapter/src/integrity.ts
    7. packages/moss-adapter/src/capability.ts
    8. packages/moss-adapter/src/index.ts
    9. packages/moss-adapter/test/contracts.test.ts
    10. packages/moss-adapter/test/production.test.ts
    11. packages/moss-adapter/test/fake.test.ts
    12. packages/moss-adapter/test/amount.test.ts
    13. packages/moss-adapter/test/capability.test.ts
    14. packages/moss-adapter/test/public-entry.smoke.mjs
    15. packages/moss-adapter/test/server-only.test.ts

    Authorized dependency and public surface:

    • the sole direct dependency addition is viem@2.55.11; no lifecycle/build permission or unrelated lockfile change;
    • the sole runtime export addition is constructCapabilityV0_1;
    • the only new exported type names are CapabilityConstructionPolicyV0_1 and CapabilityConstructionResultV0_1;
    • MossPort remains five methods with unchanged signatures.

    Frozen trust-boundary requirements:

    • the release is SYNTHETIC_TEST only and rejects every production or Maintainer-approval claim;
    • RawCapabilityEvidence.miniDemoDerived.snapshot is the one authoritative acquisition snapshot and is reused by identity;
    • current raw must validate and canonically equal that snapshot before successful construction;
    • M2-06: Implement capability construction, amount conversion and integrity #27 directly reuses the merged M2-05: Implement quote collection and deterministic selection #26 createSelectedQuoteDigest; quote.ts, selection.ts and asset-catalog.ts remain read-only;
    • 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;
    • M2-07: Implement simulation and lossless evidence mapping #28 simulation acquisition/mapping and all downstream evidence remain outside M2-06: Implement capability construction, amount conversion and integrity #27.

    Builder is now authorized to create only:

    • branch: codex/issue-27-capability-integrity
    • isolated worktree: /Users/qy/Documents/moss-mini-demo-issue-27

    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.

  11. added a commit that references this issue on Aug 7, 2026
    b3ba141
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions