← All decision records

EDR 0003 Status: accepted Implementation: none

Every principal is federated, and every token is bound to a key

Marque has no local accounts and no long-lived keys. Humans authenticate through any configured OIDC issuer, workloads through their cloud's own identity, and every token is DPoP-bound so a stolen one is useless.

Authors
Theo Zourzouvillys
Date
2026-08-15
Tags
identity security foundational

TL;DR

  • No local accounts, no local passwords, no API keys. A human is whoever an accepted OIDC issuer says they are. A workload is whoever its cloud says it is.
  • Every access token is sender-constrained with DPoP (RFC 9449): the token names a public key, and using it requires proving possession of the private half. A token lifted from a log, a proxy or a laptop is not usable on its own.
  • Workloads federate, never carry static keys. A Pilot on AWS presents its task role; on GCP, its service account. Neither has an AWS access key or a GCP service-account JSON file anywhere.
  • The Leadsman is a principal too. It has its own identity and acts under an explicit delegation from the submitter, and both names are on every record it produces.
  • Approval and execution additionally require a fresh, interactive authentication — a token minted more than a few minutes ago is not sufficient to sign a marque.

Context

Marque brokers changes to production data, so its authentication is the whole of its security posture; nothing downstream re-checks who you are. Three standing positions apply almost verbatim.

ZFN-6: a bearer token grants access to whoever holds it. For a tool like this, the interesting theft is not a breach — it is a token in a shell history, a CI log, or a screenshot in a support thread. Binding the token to a key that never leaves the operator's machine removes that entire class.

ZFN-9: static cloud credentials are a documented carve-out at best. A tool whose components hold database credentials must not also be a place where cloud keys accumulate.

ZFN-38: the Leadsman is a language model reading an operator's SQL. Handing it the operator's token would make its actions indistinguishable from theirs, which is exactly the attribution failure that note is about — and the failure would surface during an incident review, when the question is whether a human or a model decided something.

There is a fourth force the notes do not cover: an approval must be an act, not a session property. If yesterday's login is enough to sign today's marque, then a laptop left unlocked is an approval authority. Approval is the one operation where re-authentication is worth the friction.

Decision

Human authentication. The client performs an OAuth 2.0 authorization-code flow with PKCE against any issuer listed in the bootstrap document (EDR-0002). The resulting identity token is exchanged at the Harbourmaster for a Marque access token. Where a deployment already runs a token service, the exchange is RFC 8693 token exchange against it; where it does not, the Harbourmaster performs the exchange itself. Either way the client code is the same.

Key binding. Every access token carries cnf.jkt, and every request carries a DPoP proof over the method and URL. The client's private key is held in platform-backed hardware where the platform has it (Secure Enclave, TPM) and in a file with restrictive permissions where it does not. A token with cnf.jkt presented as a plain bearer is rejected — a token that committed to proof-of-possession at mint time must be used that way, or the binding is decoration.

Workload authentication. Components authenticate as themselves:

Runtime Presents Exchanged for
AWS (ECS/EKS) task-role signature or the pod's projected token a Marque workload token
GCP (Cloud Run/GKE) metadata-server ID token a Marque workload token
Elsewhere any OIDC token from a configured issuer a Marque workload token

Marque itself stores no cloud credential. A deployment that has to use a static credential records it as a carve-out with an owner and a review date, per ZFN-9.

Delegated principals. When the Leadsman analyses a request it acts under a delegation from the submitter, expressed as an RFC 8693 act claim chain. Every artefact it writes names both the actor (the analyst identity, with its model and prompt version) and the principal (the submitter). A record with one name is a bug, not a shorthand.

Freshness. One operation requires an authentication no older than a deployment-configured interval (default five minutes): producing a human approver signature. An earlier version of this record also required it for executing against a critical target; EDR-0035 removed that, because it was unsatisfiable during the outages break-glass marques exist for and locked agents out of the flow escalation exists to serve. Where a deployment genuinely wants a human present at execution, the deliberate replacement is require_execution_presence, proved by an authenticator assertion rather than by a token from an identity provider. The client re-runs the interactive flow; the token carries auth_time and the server checks it. A workload principal cannot satisfy a freshness requirement at all, which is the intended answer — a machine may not approve.

Freshness is a property of signing, not of minting. A fast-path marque — from a standing order, a delegation match, or a Surveyor conforms — is not signed by a human at the moment it is minted. Its human signature was made earlier, interactively and freshly, over the artefact that authorises the shape (EDR-0029). Assembling a reference to a signature that already exists is not signing, so no freshness check applies at mint time and none is skipped. This paragraph resolves what was, until review found it, a direct contradiction with EDR-0008.

Consequences

Easier.

  • There is no credential to rotate, revoke, leak, or find in a repository. Offboarding is removing someone from the identity provider, and it takes effect within a token lifetime.
  • Attribution is exact, including for the model: "who ran this" and "what advised them" are separate columns with separate identities.
  • A deployment reuses whatever identity infrastructure the organisation already runs. Marque does not become a second directory.

Harder.

  • The identity provider is now a hard dependency for every operation. If it is down, nobody can submit or approve. Short of building a local account fallback — which would reintroduce every problem this record removes — the mitigation is that an already-signed marque stays executable (EDR-0004), so an incident in progress can be worked.
  • DPoP is more client code than a bearer token, and hardware-backed keys are platform-specific and awkward to test. The cost is real and it is paid once.
  • Freshness will annoy people. An approver signing several marques in a session will re-authenticate more than once. Making it configurable is the escape hatch; making it default-off would mean it is never on.
  • Every component needs a workload identity provisioned before it can start, which is more deployment prerequisite than a shared secret would have been.

New obligations.

  • The delegation chain is validated, not merely recorded: a nested act chain deeper than the deployment allows is rejected.
  • Model identity is versioned. Changing the model or the prompt bundle changes the actor recorded on an analysis, so an old analysis stays attributable to what actually produced it.

References

Changelog

  • 2026-08-15: Accepted.
  • 2026-08-15: Amended to scope the freshness rule to producing a human approver signature, resolving a contradiction with EDR-0008 that an expert-panel review found. See EDR-0029. The decision is unchanged.
  • 2026-08-16: Amended after the second panel's synthesis: removed the execution-freshness clause that EDR-0035 was written to retire and that this record still carried, and named require_execution_presence as the deliberate replacement.