zeekay 6df3b6d466 account: derive the payer from the signed claim, not the environment
v0.1.0 inferred who pays from PERSONAL_BILLING_ORGS — one boolean per org,
read independently by ai and commerce, with a default that lied when unset.
Two layers consulting "the same" rule could disagree, and did: the grant
landed on the org account while the gate read the person's, so a funded org
402'd its own members.

Replace the inference with the credential's own signed statement. IAM mints
`billing_account` at the identity boundary (iam/object/billing_account.go);
the gateway validates it, strips any client copy, and mints
X-Billing-Account-Id from it. Payer parses that claim and stops guessing.
A signed claim cannot be forged by the caller it describes; the User.Type
inference it replaces could be.

The rule is now a pure function of the credential and reads no configuration,
so every layer that imports this package answers identically by construction.
The fallback resolves a pre-claim token exactly the old way — and the old way
is what the claim states for a new one, so the two agree for every principal
that is not forging. It deletes with SignupOrg when the last such token expires.

An Account is owned by a Person, an Org, or a Project; (Org, Subject) is the
money's address. Attaching an account to a holder stays commerce's binding
model — this package answers only which account is the default when nothing
is attached.
2026-07-16 13:44:49 -07:00
S
Description
pull mirror of github.com/hanzoai/account
166 KiB
Languages
Go 100%