Internal Docs/Registration & KYC — the requirements (conformance spec)
registration & KYC · requirements · conformance spec

the intended model — requirements

What a card program must do when it requires the cardholder to register and/or pass KYC before a card can be used — written as a conformance checklist. Each requirement is observable behaviour with explicit pass/fail criteria, so you can walk any proposed fix against it and know whether it's complete. Requirements are stated at the level of what the holder, the partner and the operator see — never in terms of today's field names (those sit in small as-built notes for traceability). SETTLED requirements are testable now; OPEN ones carry both candidate outcomes and convert to tests the moment a decision lands.

WORKING DRAFT.  Behavioural requirements + master decision table + consumer contracts + coverage map. Use as the bar every fix must clear.
00

how to use this

  • To validate a fix: walk it against every settled requirement's accept-criteria. For each open requirement, confirm the fix implements the branch the decision picked. If all pass, the behaviour is complete.
  • Each requirement (REQ-xx) is a behavioural rule + Given/When/Then accept-criteria + references (decision-table rows · consumer contracts) + a status.
  • The master decision table (§03) is the coverage backbone — the exhaustive (design × action × amount) → outcome grid the requirements cite. Consumer contracts (§02) (C-xx) are the obligations of each surface that shows or acts on the state.
  • The coverage map (§06) ties every known defect and live card to the requirement that catches it — so this list is a regression guard for the real bugs, not an aspiration.
  • Altitude: requirements describe behaviour, not encoding. "Show the card as held and offer registration" is the requirement; which field carries it is a design choice (see the design).
  • Beyond behaviour: §05 flags which open decisions are ⛔ design-blocking (must be answered before a design freezes); §07 lists the non-functional invariants (audit, errors, security, migration) the design must honour.
01

model & vocabulary

Four concerns, kept separate. Each can be reasoned about and reported on its own.

concernthe questiondetermined by
Verification requirementMust the holder register / pass KYC before this card is usable?the design: requires registration and/or KYC, keyed per (program, design)
Usability stateIs this card usable yet?the card: held (in a verification sub-state) vs usable
Funding timingDoes the initial load land at activation, or at verification?follows usability — deferred while Pending, immediate when usable
Consumer signalWhat does each surface (holder, operator) see and do?the card's state + reason — see the consumer contracts (§02)

Usability is one binary axis — held vs usable (an open card is simply never held) — but "held" decomposes into the verification sub-states below.

verification sub-states — "Pending" is not one state

A held card sits in exactly one of these. axis enforces only the binary (held vs usable); the sub-state — the reason — is the verdict authority's (core's), surfaced to consumers. None of these are processor card-statuses.

Not activated Awaiting registration Awaiting KYC Verified · usable  ·  off-ramps: Registration failedKYC failed → OPEN-4
sub-statemeansenforced asconsumers showexit →
Awaiting registrationactivated & held; the holder hasn't registered the cardheldheld; offer the registration pathregisters → Awaiting KYC (KYC design) or Verified (reg-only); fails → Registration failed
Registration failedthe holder attempted registration and it was rejectedheldheld; reason = registration failedOPEN-4
Awaiting KYCregistered; required KYC not yet satisfiedheldheld; awaiting KYCpasses → Verified; fails → KYC failed
KYC failedthe holder attempted KYC and failedheldheld; reason = KYC failedOPEN-4
Verifiedregistration (+ any required KYC) satisfiedusableusable; deferred funds load once (or short → OPEN-7)terminal — the card is now Active & usable

Reg-only designs never enter Awaiting KYC / KYC failed. Open designs enter none of this (activate → usable). A card that simply never progresses — the holder never acts — is the "never arrives" half of OPEN-4, distinct from an explicit failure. A failure leaves axis's held state unchanged — "failed" is the verdict authority's reason, read on demand (C-STATE), never pushed to axis; only a success (the release event) flips the card usable, so a retry just succeeds through the normal release (REQ-C6).

Rule 0 — the requirement belongs to the design; the state belongs to the card. A program can hold designs with different requirements, so "this program requires verification" is never meaningful — only "this design requires verification," evaluated per card. Verification-required ⇔ registration ∨ KYC. Registration is the entry; KYC nests inside it, graduated by amount (screening · CDD 1–3). Verification attaches to the person, not the card.
Principle — money follows usability, and exactly once. No funds move for a card while it is Pending Verification; the initial load is deferred and lands only when the card becomes usable. An open card funds immediately. A card is funded exactly once for that initial load — a verification result delivered more than once must not double-fund it.
02

consumer contracts

What each surface that shows or acts on the verification state MUST do. Behavioural — encoding is the design's choice. Referenced by the requirements as C-xx.

C-STATEThe platform makes a card's verification state distinguishable — the held/usable fact on the card, the precise reason from the verdict authority on demand.
  • From the card a consumer can tell: open vs held vs usable; that it needs registration and/or KYC; and the deferred amount if any.
  • The precise sub-state — awaiting-registration vs registration-failed vs awaiting-KYC vs KYC-failed — is the verdict authority's (core's), obtainable on demand. It is not all required on the card object; the card need only carry enough to be held correctly and route the holder.
  • No two fields or endpoints may report conflicting answers to "does this need verification."
as-built: the card carries requiresKyc / kycLocked / deferredLoadAmount — KYC-only, so even "held + needs registration" is wrong today (DEV-890); a second, conflicting field exists (DEV-842/885); the failed sub-states aren't surfaced at all.
C-FUNNELThe cardholder site holds back a verification-required card and offers the path to complete it.
  • Given a card whose design needs registration and/or KYC, not yet verified When the holder views it Then it is shown as held and the holder is offered the registration / verification path.
  • This fires for registration-only designs as well as KYC designs — both are "verification required."
  • When the card is verified Then it behaves like an ordinary usable card.
as-built: card-balance / shoppingcentre.cards gate on a KYC-only signal, so registration-only cards are never prompted (DEV-890).
C-ADMINSetldHub shows that a card is held and why, and never presents not-yet-loaded funds as spendable.
  • A pending card shows as held with the reason — awaiting registration, awaiting KYC, or both.
  • Deferred (not-yet-loaded) funds are never shown as a spendable/available balance. Beyond that — show the real (zero) balance, mask it, how prominently to surface the deferred amount, whether SetldHub differs from the cardholder site — is an open display choice (OPEN-6).
as-built gap: SetldHub keys this off a KYC-only signal, so a registration-only held card is treated as an ordinary card — labelled "Registration Required: No" and displayed unlike a KYC-held card. The mislabel and the inconsistency are the bugs; the right held-card display itself is OPEN-6. DEV-890 / DEV-685.
C-VERDICTThe compliance authority is the single source of "is verification satisfied," answered live at money-movement.
  • Funds move only on a current "verified for this holder and this amount" — never a cached verdict.
  • The verdict is amount-aware: a load needing a deeper level than the holder holds does not pass.
  • For a registration-only design there is no KYC level — "verified" means registration is confirmed; the amount-band check applies only where the design requires KYC.
  • If the verdict is unavailable (authority down or times out), the operation fails closed — no release, no money — never fail-open.
as-built: core-service owns the verdict (person KYC results, graduated by amount); axis reads it.
03

master decision table

The exhaustive backbone. Every requirement cites these rows. "—" = not applicable. Open cells defer to §05.

#designactionamountusability afterfundsconsumers must show
R1open (reg f, kyc f)activateActive & usablenoneordinary card
R2openactivateWithLoadAActive & usableload A nowordinary card
R3reg-only (reg t, kyc f)activatePending Verificationnoneheld + registration path; admin "registration required: yes"
R4reg-onlyactivateWithLoadAPending Verificationdefer Aheld + registration path; deferred A recorded, not shown as spendable (display → OPEN-6)
R5kyc (kyc t)activatePending Verificationnoneheld + verification path
R6kycactivateWithLoadA within bandPending Verificationdefer Aheld + verification path; deferred A recorded (display → OPEN-6)
R7kycactivateWithLoadA over bandPending Verificationdefer Aheld + verification path (KYC); deeper level required before funds land
R14verification-required, holder already verifiedactivate / activateWithLoad(A)Active & usablenone / load A nowordinary card (re-issue / replacement)
R8verification-requiredverify / release OPEN-0deferred AActive & usableload A — once (or short → OPEN-7)usable; balance shown
R9usable (verified / open)loadAActive & usableload A nowordinary card
R10pendingloadAOPEN-2reject — or extend deferredper decision
R11usableloadA over bandOPEN-3re-gate — or proceedper decision
R12pending sourcereplace / transferdeferrednew Pending, source retiredcarry deferred — onceheld carries to the new card
R13usable sourcereplace / transferbalancenew usable, source retiredmove balance — onceordinary card
04

requirements

Behavioural rules with pass/fail criteria. SETTLED = testable now · OPEN-n = pending a decision (§05) · SECURITY = must-fix invariant.

A · Activation
REQ-A1An open-design card is usable immediately on activation; bare activate moves no money.settled
  • Given an open design When activate Then the card is Active & usable and no funds move.
Table: R1 · Consumers:
REQ-A2A verification-required card is held after activation — Pending Verification, no money moved — unless the linked holder is already verified.settled
  • Given a design needing registration and/or KYC, holder not yet verified When activate Then the card is Pending Verification (suspended at the processor — the real enforcement) and no funds move.
  • True for registration-only designs, not just KYC.
  • Exception: if the holder is already linked and verified for this design (a re-issue / replacement), the card activates directly to usable — no hold. The hold is for unverified holders only.
Table: R3, R5, R14 (already-verified) · Consumers: C-STATE
REQ-A3A pending card's held state and reason are visible to every consumer.settled
  • Given a Pending card When any consumer reads it Then it can tell the card is held and why (registration / KYC / both).
Table: R3–R7 · Consumers: C-STATE, C-FUNNEL, C-ADMIN
REQ-A4Re-activating a card never disturbs its state or re-triggers funding.settled
  • Given an already-activated card (usable or held) When activate Then its state and funds are unchanged. Whether the call errors or returns an idempotent success is an API choice, not fixed here.
Table: — · Consumers:
as-built: rejects with IllicitModificationException — the reject-vs-idempotent shape was assumed, not specified.
REQ-A5Bare activate on a fund-after-verification design — behaviour pending decision.open-1
  • With no amount, a fund-after-verification design has nothing to load when it becomes usable. See OPEN-1 for the candidate outcomes.
Decision: OPEN-1
B · Loading & funding
REQ-B1A load on a usable card checks funds, then funds the card now.settled
  • Given a usable card When load A Then a balance check runs and, if it passes, A lands on the card.
Table: R9 · Consumers:
REQ-B2An activate-with-load on a verification-required card defers the load; no money moves until verification.settled
  • Given a verification-required design, holder not yet verified When activateWithLoad A Then the card is Pending, A is recorded as the deferred load, and no money moves.
  • Exception: an already-verified holder activates-and-loads now (no defer), like an open card — REQ-A2's carve-out on the load path.
  • A card holds one deferred-load record (amount and currency). If OPEN-2 resolves to "extend", extension updates that one record — so "funded exactly once" (REQ-B4) is once in total, not once per parked entry.
Table: R4, R6, R7, R14 · Consumers: C-STATE
REQ-B3No path commits a load — now or deferred — without a balance check where the money actually moves.settled
  • An immediate load is checked at request time; a deferred load is checked at verification, before the funds move.
  • A deferring request MAY also validate fundability up front as an early signal, but the binding check is at fund-movement.
  • If the at-verification check fails (funds short by release time) Then the shortfall is a reported outcome — never a silent drop and never a strand; the card is still verified. Exact handling (release-unfunded-and-notify vs hold-the-load) is OPEN-7.
Table: R8, R9 · Consumers: C-VERDICT · Decision: OPEN-7
REQ-B4An initial load funds the card exactly once.settled
  • Given a card with a deferred load When a verification/release signal arrives more than once (retry, duplicate, concurrency) Then the card is funded once and only once.
  • Concurrent operations resolve to one outcome: a release racing a load funds once (not both); a release racing a replacement funds the destination once. (The locking / atomic-claim mechanism is §07.)
Table: R8, R12 · Consumers:
REQ-B5Loading a card that is still Pending — behaviour pending decision.open-2
  • A load must never succeed without the funds reaching the card. Reject vs extend-the-deferred is OPEN-2.
Table: R10 · Decision: OPEN-2
REQ-B6A later load that crosses into a higher KYC band — re-gate vs proceed, pending decision.open-3
  • If a load pushes a usable card into a higher amount band, must it re-verify first? OPEN-3.
Table: R11 · Decision: OPEN-3
C · Release / verification
REQ-C1A verification event releases the card: it becomes usable and any deferred funds load — exactly once.settled
  • Given a Pending card When registration (and any required KYC) completes Then the card becomes usable and the deferred load lands, once.
  • Usability flips on the same trust as the money: an authorised release (REQ-C4 / OPEN-0) confirmed against the live verdict — not on any inbound signal. A stale or spoofed nudge makes the card neither usable nor funded.
Table: R8 · Consumers: C-FUNNEL, C-VERDICT · Depends: OPEN-0
REQ-C2No entry path can strand a card — every Pending card has a working route to usable.settled
  • Given a card made Pending by any path (plain activate, activateWithLoad, group, transfer) When verification completes Then it releases cleanly — never a permanent suspend.
Table: R3–R8 · Consumers: C-FUNNEL · Guards: D1, D2, stranded cards, DEV-890
REQ-C3Money moves on release only on a fresh, amount-aware "verified" — never cached.settled
  • Given a release/verify signal When funds would move Then the compliance authority is asked, live, "verified for this holder and amount?" — a stale/replayed/wrong signal funds nothing.
Table: R8 · Consumers: C-VERDICT
REQ-C4The release / verify operation is a privileged capability, authorised against the card's owning partner and the named holder — not the caller's own scope.security
  • Given a release call (the legitimate caller is a cross-partner orchestrator) When it names a card + a holder Then the card is resolved and authorised against the card's owning partner / the holder's entitlement — quoting an arbitrary card id or person id must not release another holder's card.
  • It is a privileged role (the release orchestrator only), not the broad partner role — and "caller's own scope" is the wrong test, since the legitimate caller owns no partner scope.
Consumers: C-VERDICT · Depends: OPEN-0 · Guards: the release-path IDOR (DEV-827 class)
REQ-C5Verification fails or never arrives — fate pending decision.open-4
  • A card sits Pending; the holder fails or never completes. Stay pending / expire / partner-driven — and the held-card expiry-anchor interaction — is OPEN-4.
Decision: OPEN-4
REQ-C6A verification failure leaves the card held — only a success releases it, so a retry recovers normally.settled
  • A failure does not change axis's state — the card stays held. "Failed" is the verdict authority's reason, read on demand (C-STATE); axis is never pushed a failure verdict and caches none.
  • Given a held card When the holder retries and verification succeeds Then the normal success release (REQ-C1) flips it usable — failure is not terminal (its terminal fate is OPEN-4).
Sub-states: Registration/KYC failed (a core reason, not an axis state) · Consumers: C-STATE, C-VERDICT · Decision: OPEN-4 (terminal fate)
D · Replacement / transfer
REQ-D1A replacement carries the source's usability and funding state to the new card; the source is retired; no re-verification.settled
  • Given a usable source with a balance When replaced Then the balance moves to the new card (usable); the holder is already verified, so no re-verification.
Table: R13 · Consumers:
REQ-D2A pending source carries its Pending state and deferred funds to the replacement, releasing on verification; funded exactly once across the move.settled
  • Given a Pending source (deferred, never funded) When replaced Then the Pending state + deferred load carry to the new card; a retried/concurrent move must not fund the destination twice.
Table: R12 · Consumers: C-STATE · Guards: double-fund risk
E · Consumer signal & display
REQ-E1A held card is exposed as needing registration and/or KYC — never as "no verification required."settled
  • Given a registration-only held card When a consumer reads it Then it sees the card needs registration — not "no verification required." (The finer awaiting-vs-failed sub-state comes from the verdict authority — C-STATE.)
Consumers: C-STATE · Guards: D4, DEV-890
REQ-E2The cardholder registration path fires for every verification-required, not-yet-verified card — reg-only included.settled
  • Given a held reg-only card When the holder visits the cardholder site Then they are offered the registration path.
Table: R3, R4 · Consumers: C-FUNNEL · Guards: DEV-890
REQ-E3SetldHub labels the held reason correctly and displays a held reg-only card the same as any held card.settled
  • Given a held reg-only card When SetldHub shows it Then it reads "registration required" and is displayed like a held KYC card — deferred funds not shown as spendable.
Consumers: C-ADMIN · Display: OPEN-6 · Guards: DEV-685, DEV-890
REQ-E4Every "requires verification" signal derives from one source — multiple emitted fields are allowed, but they can never disagree.settled
  • Given any card When two fields or endpoints report whether it needs verification Then they agree, because both derive from a single source of truth. (Derived fields may persist for compatibility — this does not mandate collapsing to one field; they must just never diverge.)
Consumers: C-STATE · Guards: DEV-842 / DEV-885 (dual-field conflict)
F · Group activation
REQ-F1Group activation applies the per-card rules to every card uniformly.settled
  • Given a group activation — a batch is a single design (enforced precondition) — When activated Then every card follows the same per-card rules above (all-open or all-verification-required).
Table: R1–R7 · Consumers:
REQ-F2A verification-required batch moves no money up front; it validates the total deferred amount, then funds each card at its own verification.settled
  • Given a verification-required batch When activated Then no funds move up front; the total deferred amount is validated up front (advisory — the binding check is per-card at each card's release, REQ-B3); per-card funding happens at each card's verification.
  • Partial failure: if the up-front total check fails, the whole batch is rejected (no card activates). If a card fails mid-batch, its outcome is independent and reported — a partial failure neither strands the rest nor silently drops the failures.
Table: R4, R6, R8 · Consumers: C-VERDICT
G · Safe migration
REQ-G1Changing how the verification state is encoded rolls out with no window where a card is mis-displayed.settled
  • Given a change to the signal encoding When it ships Then consumers tolerate old and new and are deployed first (expand/contract) — at no point does a card show the wrong held/usable state.
  • Assumes every branching consumer is internal — pending the external-consumer investigation (the open Investigate card).
Consumers: C-STATE, C-FUNNEL, C-ADMIN
05

open decisions

Each carries both candidate outcomes so it becomes a hard test the moment it's decided. ◆ = needs product / Grif · ⛔ = design-blocking (a design can't freeze until it's answered); unmarked ones are safely parameterised. The design §08 tracks the same set — numbering isn't 1:1 (it carries OPEN-0; this adds OPEN-6/7).

OPEN-0 ◆ ⛔

The release operation — split it, and who may invoke it

"Release" is today an overloaded endpoint (a single verifyIndividual branched on a person id: with it → release = activate + load; without → a KYC inquiry/screening that moves no money). It is reachable by two legitimate callers — core-service and card-balance-api (forwarding the cardholder) — neither of which is the owning partner. The whole release contract (REQ-C1–C4) rests on resolving this.

Split it — a dedicated release operation (orchestrator-only role), separate from the cardholder-facing inquiry/screening.
Keep overloaded, gate the release branch by role + card scope.
Blocks: REQ-C4 (the entire auth model) and the release contract — a design can't freeze without it. Lean: split. → design + Grif
OPEN-1 ◆ ⛔

Bare activate on a fund-after-verification design

No amount, so a fund-after-verification design has nothing to load when it becomes usable.

Require activateWithLoad — amount captured at activation, deferred.
Allow bare activate — becomes usable with no funds; funds arrive via a later load.
Program-default amount — activate defers a configured standard load.
Parameterizes: REQ-A5, table R3/R5. Need: the real partner flow. → Grif
OPEN-2

Loading a card that is Pending Verification

What does load do when the target isn't usable yet? (It must never succeed without funds reaching the card.)

Reject — "card pending verification."
Defer / extend — add to the pending amount that loads at verification.
Parameterizes: REQ-B5, table R10. Lean: reject, for a clear contract — unless top-up-before-verification is a real need.
OPEN-3 ◆

Does a later load re-gate an already-usable card?

A load that pushes a verified card into a higher amount band — re-verify first, or not?

Re-gate — hold the crossing load until the deeper KYC clears.
Proceed — banding applies only to the initial load.
Parameterizes: REQ-B6, table R11. Need: compliance intent. → Grif
OPEN-4 ◆ ⛔

Verification fails or never arrives

A card sits in Registration failed, KYC failed, or simply never progresses (the holder never acts). What is its fate — and what do we tell the partner? The explicit-failure and never-arrives cases may warrant different answers.

Stay pending indefinitely.
Expire / cancel after a window, with notification.
Partner-driven — an explicit action to resolve it.
Parameterizes: REQ-C5. Cross-feature: card-expiry counts from the activation date, so a held card burns its expiry window while unusable (DEV-819). Need: product + compliance. → Grif
OPEN-5

Retire the dead fund-timing flags?

Funding follows usability; the per-design fund-timing flags have no readers in any service.

Ignore + document now, schedule removal with the schema owner.
Keep — only if a real case needs funding decoupled from usability.
Lean: retire (cross-schema, core-owned). Guards: D5.
OPEN-6 ◆

What a held card displays — balance & deferred amount, per surface

A Pending card has no spendable funds yet (real available ≈ 0) and a deferred amount to come. The settled rule is only: never present the deferred amount as spendable, and show reg-only the same as KYC. Beyond that, what should each surface actually show? (Wrongly asserted as settled in an earlier draft — it isn't.)

Mask the balance (hidden / ***), surface the deferred amount.
Show the real (zero) available + the deferred amount, clearly separated.
Differ by surface — cardholder site minimal / non-confusing; SetldHub shows the full truth (operator tool).
Parameterizes: C-ADMIN, C-FUNNEL, REQ-E3. Need: UX / product. → Grif
OPEN-7

Deferred load, but funds short at release

Verification completes (the card is now usable), but the funding source can't cover the deferred load (parked for days/weeks). Settled invariant: the card becomes usable and the shortfall is a reported outcome — never a strand or a silent drop (REQ-B3). What then?

Release usable, load fails + notify — verified/usable with no balance; the partner retries the load.
Hold the load for retry — usable, but the deferred load stays pending a fundable retry window.
Parameterizes: REQ-B3. Need: product. → Grif
06

coverage map — every known bug → the requirement that catches it

If a requirement here is met, the listed defect/card cannot recur. This is what makes the list a regression guard.

defect / cardwhat it iscaught by
D1activate strands a verification-required card (no release route)REQ-C2
D2pure load on a locked card defers into a dead endREQ-C2, REQ-B2
D3locked designs skip the up-front balance checkREQ-B3
D4the consumer signal reports KYC-only, hiding registration-only locksREQ-E1, REQ-E2, REQ-E3
D5dead fund-timing flagsOPEN-5
D6design-config lookup ignores soft-delete / keys on design aloneRule 0 (keyed per (program, design))
DEV-890reg-only cards lock with no path out (funnel never fires)REQ-C2, REQ-E1, REQ-E2, REQ-E3
DEV-823lock applied to reg-only — but only lock-ON, never lock-OFFREQ-A2 (on) + REQ-C2 (off) + REQ-E1/E2/E3 (reg-only surfaced)
DEV-842/885kyc-level API returns conflicting requiresKyc/kycRequiredREQ-E4
stranded cardsprod cards held with no release rowREQ-C2, REQ-B4
release IDORcross-tenant release/fund by card idREQ-C4
The test it all has to pass. A registration-only design (Touchwood): activateWithLoad → held + deferred (R4); the holder is prompted to register (REQ-E2) and SetldHub displays it as held, reading "registration required" (REQ-E3); registration completes → released and funded once (REQ-C1, REQ-B4); a cross-tenant caller cannot release it (REQ-C4); and none of this strands the card (REQ-C2). That single walk-through exercises the whole spine.
07

non-functional invariants & out-of-scope

Stated as invariants (what must hold), not mechanism (how). The design picks the how.

  • Auditable. Every state transition and every release attempt — allowed and denied — is recorded with the caller's identity. Given the IDOR history, denied releases especially.
  • Defined, non-leaking error outcomes. Every reject has a defined outcome that leaks no internals: load-on-pending, release-not-authorised, release-of-unknown-card, verdict-not-satisfied, funds-short-at-release. (The repo's RestServlet currently leaks raw exception detail — the unhappy path is security-relevant.)
  • Funded-once is keyed. The fund-once guarantee (REQ-B4 / D2) rests on an idempotency key — keyed per deferred-record, honoured for the record's life, and surviving a card-id change across replacement. The key's existence + scope are required here; its encoding is design.
  • Single-currency. A deferred load, an extend (OPEN-2), and a replacement are single-currency — a currency mismatch is rejected, not silently converted (FX is out of scope here).
  • Detectable. A card entering a failed / stranded sub-state, an unfunded-at-release, or a spike in denied releases raises an alert — so the next strand is caught, not found months later.
  • Security beyond REQ-C4. Authorise the inquiry / screening branch too (PII); scope the verdict read (axis→core person lookup); treat the person id in a release as authorisation-relevant, not a free parameter; the release nudge tolerates replay (a stale nudge moves nothing — REQ-C3) and is rate-limited.
  • Existing state & data are migrated. The fix must remediate the already-stranded prod cards and migrate the existing parked-load rows into the new record shape — not only prevent recurrence (REQ-C2) and roll the signal out safely (REQ-G1). State + data migration, not just code.

Genuinely design-phase (named, not specified here): the idempotency-key mechanism; transaction isolation / locking for the concurrency invariants (REQ-B4 + release-vs-load and release-vs-transfer races); the Tribe ≤6-concurrent cap on batch funding; and the latency a live verdict call adds to every fund-movement.