Sales corrected ordering review and preparation failure boundaries
Assignment ADR-0053/sales/003; Sales participant 01a0ff07-d3d4-7553-bf28-5314810de63e, host local; coordinator 01a0e095-f279-7fd0-a8ef-92ce8f9547fc, host local. Prior Sales review was published at 5c3c870c. This follow-up supplies Sales' own bounded design choices and correction findings. It withholds formal acknowledgment until the aligned package is assembled and reviewed; no other owner's authority, runtime change or production activation is approved.
Pinned evidence and correction results
Reviewed Revenue manifest SHA256 70016cced1f8bd1558a5f51a884b4cd58d4d7d19a51cb8e7438a411446ccbfaf (Revenue source d24da76a84e7fc72dc909a1d84c748e9d11d8d65) and Platform 003 manifest 865c8ab775434e1d4b84484e68a8ee19eed24d5e21a934e801cae196f3b08de4. All twenty Revenue and seventeen Platform listed artifacts matched hashes and byte counts before copying into C:/Users/jallr/Documents/Sguild/repos/sales/.tmp/adr0053-sales003/. Earlier snapshots and clean ADR-0052 candidate 62c6c0449d8316f38dd33df2e83033208ea0703c remain untouched.
Copied runners write only Sales review storage. Dependency imports point to already installed Ajv; Platform's runner also consumes the exact previously preserved 002 descriptor example. No owner drafts or runtime were edited. Reproduce from Sales primary root:
node .tmp/adr0053-sales003/validate-draft.mjs
python .tmp/adr0053-sales003/verify-independent.py
node .tmp/adr0053-sales003/platform-snapshot/validation/validate.mjs
node .tmp/adr0053-sales003/review.mjs
node .tmp/adr0053-sales003/followup.mjs
Revenue reproduces 415 checks, 29 valid digest cases and thirteen normalization denials. Python independently verifies all 29, rejects thirteen, verifies three raw positives and rejects sixteen raw negatives, with no failures. Platform reproduces six strict schemas, 24 definitions and 199 modeled vectors. Extraction of the actual Sales wire mapper and actual Revenue structural parser confirms all 29 normalized/digest cases. Padded capture source fixtures are represented by the actual typed mapper's literal source and share the expected normalized digest; this does not claim that typed Sales emits a padded enum.
Capture-source trimming, raw currency acceptance and zero-payment structural parity now pass. The lossy fractional amount is denied by the corrected raw parser. The new shared descriptor payload and recovery request pass both owners' candidate schemas, with original UUIDv4 and matching sclose3/ssh2 suffixes. Both transport schemas accept 8192 ASCII bytes and reject 8193. Raw body 65536 bytes parses and validates in a synthetic size-only fixture; 65537 is denied. These budget fixtures are not signature/descriptor-correlation positives. Nested identity and transient terminal outcomes still need semantic validation beyond schema; Revenue now provides executable modeled negatives for them. No RSA, real-handler, DB uniqueness/concurrency, provider, financial or production proof follows from these checks.
Sales numeric and normalization position
Sales supports a deliberate ordering-v3 tightening: every admitted close numeric field uses plain nonnegative base-10 integer lexical form 0|[1-9][0-9]*, bounded by 9007199254740991 and smaller field-specific limits. Reject decimal/exponent forms even if mathematically integral, negative zero, unsafe magnitude, negatives and leading zeros before admission. This includes 1.0, 1e0, underflow/overflow and the rounded fractional boundary from the prior review. V2 remains unchanged. No supported close needs a negative numeric field: actual Sales close schema requires nonnegative price/payment and quantity 1..20, and its client emits those fields through JSON.stringify.
Revenue's generic raw parser intentionally accepts a safe signed integer such as -1, while its recognized close field schemas subsequently reject it. Platform recommends a nonnegative raw tokenizer. The accepted original-close wire set can be identical, but the assembled specification must make the layer distinction explicit: a signed generic parsing primitive is permitted only if complete closed-field nonnegative validation occurs before digest/admission/effects; no negative field is ever an admitted v3 command. If the common spec requires lexical rejection at the primitive itself, amend the generic negative-positive fixture accordingly. Do not call these primitive behaviors identical today.
Sales preparation must validate typed numbers before serialization as well as inspect final raw bytes. TypeScript number and existing zod .int() are not a safe-integer guarantee; JSON.stringify can erase negative zero or convert nonfinite values to null. Require finite safe integers, correct lower/upper bounds and no negative zero before constructing the frozen wire. Then run the approved raw validator on the exact outbound UTF-8 bytes. Safe nonnegative integers within this limit serialize as plain decimal without exponent, so the stricter raw rule is compatible with this actual mapper. Validate normalized arrays/strings and existing equivalence classes once, retain the resulting digest and freeze original prepared payer/offer/first-Lesson values. No fresh hydration on recovery.
Descriptor/body budget and preparation failures
Sales accepts 8192 ASCII bytes for the exact compact descriptor, decoded header <=384, payload <=4096 and exact RSA modulus signature 256..512. The decoded maxima imply at most 6659 compact bytes including separators; the outer cap remains an independent fail-closed check. Both original and recovery JSON bodies are at most 65536 UTF-8 bytes including the descriptor and complete envelope. Count bytes, JSON escaping, quotes and separators, not JavaScript string length or only offer/capture values. The supplied normal fixture is 2330 descriptor bytes and 2852 original body bytes, but one fixture is not a supported-payload census. Current Sales capture strings/offer arrays have no general maximum; this is a documented major-wire budget, not a claim of universal old-payload coverage.
Before creating the soft resource, Sales should validate source numeric/string/offer shape and reserve the descriptor's full 8192-byte envelope budget with the fixed-size first-Lesson field and actual serialized original values. Reject an over-budget human request with an actionable preparation reason before soft send. This conservative preflight permits less than the theoretical maximum if it reserves the full cap; document the accepted budget rather than silently trimming payer/offer fields. Always recheck final body/descriptor decoded and total bounds after the real receipt and signer output exist and before the original Revenue fetch.
| Failure cut point | Sales handling |
|---|---|
| Before durable human admission/soft send | Show preparation validation failure; no booking/payment send. An operator may correct the unsent input. |
| Admission durable, before successful soft receipt | Keep the original command and reconcile any uncertain soft send. Do not reinterpret missing receipt as absence or issue another admission around it. |
| Successful soft receipt retained, close shape/budget/digest/signing/audit preparation fails | Persist non-secret preparation failure and retain the original resource/blocker. Show "Booking preparation needs review. No payment was submitted." only when durable send evidence proves Revenue fetch was never authorized; otherwise show reconciliation pending. No fabricated descriptor/tombstone, fresh capture, rewritten original or new business key. |
| Exact prepared descriptor committed, process loses inline credential or crashes before/around fetch | Recover with the saved exact artifact and original identity. Only Revenue's serialized permanent never-admitted receipt can settle the original financial admission uncertainty. No reconstruction/resigning/replacement of the capture or command. |
| Recovery unavailable, mismatch, auth/trust denial or provider/writeback unknown | Retain blocker and evidence; reconciliation pending, replacement/payment disabled. No transport response is settlement. |
An unbound soft resource stranded before valid close preparation cannot use bound failed-close compensation. Delivery owns its exact original soft-resource resolution under existing accepted authority or a separately approved bounded remedy. Do not infer expiry/cancellation from time or missing rows, widen ADR-0053, or create an invalid close merely to obtain a tombstone. Retry only the same permitted preparation stage/immutable identity where approved; edits after durable admission require explicit original-obligation resolution and fresh independent human admission, not mutation of history.
Exact denial, uniqueness and blocker positions
Namespace/size/semantic-equivalence corrections are compatible with Sales' prior position. Preserve original UUIDv4 human admission; close sclose3:<same UUID> and soft ssh2:<same UUID>. Prospectively require one immutable Sales prepared record per original admission, sign once and durably save exact compact bytes/digest/audit before send. Revenue independently enforces permanent issuer/admission uniqueness across compatible namespaces, exact key registry uniqueness and suffix/descriptor/resource correspondence under the shared admission/tombstone/trust barrier. Existing Sales source expresses single-close intent but does not implement these new prepared-record constraints. No old journal/receipt backfill, new human verification or separate replacement close identity is authorized.
Taxonomy is still mismatched. Corrected Revenue retains Platform 002's 401 descriptor_invalid and 409 descriptor_unverifiable. Platform 003 recommends 400 malformed transport/canonical bytes/namespace/version, 403 invalid signer/issuer/audience/signature, 409 correlated accessible identity mismatch and 503 retired/revoked/unavailable trust/history. Sales prefers the latest 003 layer separation: fresh workload invalidity stays 401, artifact authorization failure after valid workload is 403, invalid transport is 400, exact identity conflicts are 409, and unavailable or no-longer-authoritative unseen provenance is 503 with uncertainty retained. Each needs one exact closed error code/envelope agreed by Platform and Revenue. There is no automatic retry with a new key under any of these responses. This preference is not a claim that corrected drafts already agree.
For financial never-admitted settlement, retain the exact immutable receipt separately from successful Sales completion; it proves permanent Revenue admission prevention only. The earlier Delivery soft resource remains a distinct obligation. For admitted failed-close compensation, neither operational Lesson Canceled/hold released nor the subsequent credit.released event is sufficient. Keep the original Sales blocker through compensating g+1, pending financial writeback and any lost finalization response. Retirement requires exact original identity/digests/resources, retained Revenue writeback proof with abandoned/no-new-collection and all compensation work resolved, plus Delivery's finalization receipt/current authoritative resource assessment proving the exact g+2 retirement. Never infer replacement readiness from event order or a historical receipt alone. Current Sales task/Lead serialization must persist the approved resolution evidence and retire only that exact blocker; fresh human admission independently rechecks current resources.
The new financial reason has a concrete Sales consumer implication. modules/handoffs/handoffs.dto.ts:93 accepts string reason/initiator, and handleCreditReleased records reason metadata. Its helper at handoffs.service.ts:617-633 classifies solely initiator === system_unpaid; proposed system_other/failed_close_compensation falls into generic cancelled/other/lesson_scheduled presentation and paused cadence. This handler does not complete scheduling_completion_v2 or retire its task. Thus wire shape acceptance is source-backed, but truthful compensation-pending presentation and exact correlation need an owner-reviewed Sales adapter before this reason is used. Do not repurpose it as unpaid-at-lock, Lost closure, refund, paid cancellation or proof that a new slot is available. Original success still preserves reserved versus committed, invoice creation versus recorded SMS send, and separate current payment/handoff assessment.
Handback boundary
Fresh scoped inbox/ledger reads at 2026-10-03T02:17:04.394Z and 2026-10-03T02:17:04.881Z informed discovery; this review completes no runtime implementation commitment. Root is sole publisher/indexer/freshness owner. Sales runtime, ADR-0052 candidate/proof, owner drafts, production, databases, keys and providers were untouched. Prior other-flow coverage gaps remain outside this recovery slice and are not removed. Formal acknowledgment remains withheld pending aligned taxonomy/numeric layers, complete preparation/evidence/blocker rules, owner compensation/resource disposition, supported-payload coverage and assembled package review.