Repository navigation
feat(gateway): R13 reservation ISSUE + READ routes — server terms only, exact money; 503 until store, exact ceiling and payer binding exist - #410
Draft
LamaSu wants to merge 7 commits into
Conversation
…ly, exact money; 503 until wired) This is R13's other half over HTTP. #402 lets accept CONSUME a reservation; this lets a principal ISSUE one and READ its own. - POST /api/settlement/reservations issues for the authenticated principal. The payer is payerFor(principal) and the ceiling is requestCeiling(requestId, principal) in EXACT base units; the id, issue time and expiry are the server's. Body authority fields (reservationId, principal, payer, ceiling) are ignored. - GET /api/settlement/reservations/:id reads only the principal's own. Another principal's reservation or request gets the same 404 as a missing one. - Amounts are canonical base-unit STRINGS; a JSON number is a float and is refused. TTL 60 s to 7 days; floor 0..3; the currency must be the request's. The ceiling check is #402's exact one. - It is a money path, so the scope checker default-denies it. It answers 503 issue-not-wired until the store (#2240), an exact request ceiling and the payer-wallet binding exist. #335's authorizedCeiling is a JS number defaulting to 1000 and is not usable as money authority. Tests: 4, end to end on one durable store: issue, accept, read consumed, second accept 409. Full gateway suite: 3058 passed, 6 skipped (only the known capture suites fail to load). 9 mutation checks, all killed. pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0171FftEAfqjwbJHowVTqAbz
This was referenced Sep 24, 2026
…r13-issue-route pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0171FftEAfqjwbJHowVTqAbz
LamaSu
added a commit
that referenced
this pull request
Sep 24, 2026
…mc9-child-reservations pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0171FftEAfqjwbJHowVTqAbz
pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… time is the store's (ChatGPT review of 0b8adda) This is the #410 half of the round-2 fixes. The store half is 45d0cde, merged in e7a49b6. - M4: the assurance floor. - `requestCeiling` becomes `requestTerms(requestId, principal) -> { currency, ceilingBaseUnits, minTier }`: the request's own server-held terms, neither with a default. - The body's `minTier` can only RAISE the request's floor, never lower it. - A malformed server floor is a wiring fault, answered with a generic 500, never a default. - Production stays 503 until gateway provides exact request terms, floor included. The requests table stores no floor today, and the 503's missing list says so. - H2: the route passes no time. The store's own clock stamps issue time and expiry (the bounded lifetime), so the `now` wiring is gone. Tests: gateway R13 134/134 (+1: the floor comes from the request, the body only raises it, a malformed server floor is a 500). tsc is clean apart from the two pre-existing unrelated errors. 4 mutation checks, all killed: the body lowers the floor; the request floor is ignored (the old code); a malformed server floor is accepted; the ceiling is not the request's. pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
LamaSu
added a commit
that referenced
this pull request
Sep 29, 2026
…h the child route on the new store API (H1) This merge carries the R13 round-2 store (45d0cde) and issue route (bbe03e3). The store's API changed, so the MC 9 child route changes with it, here in the merge. That change is the ChatGPT review's H1 over HTTP. - The route names only `{ reservationId, unit }`. The STORE derives the unit's operator, n and reclaimAt from the parent's sealed deal, inside its immediate transaction, after checking the stored bytes against the sealed digest. - The route-side resolver (services/sealed-deal-parent-units.ts) is deleted, and so is its `parentUnits` option. Production's 503 now depends only on the issue wiring. - No oracle. - The whole not-found family is the SAME 404: no parent, parent not sealed, no such unit, not the unit's operator, and a corrupt stored deal (which is also logged as an integrity fault). - An unsealed parent was a 409; it is now that same 404. - The caller's OWN request is checked first. It says nothing about the parent. - The child's own request terms apply: its ceiling (it was 0) and its floor. The child's floor is max(request's, body's, parent's). - The conflict resolution in reservations-route.test.ts: the request table takes the new terms shape (ceiling and floor), with the operator's subcontract requests; the wiring keeps the operator's own payer wallet. Tests: gateway R13 139/139, reservations-route 10/10. There are new tests for: another operator's unit; forged body terms ignored; the child's own ceiling; the child's floor; a corrupt stored deal giving the same 404. 5 route mutation checks, all killed: a corrupt deal answers 500; an unsealed parent is 409; the child ceiling is 0; the child skips its own ceiling; the child floor comes from the body only. pcc-composition 8a0f4de0, goal pcc-reconciliation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…3-issue-route Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
LamaSu
added a commit
that referenced
this pull request
Sep 29, 2026
…nto feat/mc9-child-reservations Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sue-route (plain merge, no edits) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CZpG7S6AyDzTEJBQH8up44
LamaSu
had a problem deploying
to
trusted-checks
October 7, 2026 00:22 — with
GitHub Actions
Failure
LamaSu
added a commit
that referenced
this pull request
Oct 7, 2026
…at/mc9-child-reservations (plain merge, no edits) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CZpG7S6AyDzTEJBQH8up44
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Round 3 (2026-09-29): merges #402's fixes for astra's pack-45 findings
This head merges #402 @638bc3dc (A, B, C, D, each reproduced first). The R13 delta pack is
92-composition-r13-r3-6dadaf8b.md, and the full tests pass at #415's head 6dadaf8.Round 2 (the operator's cross-family review, 2026-09-28)
The operator's ChatGPT review of #402/#410/#415 at
0b8adda9was DO-NOT-SHIP. This is the #410 half of the round-2 fixes (bbe03e3); the store half is #402 @45d0cde3, merged in e7a49b6.requestCeilingbecomesrequestTerms(requestId, principal) -> { currency, ceilingBaseUnits, minTier }: the request's own server-held terms, neither with a default. The body'sminTiercan only RAISE the request's floor, never lower it. A malformed server floor is a wiring fault, answered with a generic 500, never a default. Production stays 503 until gateway provides exact request terms, floor included — the requests table stores no floor today, and the 503's missing list says so.Tests: gateway R13 134/134 (+1: the floor comes from the request, the body only raises it, a malformed server floor is a 500).
tscis clean apart from two pre-existing unrelated errors. 4 mutation checks, all killed: the body lowers the floor; the request floor is ignored (the old code); a malformed server floor is accepted; the ceiling is not the request's.Draft, stacked on #402 (R13 store). R13's other half over HTTP. #402 lets the accept route CONSUME a reservation; this lets a principal ISSUE and READ one. It cannot merge before #402 (operator decision #2240, queue item 26), WP-A (R28) and the two decisions below.
What it does
POST /api/settlement/reservations{requestId, currency, maxAmountBaseUnits: "<canonical base units>", purpose, expiresInSec, minTier?}. Returns 201 with the reservation (amounts as exact decimal strings).GET /api/settlement/reservations/:idAuthority. Every term that grants money authority is the server's:
authenticatedPrincipal).payerFor(principal), the wallet bound to that principal. A request'srequesterWalletis caller data and is never used (invariant 10).requestTerms(requestId, principal)(round 2, M4) — the principal's OWN request's server-held terms: its authorized ceiling in EXACT base units, and its assurance floor. Neither has a default. It must be the principal's own request; another principal's request is a 404, exactly like a missing one. The body'sminTiercan only RAISE the request's floor, never lower it.A body
reservationId,principal,payerorceilingis ignored (tested).maxAmountBaseUnitsmust be a canonical base-unit STRING. A JSON number (a float), "0", a leading zero, a sign, an exponent or 79 digits is 400. The ceiling check is the store's exact one (feat(db,gateway): R13 one-use budget reservations: durable store + atomic consume (SCHEMA CHANGE, approved under operator item 26) #402).issue-not-wiredand writes nothing until EVERY production piece exists: the reservation store (operator decision #2240, PR feat(db,gateway): R13 one-use budget reservations: durable store + atomic consume (SCHEMA CHANGE, approved under operator item 26) #402); exact request terms — an exact ceiling in base units AND the request's assurance floor, no defaults (fix(gateway): honest operator-relay evidence, claim authentication, immutable authorized ceiling (LO-GW-4/3a, R-06) #335'sauthorizedCeilingis a JS number defaulting to 1000; the requests table stores no floor today); and the payer-wallet binding (gateway N1/N21).⚡ Decisions this needs (not mine)
Exact request terms — ceiling AND assurance floor (gateway, fix(gateway): honest operator-relay evidence, claim authentication, immutable authorized ceiling (LO-GW-4/3a, R-06) #335 R-06). Today
authorizedCeiling = body.budget ?? 1000: a JS number with a DEFAULT, and the requests table stores no floor at all. For money authority both must be:Production stays 503 until gateway provides both (round 2, M4).
The payer-wallet binding (gateway N1/N21). Which wallet pays for a principal's reservation? It is never a body field.
Tests (
src/__tests__/reservations-route.test.ts, 4)End to end on ONE durable store: issue (201, server terms, body authority ignored) → accept (200, sealed) → read (consumed, the same digest) → accept again (409).
Authority: 401; the 404 existence-oracle closure for requests and reservations; no bound wallet is 409.
Exactness and bounds: eight malformed amounts; the TTL and floor bounds; currency mismatch; the ceiling exact to one base unit.
Production and faults: 503 on both endpoints; a thrown resolver is a generic 500.
9 mutation checks, all killed:
(Round 1 counts. Round 2 — M4 and the store clock — adds its own test and 4 mutation checks; see the Round 2 section above.)
pcc-composition 8a0f4de0, goal pcc-reconciliation.
🤖 Generated with Claude Code
https://claude.ai/code/session_0171FftEAfqjwbJHowVTqAbz