Documentation
¶
Overview ¶
Package credentialinvalidate is the single entry point for credential revocation events: it bumps the user's authz_epoch, revokes all active sessions, and revokes all refresh chains in one ambient transaction.
AI-robust archtest (all Hard post #1033, see tools/archtest/credential_invalidate_funnel_invariants_test.go + tools/archtest/fence_token_mint_funnel_test.go):
- CREDENTIAL-INVALIDATE-FUNNEL-01: session.Store.RevokeForSubject callers ⊆ {this pkg, store impl, storetest, *_test.go}
- USER-AUTHZ-EPOCH-BUMP-FUNNEL-01: UserRepository.BumpAuthzEpoch callers ⊆ {this pkg, repo impl, conformance, *_test.go}
- REFRESH-REVOKE-USER-FUNNEL-01: refresh.Store.RevokeUser callers ⊆ {this pkg, store impl, *_test.go}
- CREDENTIAL-INVALIDATE-UPSTREAM-CALLER-01: Invalidator.Apply callers ⊆ {this pkg, authzmutate, identitymanage, sessionrefresh, rbacassign, *_test.go}
- FENCE-TOKEN-MINT-FUNNEL-01: credentialfence.Mint callers ⊆ {this pkg, storetest/conformance, *_test.go}
The three mutation methods take a credentialfence.FenceToken capability proof (#1033). Apply mints a FenceToken via credentialfence.Mint and passes the same value to each of the three calls. Combined with the type-system seal on FenceToken (external packages cannot implement the interface or construct the unexported impl) plus the runtime nil-guard (credentialfence.MustHave at the top of every mutation impl), the upstream half of the funnel is now Hard: external packages cannot produce a FenceToken value, so the mutation methods cannot be invoked from outside the funnel even at compile time. See ADR §A16 for the closure proof and threat-matrix re-evaluation.
Apply must be called inside an ambient transaction (txCtx derived from persistence.CellTxManager.RunInTx). All three operations commit atomically; call order is irrelevant to correctness.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Applier ¶
type Applier interface {
Apply(ctx context.Context, tid tenant.TenantID, subjectID string, event session.CredentialEvent) error
}
Applier is the credential-invalidation funnel surface used by callers that need substitutability for testing (e.g. sessionrefresh injects a spy in unit tests). The sole production implementation is *Invalidator.
AI-robust archtest dependency: this interface MUST live in the credentialinvalidate package — not in any caller package — so info.Selections resolves Apply via this package, making call-sites detectable by CREDENTIAL-INVALIDATE-UPSTREAM-CALLER-01. A caller-package local interface (the pre-#1196 sessionrefresh.invalidatorApplier form) would resolve Apply via the caller package, hiding the callsite from the callsite-level scan and creating a Soft channel. Keep the interface here.
tid is the tenant that scopes the mutation; callers must provide it explicitly (PR-2a philosophy: no implicit ctx-read inside the funnel). Passing an empty or invalid TenantID returns an error (fail-closed; repo methods require a valid tenant).
type Invalidator ¶
type Invalidator struct {
// contains filtered or unexported fields
}
Invalidator is the single entry point for the credential-revocation trifecta: bump user authz_epoch + revoke sessions + revoke refresh chain. All callers must go through Apply; direct calls to the underlying stores are enforced by archtest funnels (see package-level godoc).
func New ¶
func New(users ports.UserRepository, sessions session.Store, refreshStore refresh.Store) (*Invalidator, error)
New constructs an Invalidator, fail-fasting on nil deps (including typed-nil).
func (*Invalidator) Apply ¶
func (i *Invalidator) Apply(txCtx context.Context, tid tenant.TenantID, subjectID string, event session.CredentialEvent) error
Apply executes the three credential-revocation operations inside the ambient tx carried by txCtx. The operations are ordered for short-circuit on error:
- BumpAuthzEpoch — invalidates all future tokens by advancing the epoch
- RevokeForSubject — marks active sessions dead
- RevokeUser — marks all refresh chains dead
All three operations commit atomically when the surrounding tx commits. Order is defined only for short-circuit predictability; correctness does not depend on the order.
tid is the tenant that scopes the BumpAuthzEpoch write. Callers must provide it explicitly; the funnel no longer reads tenant from the context (PR-2a: non-JWT callers such as rbacassign/service-token and the refresh-reuse cascade have no tenant in ctx, which previously caused 500 errors).