flex-auth/docs/decision-input-freshness.md
tegwick 6a6464fcc9
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 1s
Answer ops-warden and secrets-engine; open FLEX-WP-0021
Two cross-repo questions arrived in the flex-auth inbox and both are
answered as decision records rather than as prose in a message.

FLEX-DEC-2026-004 answers ops-warden WARDEN-WP-0034-T05. A decision
lifetime shorter than the SSH certificate TTL is meaningful, but only as
authority to issue, never as authority to use an already-issued
certificate. The pre-sign gate is the only consumer of the shorter
lifetime: no replay past expires_at, fresh Check per sign. The lever that
shortens effective access is the requested TTL as a policy input, which
is already deployed as the ttl_out_of_bounds deny. ops-warden's section
9.7.2 window through certificate TTL is correct as written and correctly
owned by the PEP; flex-auth does not want that residue moved to the PDP.

docs/decision-input-freshness.md gains the same boundary as published
contract text, so the ruling is not only in the decision log.

FLEX-DEC-2026-005 answers secrets-engine. A real policy package is
expected and flex-auth authors it here as it does for every consumer; the
reserved coordinate is secrets-engine.catalog-lane.lifecycle v1 and it
does not exist yet. Their choice not to default the pin was correct and
is endorsed explicitly. POST /v1/check is deployed but has no
estate-wide address by design -- per-consumer cluster-local pins with
default-deny ingress -- so their 2026-09-06 probe found the design
working, not an outage.

FLEX-WP-0021 carries that work: obtain the real action vocabulary from
secrets-engine, publish the package with fixtures, confirm the digest
join against a real decision record, then stand up a
flex-auth-secrets-engine pin in warn without moving the other two pins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JTbVXpEiXA7mNJVpDnEPcB

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 412054@bnt-lap001
Assistant-Session: 3968fae1-8d59-4209-9bd6-c22594b8ab19
2026-09-06 01:12:50 +02:00

4.7 KiB

Decision input freshness

Status: published Date: 2026-09-02 Standard: security-layer-model_v0.7 §9.7.2

A flex-auth decision is a join over sources that refresh independently. One number at a PDP would be either a fiction or the worst case. This document states a visibility deadline per input class, with the mechanism that bounds it.

Provenance identifies which snapshot and package a decision read (registry_snapshot_digest, policy_package_digest, directory_etag, input_claim_digests). Without those digests a deadline is unfalsifiable.

Operational bound shared by every class: an allow is never valid past lifetime.expires_at (default TTL 15m). That is the consumer-visible ceiling. The class deadlines below say when a new Check is guaranteed to see a revocation of that class of input.

Approval-claim freshness

What is joined Request-time approval and identity claims on CheckRequest.context (and related subject attributes)
Mechanism No PDP-side cache of claims. Each Check evaluates the claims as presented.
Deadline Immediate on the next Check (0). A revoked claim is visible as soon as the consumer stops sending it.
Cached allow Bounded by lifetime. Replay of a previous allow after the claim is revoked is refused once the digest no longer matches or the TTL ends.
Provenance input_claim_digests.context

flex-auth does not store or mutate the approval object (approval-engine).

Registry snapshot cadence

What is joined Protected systems, resources, subjects, groups, teams, tenants, relationship facts
Mechanism In-memory registry.Store loaded at process start and by flex-auth load-registry. There is no background watch.
Deadline A registry-borne revocation is visible after the operator reloads the snapshot or when the current allow TTL ends, whichever is first. On a running process that has not reloaded, the snapshot is otherwise unchanged.
Provenance registry_snapshot_digest — SHA-256 of canonical snapshot JSON

The digest makes the deadline checkable: a later Check whose digest differs read a different snapshot.

Policy package activation

What is joined The validated Rego-in-Markdown package (id / version / compiled module)
Mechanism Loaded at process start and by CLI --policy. No hot swap.
Deadline A package change is visible after reload or when the current allow TTL ends, whichever is first.
Provenance policy_package, policy_version, policy_package_digest

Directory ETag

What is joined Delegated directory state (Topaz objects/relations, relationship-PDP tuples) and optional group-resolver evidence
Mechanism Topaz returns DirectoryETag; relationship adapters return a consistency token. Group resolvers (Graph, SCIM, LDAP, Keycloak) attach Freshness.MaxAge when configured. Verdicts are not cached by flex-auth.
Deadline Next Check against the directory for ETag-bearing adapters (0 relative to the directory's own visibility). For resolvers, the configured MaxAge; if MaxAge is unset, directory-borne group evidence is unbounded except by the allow TTL.
Provenance directory_etag; resolver freshness is subject-attribute evidence, not a second decision

A stale-directory signal from Topaz fails closed (topaz_directory_stale).

Lifetime versus an artifact issued under the decision

lifetime.expires_at bounds the decision, not anything a consumer creates while acting on it. It is authority to issue, not authority to use.

Where a PEP's enforcement produces a durable credential — ops-warden's SSH certificate is the shipped case — the credential's own TTL governs it, and no flex-auth field reaches it. A short decision lifetime bounds how long a revoked principal can keep obtaining new credentials, which is the part a PDP can bound; it does not recall one already issued. The residue between the two is the consumer's §9.7.2 window to state, and it is correctly stated at the PEP.

The lever that shortens the artifact's own life is the requested TTL as a policy input, not the decision lifetime. See FLEX-DEC-2026-004.

How to read this as a consumer

  1. Do not cache a verdict past lifetime.expires_at.
  2. To know whether a stored allow still names the same facts, compare registry_snapshot_digest, policy_package_digest, and directory_etag to a fresh Check.
  3. Approval revocation is a claim-class problem: stop presenting the claim, and do not replay a digest that included it.
  4. Do not read lifetime as a bound on a credential you issued under the allow. Bound that credential with its own TTL.