ADR-036: Fail-closed session identity; JWT at logon, mapped CompIDs only
Status: Accepted Β· State: YU10-fix-ingress
Contextβ
A SenderCompID is an identifier, not proof of identity. The existing entitlement machinery
(EntitlementGate.resolve) validates a JWT and returns a ResolvedPrincipal designed to be
resolved once and reused. The REST path's risk.entitlement.enforced flag defaults to false to
keep the token-less UI working; a compatibility property of an existing surface.
Decisionβ
- Logon authenticates:
Password(554)carries a JWT (the same tokens the dev-token endpoint mints); the acceptor calls the existingEntitlementGate.resolveonce at logon and pins theResolvedPrincipalto the session. No per-message resolution. - CompID must be mapped:
FIX_SESSION_ACCOUNTSis a complete allowlist binding each CompID to exactly one account. Unmapped CompID, absent/invalid JWT, or a JWT whose principal is not entitled to the mapped account β logon rejected. There is no fallback account. - Fail-closed regardless of the REST flag:
risk.entitlement.enforcedcontinues to govern the REST path only. A brand-new ingress surface has no installed base to keep compatible, so it starts closed. - Cluster-internal endpoint: the acceptor port is not routed through ingress and has no public exposure; kind exposes a NodePort for test clients. The deployed session profile is plaintext TCP inside the cluster boundary; acceptable precisely because the endpoint does not cross that boundary.
Alternatives consideredβ
- CompID-only identity (no credential): rejected; any network-reachable client could claim a mapped CompID.
- A parallel FIX-specific credential store: rejected; the JWT infrastructure, entitlement resolution, and account model already exist; a second credential system adds surface without adding strength.
- Demo-account fallback for unmapped CompIDs: rejected; it converts an unknown external identity into a valid trading account silently.
Consequencesβ
- Session identity strength equals the JWT secret's strength, shared with the REST path; one credential system to operate and rotate.
- The pinned principal lives for the session; re-authentication is a new logon.
- Any future public exposure of the port is gated on transport security (TLS/mTLS) as a precondition, recorded here as the boundary this state deliberately does not cross.