You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Audit journal entries contain no caller identity fields (no sub, no act.sub, no caller/actor/principal) even when the write request carried a valid caller JWT that FinGuard verified. The ledger records what happened (key, digest, mode, detail) but never who performed it.
docs/identity-iam.md promises identity recording in two places:
§2 JWT field table: sub → "Workload / client subject; recorded as caller"
§7: "A valid JWT with act.submust journal the human, not a service-account sub, when the manifest is obo_user."
Note on expectations: the docs do not specify the full journal entry schema. The exact field names/structure below (sub / act.sub / caller) are inferred from the documented semantics ("recorded as caller", "must journal the human"). The core expectation — that the journal records who the caller was — is a direct reading of the docs; the exact field shape is the inference part.
The journal entry for the allowed write should record the caller identity — at minimum the verified sub (docs: "recorded as caller"), and act.sub when the manifest is obo_user (docs: "must journal the human") — so the ledger is attributable to a principal.
Actual Behavior
The journal entry contains only operational fields. Full field list observed:
No sub, no act.sub, no caller/actor/principal field. The same JWT was verified by FinGuard for the write (log: ext_authz allow), so the identity was available at decision time but was not persisted.
Impact
High (for audit/compliance). The journal is the accountability ledger of the product's core governance promise. Without caller identity:
The ledger cannot answer "which human/workload authorized this write" — the audit trail is not attributable, which is typically a hard requirement for enterprise/甲方 audit and compliance.
The operator console's audit role has a Sessions view (/v1/sessions, per docs/operator-console.md) whose data would be empty/meaningless without identity capture.
Possible Cause / Suggested Direction
The journal persistence layer does not currently carry caller identity from the verified JWT (the ext_authz/ext_proc decision path drops it before journal insert), or the journal schema has no identity columns yet.
Suggest: persist verified caller identity (sub; act.sub when present) on journal entries for governed writes, and document the journal entry schema in docs/ so the contract is explicit.
Summary
Audit journal entries contain no caller identity fields (no
sub, noact.sub, no caller/actor/principal) even when the write request carried a valid caller JWT that FinGuard verified. The ledger records what happened (key,digest,mode,detail) but never who performed it.docs/identity-iam.mdpromises identity recording in two places:sub→ "Workload / client subject; recorded as caller"act.submust journal the human, not a service-accountsub, when the manifest isobo_user."Environment
ghcr.io/finogeeks/finguard:0.1.0(signed digestsha256:63206295f5724a814892129ff8129f97a5ec26f4145e6450c80d5f14dce7f7a5)finguard serve+ pinned agentgatewayfinguard, RS256 + JWKS; OIDC enabled on FinGuard (FINGUARD_OIDC_ISSUER/AUDIENCE/JWKS_URL)POST /writescounter)Steps to Reproduce
Expected Behavior
(Per docs §2 / §7 semantics — field names inferred, identity recording expected.)
The journal entry for the allowed write should record the caller identity — at minimum the verified
sub(docs: "recorded as caller"), andact.subwhen the manifest isobo_user(docs: "must journal the human") — so the ledger is attributable to a principal.Actual Behavior
The journal entry contains only operational fields. Full field list observed:
{ "event_id": "5f9fe287-...", "tenant_id": "default", "key": "journal-issue-...", "digest": "d56b9fef-...", "canonicalization_version": "v1", "tier": "governed", "mode": "allowed", "detail": "upstream_succeeded", "data_classes": [], "ts_unix_ms": 1787565416152 }No
sub, noact.sub, no caller/actor/principal field. The same JWT was verified by FinGuard for the write (log:ext_authz allow), so the identity was available at decision time but was not persisted.Impact
High (for audit/compliance). The journal is the accountability ledger of the product's core governance promise. Without caller identity:
obo_usercan be executed by any valid-JWT caller, and even the fact of who called is not recorded.auditrole has a Sessions view (/v1/sessions, perdocs/operator-console.md) whose data would be empty/meaningless without identity capture.Possible Cause / Suggested Direction
sub;act.subwhen present) on journal entries for governed writes, and document the journal entry schema indocs/so the contract is explicit.Additional Context
obo_userAction Manifest does not enforceact.subon the data plane) — same root area (identity handling on the greenfield path), reported separately since the fix surfaces differ.