Repository navigation
Open
Labels
app/idPackage/app: id (pkgs/ or apps/ in this repo)Package/app: id (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Description
Follow-up from the #2065 design (doc/2026-10-29T12-10-00Z_design_refundable_grants_pending_transfers/, PR #2293), §6.3.
Why
The pending-transfer mechanism adds failure modes the posted design did not have: a service that dies between reserve and vest leaves the user's paid grant to expire on the TigerBeetle timeout, and a crash between writing intent and submitting the transfer leaves a row whose state disagrees with the ledger.
Scope
- Sweeper:
state=pending AND window_ends_at < now→ post (retry with backoff), then markposted;Expiredis a reconcilable state, not a loss. - Safety net:
timeout= window + slack (design recommends +72h) so a dead service cannot hold a grant forever; the sweeper must post before that, and the slack is a last resort. - Drift alarm: compare each grant's
pending_transfer_idresolution in TigerBeetle against the row state; mismatch is an alert (never a silent fix). - Late-refund fallback per §6.2: clawback attempt, on
exceeds_creditsmark the grantdebtand expose it to the gateway's grant/redemption refusal. - Metrics: pending count, oldest pending age, expired-then-reconciled count, drift count, debt total.
Depends on
The grant service issue (creates the table and endpoints this reads).
Done when
A test cluster with a killed service between reserve and vest self-heals via the sweeper, a seeded drift row raises an alarm, and an after-vest refund lands in debt rather than throwing.
Acceptance criteria
- Sweeper posts pending grants past window end (retry with backoff) and marks them posted; Expired is handled as reconcilable, never a silent loss
- Drift alarm fires on a seeded row whose TigerBeetle pending_transfer_id resolution disagrees with the row state; mismatches alert, never auto-fix silently
- After-vest refund path lands the grant in
debtand exposes it to gateway refusal (no throw) - Metrics exist: pending count, oldest pending age, expired-then-reconciled count, drift count, debt total
- Killed-service test: a service dying between reserve and vest self-heals via the sweeper
Metadata
Metadata
Assignees
Labels
app/idPackage/app: id (pkgs/ or apps/ in this repo)Package/app: id (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/creatorFiled by the new-issue-creator jobFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Activity
developing-today commentedon Oct 29, 2026
CODE-1151
dezren39 commentedon Oct 29, 2026
Intake review
Related: #2065 design (PR #2293, §6.2/§6.3), the grant-service build issue #2294 (creates the table this reads), epic #2056
Notes: Follow-up from the #2065 design; depends on #2294's grant table/endpoints existing first.
Risks: The +72h timeout slack is a last resort — a sweeper that routinely relies on it is masking a dead service.
Suggested approach: Build after #2294; test-first with the killed-service and seeded-drift scenarios from the body's Done-when.
🤖 Agent note · filed
meta/enrichedapplied. Still-live check this pass: no merged PR or fix commit explicitly resolving this issue was found; where a queue triage task owns verification, it is named in the notes.developing-today commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 40 (priority/normal). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
18 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
agent-note:v1
event: picked_up
task: 7866 (triage, repo-health-code-pilot; worker repo-worker-code; OpenChamber scheduled lane 7b47536b-c162-444c-be8a-3a9538cc4cb5)
by: openchamber-scheduled-lane
at: 2026-11-04T04:16Z
Claimed task 7866 and resumed its prior handed-off state. I will verify issue #2295, current implementation/PR state, and any active owner before routing or closing the triage.
dezren39 commentedon Nov 4, 2026
agent-note:v1
event: done (triaged; implementation dependency-blocked)
task: 7866 (triage, repo-health-code-pilot; worker repo-worker-code; OpenChamber scheduled lane 7b47536b-c162-444c-be8a-3a9538cc4cb5)
by: openchamber-scheduled-lane
at: 2026-11-04T04:19Z
Fresh verification: issue #2295 remains OPEN; no matching implementation PR exists. Current origin/main is 12fcad9, and no grant-vesting reconciler or grant-service implementation was found under pkgs/id.
Dependencies and ordering:
queue/blocked,status/blocked,user/escalated) because its RTT mesh and 6-replica TigerBeetle rehearsal require Drew-provided cloud accounts and a spend cap. Its recorded escalation names the access and cost decisions required.user/review; this is Drew's policy decision on the refund window and whether pending tokens are spendable. Active triage task 7322 owns that decision; do not choose a default here.No duplicate implementation task was enqueued while the upstream service and its blockers remain unresolved. Task 7866 is complete as triaged. Transient lifecycle labels set by this task were removed; issue classification labels remain.