Repository navigation
D608: a manual credit grant or deduction is the Super Admin's, through the grant service (#1308) - #1321
Merged
Conversation
…h the grant service (#1308) POST /perks/admin/credits wrote the ledger itself: any admin, no reason, no audit row, no notice, a raw index error on a reused source, and rows the grants list never showed. It now calls manualAdjust in creditGrants.ts: Super Admin only, a reason of at least 10 characters in the audit row, a note of at most 500 the member sees, idempotent on source_ref (409 already_recorded naming the row), no overdraw (400 would_overdraw with the balance), both tests inside the insert, one logAdminAction row and one inbox notice. Manual lines carry rule_key 'manual' and show in the Super Admin's grants list, marked manual. No migration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016Q3DcWsMTSxPxJa7tMeDAs
|
Preview: https://studioos-pr-1321.guillaumelauzier.workers.dev (built from e1735b5) The pull request's SPA build on a Worker with no bindings: pages and deep links work, |
guillaumelauzier
marked this pull request as ready for review
October 6, 2026 23:19
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.
Objective
POST /api/perks/admin/creditswroteperk_credit_ledgeritself, which broke D540's rule that every grant goes through one service. #1165's audit found it (area 7). The route:source_refthrough as a raw index error;This PR routes the adjustment through
services/creditGrants.ts.Closes #1308
Implementation
manualAdjustinservices/creditGrants.ts. The route checksrequireSuperAdminand hands the rest to the service.delta: a non-zero whole number, at most 100,000 either way. That is the boundadmin_credit_rules.tsuses. A string such as"10"is refused.reason: at least 10 characters, the sharedCREDIT_REASON_MINfloor. It is recorded in the audit row, not shown to the member.note: what the member sees, at most 500 characters. A longer one is refused, not cut. With no note it reads "Credits added (or deducted) by the Axal team".source_ref(defaultadmin:<id>:<ISO>). A ref already on that member's ledger, of any kind, is a 409already_recordedwith the existingledger_id. That includes a rule grant's ref, so a manual line can't double a reward.would_overdrawwith thebalance.INSERT, so two adjustments racing can't both pass.rule_key = 'manual': agrantline for a grant, anadmin_adjustline for a deduction;logAdminActionrow,credit_manual_adjust;credit_manual_adjust.The route returns refusals through
refuse():invalid_user,invalid_delta,reason_too_short,note_too_long,invalid_source_ref,would_overdraw;user_not_found;already_recorded.The grants list (
GET /api/admin/credit-rules/grants):manual: true;credits;revoke:<id>) are left out, though revoking a manual grant also writes amanualadmin_adjustline.No migration.
rule_key(migration 381) is the marker, so 414 is not taken.Docs: new
decisions/D608.md, and a one-line pointer in D540.Files changed
cloudflare-worker/src/services/creditGrants.ts:manualAdjust,MANUAL_RULE_KEY, the bounds.cloudflare-worker/src/routes/perks.ts: the/admin/creditshandler only.cloudflare-worker/src/routes/admin_credit_rules.ts: the grants list only.cloudflare-worker/test/manual_credit_adjust_d608.test.ts(new, 9 tests).frontend/test/perks_live.test.mjs: its source pin on the old route's message now points at the service's in-insert balance check.documentation/architecture/decisions/D608.md(new),D540.md(pointer).Testing
npm run build, thennpm run test:drift > drift.log 2>&1; echo EXIT=$?, gives EXIT=0.source_refof either sign, and a rule grant's ref, each a 409 that writes nothing;?user_id=.Risks
wrangler.tomlchange.api.perkGrantCreditsexists and nothing uses it.reason.Dependencies
D540 (#1103), and the grant service. #1165 area 7 item 2 (the screen's design) is separate.
Agent
S08 · Claude Code
Review requested
S1.
🤖 Generated with Claude Code
https://claude.ai/code/session_016Q3DcWsMTSxPxJa7tMeDAs
Generated by Claude Code