Align INTENT and SCOPE to security layer model v0.7; plan conformance work
The standard was accepted at v0.7 on 2026-08-29. Four of flex-auth's review findings are in the accepted text: 9.3's two-owner split, 6.4.2 scoped to the decision's own binding with our canonical request digest as its mechanical test, 9.7.2 split by role, and 17 moving the decision-record schema to access-engine. INTENT.md - Machine-readable layer declaration in frontmatter (layer: Engine, role: PDP), which section 11 requires and we did not have. audit-core noted our declaration was legible only by following the decision trail. - PDP failure semantics stated: our outage is consumer residue, not input degradation; fail-open is not expressible by a PDP at all. - Four owned obligations added: the decision-record schema as our contract, the request digest as the published replay test, a lifetime on every allow, and visibility deadlines per input class. - A Layer Conformance section stating the state honestly: conforming with one declared gap, no Tooling client, not PEP-shaped. - Vocabulary correction: earlier text dropped "control plane" as Staff vocabulary. Section 8 binds it to the Engine layer, which is why kings-guard was asked to release it. The term is ours; we prefer "decision engine" for precision, not boundary. SCOPE.md - Layer and role in the one-liner; the four obligations In Scope; five boundaries established in review but never written down Out of Scope. - Three capability blocks marked planned for workplans completed in May are now current; two blocks added. - Superseded ADR-0006 citation corrected to ADR-0009, which retires the global flag outright rather than deferring it. history/2026-08-29-layer-model-v0.7-alignment-review.md checks each obligation against the code and finds six gaps. FLEX-WP-0019 closes them, with T02 before T04 because a visibility deadline for registry-borne facts is unfalsifiable until provenance can identify the snapshot a decision read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012sgN4GH5ZYT8pJVkCR6dcP Assistant: claude-code Assistant-Model: opus Assistant-Process: 4014348@bnt-lap001 Assistant-Session: a993abda-65a0-4ea8-8ccd-0fcd78c92ac0
This commit is contained in:
parent
5753b47ccb
commit
0e2efa8fcf
6 changed files with 492 additions and 64 deletions
|
|
@ -2,9 +2,9 @@
|
||||||
"schema": "repo_manager.index.v1",
|
"schema": "repo_manager.index.v1",
|
||||||
"slug": "flex-auth",
|
"slug": "flex-auth",
|
||||||
"repo_root": "/home/worsch/flex-auth",
|
"repo_root": "/home/worsch/flex-auth",
|
||||||
"head_sha": "54aae6b6b365407c102c511e30c392b459423be2",
|
"head_sha": "5753b47ccb72f96689df9ec5eeb7be100f6817cd",
|
||||||
"observed_at": "2026-08-29T00:42:15.556704Z",
|
"observed_at": "2026-08-29T08:19:42.754823Z",
|
||||||
"source_fingerprint": "3cadc015fd19f01f7381a51c7d7b0aa461f875bfe59253be427e9d5d8f373795",
|
"source_fingerprint": "2d3773fc38408c64d1a9a4efc7335ed792f361cdf6464f04389615c9b443fa53",
|
||||||
"source_files": [
|
"source_files": [
|
||||||
".repo-classification.yaml",
|
".repo-classification.yaml",
|
||||||
"INTENT.md",
|
"INTENT.md",
|
||||||
|
|
@ -1071,7 +1071,7 @@
|
||||||
"status": "resolved",
|
"status": "resolved",
|
||||||
"title": "Review of security layer model v0.4: assent with findings, one rule contested",
|
"title": "Review of security layer model v0.4: assent with findings, one rule contested",
|
||||||
"source_path": "decisions/decisions.md",
|
"source_path": "decisions/decisions.md",
|
||||||
"uuid": null,
|
"uuid": "2e96321d-c7bf-4127-9c30-f3def32e5bee",
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"extra": {
|
"extra": {
|
||||||
"record": {
|
"record": {
|
||||||
|
|
@ -1101,7 +1101,47 @@
|
||||||
"updated": "2026-08-29T00:42:13.009799Z",
|
"updated": "2026-08-29T00:42:13.009799Z",
|
||||||
"rationale": "Assent to security-layer-model v0.4, with one rule contested and two capability assignments not accepted as assented. Section 9.3 conflicts with shipped assented behavior: it rules engine-unreachability fallback into the engine, where it cannot live, and collides with ops-warden ADR-0009's per-zone consumer PEP map. Section 13 names access-engine as intended owner of containment (accept as proposed owner only, pending per 9.2) and of authentication/assurance evidence (declined as stated; the identity layer and audit-core own that). Three consistency defects: frontmatter status proposed contradicts section 14 'accepted'; the adoption count reads seven of fifteen with remaining eight against sixteen estate-authored repositories and nine listed; section 14 says three repositories above a table of four. FLEX-IN-0002 answered: the approval boundary unblocks T03 design, T05 additionally needs the approval claim bound to the NewDecisionBinding request digest and a named owner and ordering for single consumption; the maturity claim route is practical as a request claim but not as registry content until the self-declared provenance digest gap closes.",
|
"rationale": "Assent to security-layer-model v0.4, with one rule contested and two capability assignments not accepted as assented. Section 9.3 conflicts with shipped assented behavior: it rules engine-unreachability fallback into the engine, where it cannot live, and collides with ops-warden ADR-0009's per-zone consumer PEP map. Section 13 names access-engine as intended owner of containment (accept as proposed owner only, pending per 9.2) and of authentication/assurance evidence (declined as stated; the identity layer and audit-core own that). Three consistency defects: frontmatter status proposed contradicts section 14 'accepted'; the adoption count reads seven of fifteen with remaining eight against sixteen estate-authored repositories and nine listed; section 14 says three repositories above a table of four. FLEX-IN-0002 answered: the approval boundary unblocks T03 design, T05 additionally needs the approval claim bound to the NewDecisionBinding request digest and a named owner and ordering for single consumption; the maturity claim route is practical as a request claim but not as registry content until the self-declared provenance digest gap closes.",
|
||||||
"decided_by": "flex-auth (reviewing side)",
|
"decided_by": "flex-auth (reviewing side)",
|
||||||
"decided_at": "2026-08-29T00:42:13.009799Z"
|
"decided_at": "2026-08-29T00:42:13.009799Z",
|
||||||
|
"state_hub_decision_id": "2e96321d-c7bf-4127-9c30-f3def32e5bee"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "decision",
|
||||||
|
"id": "FLEX-DEC-2026-003",
|
||||||
|
"status": "resolved",
|
||||||
|
"title": "Review of security layer model v0.6 and companion v0.1: assent, two answers, five findings",
|
||||||
|
"source_path": "decisions/decisions.md",
|
||||||
|
"uuid": null,
|
||||||
|
"parent_id": null,
|
||||||
|
"extra": {
|
||||||
|
"record": {
|
||||||
|
"id": "FLEX-DEC-2026-003",
|
||||||
|
"kind": "decision",
|
||||||
|
"title": "Review of security layer model v0.6 and companion v0.1: assent, two answers, five findings",
|
||||||
|
"status": "resolved",
|
||||||
|
"origin": "cross-repo",
|
||||||
|
"origin_ref": "net-kingdom security-layer-model_v0.6 + companion_v0.1",
|
||||||
|
"standard": "net-kingdom/canon/standards/security-layer-model_v0.6.md",
|
||||||
|
"owner": "flex-auth",
|
||||||
|
"affects": [
|
||||||
|
"flex-auth",
|
||||||
|
"gate-house",
|
||||||
|
"net-kingdom",
|
||||||
|
"info-tech-canon",
|
||||||
|
"ops-warden",
|
||||||
|
"approval-engine"
|
||||||
|
],
|
||||||
|
"requested_dispositions": [
|
||||||
|
"assent",
|
||||||
|
"revise",
|
||||||
|
"reject"
|
||||||
|
],
|
||||||
|
"created": "2026-08-29T08:18:39.602701Z",
|
||||||
|
"updated": "2026-08-29T08:19:41.832549Z",
|
||||||
|
"rationale": "Assent to v0.6 and companion v0.1, with two answers and five findings, none blocking. Q1: section 6.4.2 is right but collides with 9.7.1's session-bound allow, needs the request digest as its mechanical replay test, and should rule explicitly on deny-caching. Q2: the visibility deadline does land on a PDP and harder than at a PEP, but must be per input class rather than one number, and it makes flex-auth's registry-provenance gap load-bearing rather than untidy. Findings: 6.4's stance-map register does not exist in section 13 and neither document says where a map is published; the companion omits it too, which is the sufficiency gap gate-house asked for; section 17 puts the decision-record schema in Taxonomy when it is the PDP's output artifact, inverting the section 2 rule flex-auth used to decline authentication evidence; sections 17-19 are H1 outside the hierarchy; section 19 grades the document it lives in and will age.",
|
||||||
|
"decided_by": "flex-auth (reviewing side)",
|
||||||
|
"decided_at": "2026-08-29T08:19:41.832549Z"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1147,7 +1187,7 @@
|
||||||
"status": "closed",
|
"status": "closed",
|
||||||
"title": "Review requested: security layer model v0.3 (approval-engine, maturity-engine)",
|
"title": "Review requested: security layer model v0.3 (approval-engine, maturity-engine)",
|
||||||
"source_path": "intakes/intakes.md",
|
"source_path": "intakes/intakes.md",
|
||||||
"uuid": null,
|
"uuid": "01a04afa-307b-7e9e-b210-261badabcec7",
|
||||||
"parent_id": null,
|
"parent_id": null,
|
||||||
"extra": {
|
"extra": {
|
||||||
"record": {
|
"record": {
|
||||||
|
|
@ -1171,7 +1211,8 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"closed_at": "2026-08-29T00:42:14.888434Z",
|
"closed_at": "2026-08-29T00:42:14.888434Z",
|
||||||
"outcome": "assented with findings \u2014 see FLEX-DEC-2026-002"
|
"outcome": "assented with findings \u2014 see FLEX-DEC-2026-002",
|
||||||
|
"state_hub_intake_id": "01a04afa-307b-7e9e-b210-261badabcec7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1179,17 +1220,17 @@
|
||||||
"events": [
|
"events": [
|
||||||
{
|
{
|
||||||
"type": "repo.command.applied",
|
"type": "repo.command.applied",
|
||||||
"command": "repo.work.close_intake",
|
"command": "repo.work.resolve_decision",
|
||||||
"operation": "close",
|
"operation": "resolve",
|
||||||
"correlation_id": "1e832e3c-4e51-4dfd-919d-40593c18b2ab",
|
"correlation_id": "fe430c1e-83bb-4dba-b6fc-337baa1a0059",
|
||||||
"kind": "intake",
|
"kind": "decision",
|
||||||
"id": "FLEX-IN-0002",
|
"id": "FLEX-DEC-2026-003",
|
||||||
"git_sha": "54aae6b6b365407c102c511e30c392b459423be2",
|
"git_sha": "5753b47ccb72f96689df9ec5eeb7be100f6817cd",
|
||||||
"files_touched": [
|
"files_touched": [
|
||||||
"intakes/intakes.md"
|
"decisions/decisions.md"
|
||||||
],
|
],
|
||||||
"source": "repo-manager",
|
"source": "repo-manager",
|
||||||
"emitted_at": "2026-08-29T00:42:15.556791Z"
|
"emitted_at": "2026-08-29T08:19:42.754925Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
INTENT.md
135
INTENT.md
|
|
@ -1,45 +1,53 @@
|
||||||
|
---
|
||||||
|
# NetKingdom security layer declaration (security-layer-model_v0.7 §11).
|
||||||
|
# Machine-readable because §11 requires it: prose cannot distinguish a
|
||||||
|
# declaration from a transcribed review. Reference form: ops-warden layer.yaml.
|
||||||
|
layer: Engine
|
||||||
|
role: PDP
|
||||||
|
framework: netkingdom-security-layer-model
|
||||||
|
standard_version: "0.7"
|
||||||
|
declared_by: decisions/decisions.md FLEX-DEC-2026-001, FLEX-DEC-2026-002, FLEX-DEC-2026-003
|
||||||
|
declared_at: "2026-08-29"
|
||||||
|
pep_stance: null # not PEP-shaped: flex-auth renders decisions, it causes no protected side effect
|
||||||
|
tooling_contacts: [] # §5 binds Staff; flex-auth holds no Tooling client
|
||||||
|
---
|
||||||
|
|
||||||
# Flex-Auth Intent
|
# Flex-Auth Intent
|
||||||
|
|
||||||
> **NetKingdom layering review — 2026-08-28.** This repository's role was reviewed
|
> **Layer declaration.** flex-auth is **Engine / PDP** under the NetKingdom
|
||||||
> against the NetKingdom IT-security layer model: **Taxonomy → Tooling → Engines →
|
> Security Layer Model (`net-kingdom/canon/standards/security-layer-model_v0.7.md`,
|
||||||
> Staff**, layered by determinism and by the kind of artifact each layer produces.
|
> accepted 2026-08-29). It is **the only policy decision point in NetKingdom**
|
||||||
> Findings and the argument behind them:
|
> (§6): no other repository, in any layer, renders or caches an authorization
|
||||||
> `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`.
|
> decision. The frontmatter above is the machine-readable form §11 requires; this
|
||||||
> The model is `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed),
|
> paragraph is the declaration in flex-auth's own voice.
|
||||||
> ratified by `gate-house/decisions/decisions.md` GH-DEC-2026-001.
|
|
||||||
>
|
>
|
||||||
> The layer rule that binds every repository: **Staff never touches tooling
|
> The layer rule that binds every repository: **Staff never touches Tooling
|
||||||
> directly. It acts only through engine APIs.**
|
> directly. It acts only through Engine APIs.** flex-auth is one of those APIs.
|
||||||
>
|
>
|
||||||
> **This repository is Engine — and the only policy decision point in NetKingdom.**
|
> **What PDP means here, and what it does not.** As the estate's only PDP,
|
||||||
> Reframed on 2026-08-28 per `gate-house/decisions/decisions.md` GH-DEC-2026-001:
|
> flex-auth's outage is *consumer residue*, not input degradation (§9.3): when
|
||||||
> "control plane" dropped as Staff vocabulary, the layer and the exclusive
|
> flex-auth is unreachable there is no evaluator in the path, so what happens
|
||||||
> decision-point role stated, policy authoring separated from policy evaluation,
|
> next is the consumer's declared stance and never flex-auth's to express.
|
||||||
> gate-house's authority context adopted as input claims, and the access
|
> Fail-open is not expressible by a PDP at all. When flex-auth is reachable but
|
||||||
> lane/rule demarcation recorded.
|
> cannot reach its own inputs, the fallback is flex-auth's, deterministic, and
|
||||||
|
> fails to reduced authority. The PIP engines — user, tenant, zone, approval,
|
||||||
|
> maturity — supply facts flex-auth consumes as claims; `audit-core` records;
|
||||||
|
> `secrets-engine` holds credential lifecycle downstream of a decision.
|
||||||
>
|
>
|
||||||
> *Reframe applied. **Assent given on 2026-08-28** — `decisions/decisions.md`
|
> flex-auth reached this position by review rather than assertion, and holds
|
||||||
> FLEX-DEC-2026-001, answering intake `FLEX-IN-0001`: flex-auth assents to the Engine
|
> three records: `FLEX-DEC-2026-001` (Engine framing, the `access-engine` name,
|
||||||
> framing, to `access-engine` as the ruled name, and to the authoring/evaluation
|
> the authoring/evaluation split), `FLEX-DEC-2026-002` (§9.3 contested and
|
||||||
> split. One item remains: the rename itself, a separate governed migration — it
|
> upheld), and `FLEX-DEC-2026-003` (v0.6 review; §6.4.2, §9.7.2 and §17 as
|
||||||
> touches `FLEX-WP` prefix ownership, State Hub identifiers, ops-warden's routing
|
> adopted in v0.7).
|
||||||
> tables, zone-engine's binding boundary text, and secrets-engine integrations —
|
>
|
||||||
> and is not authorized by GH-DEC-2026-001. flex-auth adds two conditions on it
|
> *One item remains open: the ruled rename to `access-engine`. It is a separate
|
||||||
> (FLEX-DEC-2026-001 item 2): repository identity and runtime identity rename in
|
> governed migration — it touches `FLEX-WP` prefix ownership, State Hub
|
||||||
|
> identifiers, ops-warden's routing tables, zone-engine's boundary text, and
|
||||||
|
> secrets-engine integrations — and carries two conditions from
|
||||||
|
> `FLEX-DEC-2026-001`: repository identity and runtime identity rename in
|
||||||
> separate revertible steps, repository first, because the enforcing ops-warden
|
> separate revertible steps, repository first, because the enforcing ops-warden
|
||||||
> pin binds tokens to the protected-system name; and `FLEX-WP` prefix ownership
|
> pin binds tokens to the protected-system name; and `FLEX-WP` prefix ownership
|
||||||
> stays with the repository.*
|
> stays with the repository.*
|
||||||
>
|
|
||||||
> **Known non-conformance — registry provenance.** Standard §6 holds that
|
|
||||||
> compiled data determining an outcome is still deciding, and that provenance
|
|
||||||
> must stay reconstructable from the decision. `DecisionProvenance` carries the
|
|
||||||
> evaluator, mode, policy package, policy version, and directory ETag, but no
|
|
||||||
> digest of the registry snapshot. A decision that turned on registry content
|
|
||||||
> cannot be replayed from its own provenance. flex-auth accepts this as its own
|
|
||||||
> gap rather than claiming conformance; until it is closed, outcome-determining
|
|
||||||
> content belongs in the versioned policy package, not the registry — for
|
|
||||||
> zone-engine's zone stance, for gate-house's authority ceilings, and for
|
|
||||||
> everyone else on the same terms.
|
|
||||||
|
|
||||||
> This file captures **why this repository exists**, the **direction it is
|
> This file captures **why this repository exists**, the **direction it is
|
||||||
> moving toward**, and the **kind of system it is meant to become**.
|
> moving toward**, and the **kind of system it is meant to become**.
|
||||||
|
|
@ -53,14 +61,24 @@ for organizations that want to grow from simple access rules into
|
||||||
enterprise-grade authorization without giving up clear ownership, local
|
enterprise-grade authorization without giving up clear ownership, local
|
||||||
development ergonomics, or inspectable policy decisions.
|
development ergonomics, or inspectable policy decisions.
|
||||||
|
|
||||||
It is an **Engine** in the NetKingdom security layer model
|
It is an **Engine**, role **PDP**, in the NetKingdom security layer model
|
||||||
(`net-kingdom/canon/standards/security-layer-model_v0.1.md`): a deterministic
|
(`net-kingdom/canon/standards/security-layer-model_v0.7.md`): a deterministic
|
||||||
API for a modeled concept, where the same authoritative input state yields the
|
API for a modeled concept, where the same authoritative input state yields the
|
||||||
same result. It is deliberately not described as a control plane — that is
|
same result.
|
||||||
Staff-layer vocabulary, and flex-auth is not Staff.
|
|
||||||
|
|
||||||
Within NetKingdom it is **the only policy decision point** (standard §6). No
|
Within NetKingdom it is **the only policy decision point** (standard §6). No
|
||||||
other repository, in any layer, may render or cache an authorization decision.
|
other repository, in any layer, may render or cache an authorization decision.
|
||||||
|
Engine typing (§3.3) makes the corollary explicit: a new engine is a PIP unless
|
||||||
|
the standard is amended, so *"we need an engine for X"* can never become *"X now
|
||||||
|
decides"*.
|
||||||
|
|
||||||
|
A note on vocabulary, corrected here. Earlier versions of this file dropped
|
||||||
|
"control plane" on the grounds that it was Staff-layer vocabulary. That reason
|
||||||
|
was wrong on the standard's own terms — §8 binds **control plane to the Engine
|
||||||
|
layer**, which is why kings-guard was asked to release it. The term is
|
||||||
|
flex-auth's to use. This file prefers **decision engine** anyway, because it
|
||||||
|
names what flex-auth does rather than where it sits, but the preference is
|
||||||
|
style, not a boundary.
|
||||||
|
|
||||||
It is the **authorization layer** in the path from verified identity to
|
It is the **authorization layer** in the path from verified identity to
|
||||||
protected resources:
|
protected resources:
|
||||||
|
|
@ -118,6 +136,19 @@ authenticated; flex-auth decides what that actor is allowed to do.
|
||||||
- Relationship facts and inherited access.
|
- Relationship facts and inherited access.
|
||||||
- PDP adapter coordination.
|
- PDP adapter coordination.
|
||||||
- Decision logging, explanations, and audit export.
|
- Decision logging, explanations, and audit export.
|
||||||
|
- **The decision-record schema**, published as flex-auth's own contract
|
||||||
|
(§17). A decision record is the PDP's output artifact — the one thing in the
|
||||||
|
estate only flex-auth produces — so §2 keeps its schema here rather than in
|
||||||
|
Taxonomy. flex-auth argued this against its own interest and took the work on.
|
||||||
|
- **The canonical request digest** over normalized subject, action, resource,
|
||||||
|
and context. It is the mechanical test for §6.4.2: a consumer may replay a
|
||||||
|
verdict iff the digest matches and the decision's lifetime holds.
|
||||||
|
- **A stated lifetime on every allow** (§9.7.1) — a TTL, or a binding to a
|
||||||
|
session or obligation that ends. An allow with no stated end is a standing
|
||||||
|
grant.
|
||||||
|
- **A revocation visibility deadline per input class** (§9.7.2) — approval-claim
|
||||||
|
freshness, registry snapshot cadence, policy package activation, directory
|
||||||
|
ETag. A single number at a PDP is either a fiction or the worst case.
|
||||||
|
|
||||||
### Gate House Owns the Doctrine the Decision Serves
|
### Gate House Owns the Doctrine the Decision Serves
|
||||||
|
|
||||||
|
|
@ -237,12 +268,12 @@ adopting their models as its own:
|
||||||
- a local directory plus policy-evaluation engine for self-contained
|
- a local directory plus policy-evaluation engine for self-contained
|
||||||
delegated setups
|
delegated setups
|
||||||
|
|
||||||
Flex-auth remains the stable control plane even when the backend changes.
|
Flex-auth remains the stable decision point even when the backend changes.
|
||||||
|
|
||||||
## Consumer Patterns
|
## Consumer Patterns
|
||||||
|
|
||||||
Two consumer shapes drive flex-auth, and the first one to ship deliberately
|
Two consumer shapes drive flex-auth, and the first one to ship deliberately
|
||||||
is not a document pipeline — proving the control plane stays generic.
|
is not a document pipeline — proving the decision engine stays generic.
|
||||||
|
|
||||||
**First shipped consumer — an action gate (ops-warden SSH signing).** A
|
**First shipped consumer — an action gate (ops-warden SSH signing).** A
|
||||||
protected system asks flex-auth a single "may this actor perform this action
|
protected system asks flex-auth a single "may this actor perform this action
|
||||||
|
|
@ -273,6 +304,30 @@ Together these shape flex-auth around real authorization needs — both
|
||||||
point-in-time action gates and result-filtering pipelines — without making the
|
point-in-time action gates and result-filtering pipelines — without making the
|
||||||
policy service consumer-specific.
|
policy service consumer-specific.
|
||||||
|
|
||||||
|
## Layer Conformance
|
||||||
|
|
||||||
|
flex-auth's conformance state under §11 is **conforming with one declared gap**.
|
||||||
|
It holds no Tooling client, so the §5 shapes do not apply to it, and it is not
|
||||||
|
PEP-shaped, so it owes no stance map under §6.4.
|
||||||
|
|
||||||
|
**The declared gap — registry-snapshot digest in decision provenance (§13).**
|
||||||
|
`DecisionProvenance` carries the evaluator, mode, policy package, policy version,
|
||||||
|
directory ETag, and decision time, but no digest of the registry snapshot that
|
||||||
|
supplied resource, subject, and relationship facts. A decision that turned on
|
||||||
|
registry content cannot be replayed from its own provenance.
|
||||||
|
|
||||||
|
v0.7 §9.7.2 promotes this from housekeeping to a **conformance prerequisite**,
|
||||||
|
on flex-auth's own argument: a stated visibility deadline for a fact carried by
|
||||||
|
a registry snapshot is unfalsifiable while provenance holds no snapshot digest,
|
||||||
|
because nobody can determine afterwards which snapshot a decision read. The
|
||||||
|
deadline and the digest are one gap seen from two sides.
|
||||||
|
|
||||||
|
Until it closes, one rule holds and flex-auth applies it to everyone equally,
|
||||||
|
including itself: **outcome-determining content belongs in the versioned policy
|
||||||
|
package, not in registry content** — for zone stance, for gate-house's authority
|
||||||
|
ceilings, for maturity levels, and for flex-auth's own facts. Registry content
|
||||||
|
carries membership and identity; the policy package carries effect.
|
||||||
|
|
||||||
## Non-Goals
|
## Non-Goals
|
||||||
|
|
||||||
- Flex-auth is not an identity provider.
|
- Flex-auth is not an identity provider.
|
||||||
|
|
|
||||||
70
SCOPE.md
70
SCOPE.md
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
## One-liner
|
## One-liner
|
||||||
|
|
||||||
flex-auth is a policy-as-code authorization registry and control plane for
|
flex-auth is a policy-as-code authorization registry and decision engine for
|
||||||
NetKingdom-aligned systems.
|
NetKingdom-aligned systems. Under the NetKingdom Security Layer Model
|
||||||
|
(`security-layer-model_v0.7`, accepted 2026-08-29) it is **Engine / PDP** — the
|
||||||
|
estate's only policy decision point.
|
||||||
|
|
||||||
## Core Idea
|
## Core Idea
|
||||||
|
|
||||||
|
|
@ -33,6 +35,14 @@ can be coordinated behind a stable flex-auth API.
|
||||||
- Markitect as the first concrete protected-system consumer.
|
- Markitect as the first concrete protected-system consumer.
|
||||||
- Delegated PDP and directory adapter boundaries after the standalone core is
|
- Delegated PDP and directory adapter boundaries after the standalone core is
|
||||||
stable.
|
stable.
|
||||||
|
- The **decision-record schema**, published as flex-auth's own contract
|
||||||
|
(`security-layer-model_v0.7` §17).
|
||||||
|
- The **canonical request digest** as the published replay test for consumers
|
||||||
|
(§6.4.2).
|
||||||
|
- **Decision lifetimes** on every allow, and **revocation visibility deadlines
|
||||||
|
stated per input class** (§9.7).
|
||||||
|
- **Registry-snapshot provenance**, so a decision that turned on registry
|
||||||
|
content is replayable from its own record (§6.1, §9.7.2).
|
||||||
|
|
||||||
## Out of Scope
|
## Out of Scope
|
||||||
|
|
||||||
|
|
@ -46,6 +56,18 @@ can be coordinated behind a stable flex-auth API.
|
||||||
model.
|
model.
|
||||||
- Forcing a single PDP backend or directory provider.
|
- Forcing a single PDP backend or directory provider.
|
||||||
- Hiding policy behavior behind opaque administrative toggles.
|
- Hiding policy behavior behind opaque administrative toggles.
|
||||||
|
- Expressing fail-open. When flex-auth is unreachable there is no evaluator in
|
||||||
|
the path; the residue is the consumer's declared stance (§9.3).
|
||||||
|
- Owning enforcement. A PEP's obligations under §6.4 are the consumer's,
|
||||||
|
including its published stance map.
|
||||||
|
- Owning the approval object, its storage, or its lifecycle — that is
|
||||||
|
`approval-engine`'s (§9.4). flex-auth validates approvals as input claims and
|
||||||
|
never mutates them.
|
||||||
|
- Owning evidence of authentication or assurance. flex-auth consumes assurance
|
||||||
|
claims and never redefines them; it owns evidence of the decision
|
||||||
|
(`FLEX-DEC-2026-002`, recorded as declined in §13).
|
||||||
|
- Authoring security doctrine. gate-house owns invariants, authority ceilings,
|
||||||
|
operating modes, and the authority context flex-auth consumes as claims.
|
||||||
|
|
||||||
## Relevant When
|
## Relevant When
|
||||||
|
|
||||||
|
|
@ -105,13 +127,19 @@ ops-warden adopted a calling identity (`WARDEN-WP-0031`): anonymous `/v1/check`
|
||||||
is 401, a token bound to another protected system is 403.
|
is 401, a token bound to another protected system is 403.
|
||||||
|
|
||||||
Production `policy.enabled` is **deliberately off, and is not coming back as a
|
Production `policy.enabled` is **deliberately off, and is not coming back as a
|
||||||
boolean.** ops-warden's `ADR-0006` (2026-08-19) defers it permanently:
|
boolean.** ops-warden's `ADR-0009` (2026-08-22, superseding `ADR-0006`) settles it:
|
||||||
`policy.enabled` is one repo-wide flag, and with `fail_closed: true` it makes
|
`policy.enabled` is one repo-wide flag, and with `fail_closed: true` it makes
|
||||||
flex-auth a hard dependency of every `warden sign` — including the SSH
|
flex-auth a hard dependency of every `warden sign` — including the SSH
|
||||||
certificates the ops-bridge tunnels depend on, one of which carries the policy
|
certificates the ops-bridge tunnels depend on, one of which carries the policy
|
||||||
call itself. Enforcement is being rescoped to *security zones* (`zone-engine`
|
call itself. `ADR-0009` retires `policy.enabled` and the global `policy.fail_closed`
|
||||||
`ZONE-WP-0001`, consumer side `WARDEN-WP-0032`). flex-auth reviewed that model as
|
outright and replaces them with a total per-zone stance map in the consumer PEP
|
||||||
the PDP on 2026-08-19 and holds one boundary: zone **membership** compiles into
|
(`ops-warden/pep-stance.yaml`): open for `z0`-`z2` and `unknown`, closed for
|
||||||
|
`z3-critical`. That map is the reference shape for `security-layer-model_v0.7`
|
||||||
|
§6.4 obligation 3, and it is the estate's only published one — §13.1's register
|
||||||
|
has one row, which the standard records as itself the finding.
|
||||||
|
|
||||||
|
flex-auth reviewed the zone model as the PDP on 2026-08-19 and holds one
|
||||||
|
boundary: zone **membership** compiles into
|
||||||
the registry snapshot flex-auth already consumes (no schema change needed), while
|
the registry snapshot flex-auth already consumes (no schema change needed), while
|
||||||
per-zone **stance** belongs in the versioned policy package, because registry
|
per-zone **stance** belongs in the versioned policy package, because registry
|
||||||
content is absent from decision provenance. **Fail-open is not expressible by a
|
content is absent from decision provenance. **Fail-open is not expressible by a
|
||||||
|
|
@ -119,6 +147,16 @@ PDP at all** and stays a consumer-side setting. The enforcing pins stay
|
||||||
enforcing regardless — an enforcing pin with no enforcing consumer still turns
|
enforcing regardless — an enforcing pin with no enforcing consumer still turns
|
||||||
the anonymous path into a 401 rather than a decision.
|
the anonymous path into a 401 rather than a decision.
|
||||||
|
|
||||||
|
**Layer position (2026-08-29).** The NetKingdom Security Layer Model was
|
||||||
|
accepted at v0.7. flex-auth is **Engine / PDP**, declared machine-readably in
|
||||||
|
`INTENT.md` frontmatter per §11. Four of flex-auth's review findings were adopted
|
||||||
|
into the standard: §9.3's two-owner split for degraded mode, §6.4.2 scoped to the
|
||||||
|
decision's own binding with the canonical request digest as its mechanical test
|
||||||
|
and negative caching ruled explicitly, §9.7.2 split by role, and §17 moving the
|
||||||
|
decision-record schema to flex-auth. Conformance state is **conforming with one
|
||||||
|
declared gap** — the registry-snapshot digest in decision provenance, which §9.7.2
|
||||||
|
promotes to a conformance prerequisite. `FLEX-WP-0019` carries the work.
|
||||||
|
|
||||||
State Hub integration is present through:
|
State Hub integration is present through:
|
||||||
|
|
||||||
- `.custodian-brief.md`
|
- `.custodian-brief.md`
|
||||||
|
|
@ -212,20 +250,34 @@ description: Repo intent, boundaries, research, workplan map, and State Hub agen
|
||||||
```capability
|
```capability
|
||||||
type: workplan
|
type: workplan
|
||||||
title: Standalone policy core plan
|
title: Standalone policy core plan
|
||||||
status: planned
|
status: current
|
||||||
description: Workplan for schemas, local registry, policy packages, check APIs, list/explain, decision log, CLI/service skeleton, tests, and examples.
|
description: Workplan for schemas, local registry, policy packages, check APIs, list/explain, decision log, CLI/service skeleton, tests, and examples.
|
||||||
```
|
```
|
||||||
|
|
||||||
```capability
|
```capability
|
||||||
type: workplan
|
type: workplan
|
||||||
title: Markitect consumer integration plan
|
title: Markitect consumer integration plan
|
||||||
status: planned
|
status: current
|
||||||
description: Workplan for Markitect resource namespace, manifest import, action vocabulary, check fixtures, contract tests, and integration flow.
|
description: Workplan for Markitect resource namespace, manifest import, action vocabulary, check fixtures, contract tests, and integration flow.
|
||||||
```
|
```
|
||||||
|
|
||||||
```capability
|
```capability
|
||||||
type: workplan
|
type: workplan
|
||||||
title: Delegated adapter plan
|
title: Delegated adapter plan
|
||||||
status: planned
|
status: current
|
||||||
description: Workplan for Topaz evaluation, relationship PDP adapters, rule PDP adapters, Keycloak AuthZ path, directory resolvers, and operations docs.
|
description: Workplan for Topaz evaluation, relationship PDP adapters, rule PDP adapters, Keycloak AuthZ path, directory resolvers, and operations docs.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```capability
|
||||||
|
type: contract
|
||||||
|
title: Decision-record contract
|
||||||
|
status: current
|
||||||
|
description: Published decision-record schema, canonical request digest as the replay test for consumers, and decision provenance — flex-auth's own contract under security-layer-model v0.7 section 17.
|
||||||
|
```
|
||||||
|
|
||||||
|
```capability
|
||||||
|
type: orientation
|
||||||
|
title: Layer declaration
|
||||||
|
status: current
|
||||||
|
description: Machine-readable Engine/PDP declaration in INTENT.md frontmatter with conformance state and the one declared gap, per security-layer-model v0.7 section 11.
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -111,3 +111,4 @@
|
||||||
| intake | FLEX-IN-0002 | closed | — | intakes/intakes.md |
|
| intake | FLEX-IN-0002 | closed | — | intakes/intakes.md |
|
||||||
| decision | FLEX-DEC-2026-001 | resolved | — | decisions/decisions.md |
|
| decision | FLEX-DEC-2026-001 | resolved | — | decisions/decisions.md |
|
||||||
| decision | FLEX-DEC-2026-002 | resolved | — | decisions/decisions.md |
|
| decision | FLEX-DEC-2026-002 | resolved | — | decisions/decisions.md |
|
||||||
|
| decision | FLEX-DEC-2026-003 | resolved | — | decisions/decisions.md |
|
||||||
|
|
|
||||||
136
history/2026-08-29-layer-model-v0.7-alignment-review.md
Normal file
136
history/2026-08-29-layer-model-v0.7-alignment-review.md
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
---
|
||||||
|
id: flex-auth-2026-08-29-layer-model-alignment
|
||||||
|
type: history
|
||||||
|
title: "Layer model v0.7 alignment: INTENT, SCOPE, and the gap between them"
|
||||||
|
domain: infotech
|
||||||
|
repo: flex-auth
|
||||||
|
owner: flex-auth
|
||||||
|
created: "2026-08-29"
|
||||||
|
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
||||||
|
records: decisions/decisions.md FLEX-DEC-2026-001, FLEX-DEC-2026-002, FLEX-DEC-2026-003
|
||||||
|
workplan: workplans/FLEX-WP-0019-layer-model-conformance.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Layer model v0.7 alignment review
|
||||||
|
|
||||||
|
The NetKingdom Security Layer Model was accepted at **v0.7** on 2026-08-29.
|
||||||
|
`INTENT.md` and `SCOPE.md` were aligned to it in the same session. This document
|
||||||
|
records what changed, then asks the question the alignment exists to answer:
|
||||||
|
**where does the stated scope now outrun the implementation, and what has to be
|
||||||
|
built to close it.**
|
||||||
|
|
||||||
|
## 1. How flex-auth arrived at v0.7
|
||||||
|
|
||||||
|
flex-auth reviewed three versions and holds three records. Four of its findings
|
||||||
|
became text in the accepted standard:
|
||||||
|
|
||||||
|
| Finding | Adopted as |
|
||||||
|
| --- | --- |
|
||||||
|
| §9.3 collapsed two failures with different owners | §9.3 rewritten: input degradation is the engine's, engine-unreachability is necessarily the consumer's |
|
||||||
|
| §6.4.2 forbade the session-bound allow §9.7.1 permits | §6.4.2 scoped to the decision's own binding and lifetime, with flex-auth's canonical request digest as the mechanical test, and negative caching ruled permitted where the refusal is recorded |
|
||||||
|
| A PDP's visibility deadline is per input class, not one number | §9.7.2 split by role |
|
||||||
|
| The decision-record schema is the PDP's output, not Taxonomy's | §17 moves it to `access-engine` |
|
||||||
|
|
||||||
|
The last of those was argued **against flex-auth's own interest** — it takes work
|
||||||
|
on rather than off — and the standard says so, because that is what makes the
|
||||||
|
§2 ownership rule credible when flex-auth also uses it to decline work.
|
||||||
|
|
||||||
|
Two of flex-auth's positions were recorded rather than adopted: containment
|
||||||
|
surface ownership stays **proposed** (§13, pending under §9.2), and
|
||||||
|
authentication/assurance evidence is recorded as **declined**.
|
||||||
|
|
||||||
|
## 2. What changed in INTENT.md
|
||||||
|
|
||||||
|
1. **A machine-readable layer declaration** in frontmatter — `layer: Engine`,
|
||||||
|
`role: PDP` — which §11 requires and flex-auth did not have. `audit-core`
|
||||||
|
named this precisely: flex-auth's declaration was "legible as one only by
|
||||||
|
following its decision trail." Prose cannot distinguish a declaration from a
|
||||||
|
transcribed review.
|
||||||
|
2. **The PDP role stated with its failure semantics**: flex-auth's outage is
|
||||||
|
consumer residue, not input degradation. Fail-open is not expressible by a
|
||||||
|
PDP at all.
|
||||||
|
3. **Four obligations added to what flex-auth owns**: the decision-record
|
||||||
|
schema as its own contract, the canonical request digest as the published
|
||||||
|
replay test, a lifetime on every allow, and revocation visibility deadlines
|
||||||
|
per input class.
|
||||||
|
4. **A `Layer Conformance` section** stating the conformance state honestly:
|
||||||
|
conforming with one declared gap, no Tooling client, not PEP-shaped.
|
||||||
|
5. **A vocabulary correction.** Earlier versions dropped "control plane" as
|
||||||
|
Staff vocabulary. That reason was wrong on the standard's own terms — §8
|
||||||
|
binds control plane to the **Engine layer**, which is why kings-guard was
|
||||||
|
asked to release it. The term is flex-auth's to use. This file prefers
|
||||||
|
"decision engine" as a matter of precision, not boundary.
|
||||||
|
|
||||||
|
## 3. What changed in SCOPE.md
|
||||||
|
|
||||||
|
The one-liner now states the layer and role. In Scope gained the four v0.7
|
||||||
|
obligations. Out of Scope gained five boundaries flex-auth had established in
|
||||||
|
review but never written down: fail-open, enforcement, the approval object,
|
||||||
|
authentication evidence, and doctrine authoring. Three capability blocks were
|
||||||
|
still marked `planned` for workplans completed in May and are now `current`, and
|
||||||
|
two capability blocks were added. A superseded citation of ops-warden `ADR-0006`
|
||||||
|
was corrected to `ADR-0009`, which retires the global flag outright rather than
|
||||||
|
deferring it.
|
||||||
|
|
||||||
|
## 4. Scope versus implementation — the gap
|
||||||
|
|
||||||
|
This is the operative section. Each row is checked against the code, not
|
||||||
|
against the documents.
|
||||||
|
|
||||||
|
| # | Obligation | Standard | Implementation today | Gap |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| G1 | Machine-readable layer declaration | §11 | `INTENT.md` frontmatter, added in this session | **closed**, needs a conformance test |
|
||||||
|
| G2 | Registry-snapshot digest in decision provenance | §6.1, §9.7.2, §13 | `DecisionProvenance` carries evaluator, mode, policy package, policy version, directory ETag, decision time — **no snapshot digest** | **open — conformance prerequisite** |
|
||||||
|
| G3 | Every allow carries an explicit lifetime | §9.7.1 | `DecisionEnvelope` has **no lifetime field**. `ActionAuthorizationValidity` has `not_before`/`expires_at`, but that is the durable approval object, not the decision | **open** |
|
||||||
|
| G4 | Revocation visibility deadline per input class | §9.7.2 | Not stated anywhere — no document, no field | **open** |
|
||||||
|
| G5 | Decision-record schema published as flex-auth's contract | §17 | `schemas/decision_envelope.schema.json` exists and describes `binding` and `provenance` via `$defs`. It carries no lifetime, no policy-package **digest** (name and version only), and no input-claim digests | **partial** |
|
||||||
|
| G6 | Canonical request digest as the §6.4.2 replay test | §6.4.2 | `NewDecisionBinding` computes it over normalized subject, action, resource, context; it is in every binding and regression-tested | **closed in code, unpublished as consumer guidance** |
|
||||||
|
| G7 | Doctrine reaches the decision as claim or versioned rule | §6.2 | Context claims and versioned policy packages both exist | **closed** |
|
||||||
|
| G8 | Approvals consumed as input claims, never mutated | §9.4 | flex-auth mutates no approval. `FLEX-WP-0017` T03/T05 wait on `approval-engine` | **closed on flex-auth's side; blocked externally** |
|
||||||
|
|
||||||
|
### Why G2 is the one that matters most
|
||||||
|
|
||||||
|
G2 and G4 are the same gap seen from two sides, and the standard now says so in
|
||||||
|
flex-auth's own words. A stated visibility deadline for a fact carried by a
|
||||||
|
registry snapshot is **unfalsifiable** while provenance holds no snapshot
|
||||||
|
digest, because nobody can determine afterwards which snapshot a decision read.
|
||||||
|
Publishing G4 without closing G2 would be publishing a number nobody can check.
|
||||||
|
|
||||||
|
G2 is also cheap. `registry.Snapshot` is already a deterministic,
|
||||||
|
JSON-serializable struct with a test asserting that determinism
|
||||||
|
(`TestStoreLoadsAndSavesDeterministicSnapshot`), and `pkg/api/canonical.go`
|
||||||
|
already carries the canonical-JSON-plus-SHA-256 pattern that
|
||||||
|
`NewDecisionBinding` uses. The work is to reuse that pattern over the snapshot
|
||||||
|
and thread the result into `DecisionProvenance`, including through the delegated
|
||||||
|
adapters, which already share the canonical binding constructor.
|
||||||
|
|
||||||
|
### Why G3 is larger than it looks
|
||||||
|
|
||||||
|
Adding a lifetime field is trivial. Deciding **what the lifetime is** is not: a
|
||||||
|
TTL, a session binding, or an obligation binding, per §9.7.1. flex-auth has no
|
||||||
|
session concept, so the honest first step is a policy-package-declared TTL with
|
||||||
|
an explicit default, and a deny for any allow that would otherwise have no
|
||||||
|
stated end. That is a policy-surface change and needs fixtures, not just a
|
||||||
|
struct field.
|
||||||
|
|
||||||
|
### A capability flex-auth claimed and cannot yet exercise
|
||||||
|
|
||||||
|
flex-auth told gate-house it is the repository positioned to notice when the
|
||||||
|
aggregate of consumer stances diverges from what the policy packages say. §13.1
|
||||||
|
now exists as the register, and it has **one row** — `ops-warden`, with
|
||||||
|
`ops-mason` catalogued PEP-shaped and unpublished. The claim is sound and the
|
||||||
|
data is not there yet. This is not a flex-auth gap to close alone, but flex-auth
|
||||||
|
should be able to read the register once it is populated, and should say so
|
||||||
|
rather than let the claim sit unexercised.
|
||||||
|
|
||||||
|
## 5. What this does not change
|
||||||
|
|
||||||
|
flex-auth's boundaries are unchanged by v0.7. It still does not author doctrine,
|
||||||
|
own approvals, own enforcement, or own authentication evidence. The rename to
|
||||||
|
`access-engine` remains a separate governed migration under the two conditions
|
||||||
|
in `FLEX-DEC-2026-001`, and nothing in the alignment starts it.
|
||||||
|
|
||||||
|
## 6. Outcome
|
||||||
|
|
||||||
|
`FLEX-WP-0019` carries G1's test, G2, G3, G4, G5, and G6. G7 needs nothing.
|
||||||
|
G8 stays with `FLEX-WP-0017`, blocked on `approval-engine`.
|
||||||
143
workplans/FLEX-WP-0019-layer-model-conformance.md
Normal file
143
workplans/FLEX-WP-0019-layer-model-conformance.md
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
---
|
||||||
|
id: FLEX-WP-0019
|
||||||
|
type: workplan
|
||||||
|
title: "Layer model v0.7 conformance: provenance, lifetimes, deadlines, and the decision contract"
|
||||||
|
domain: infotech
|
||||||
|
repo: flex-auth
|
||||||
|
status: ready
|
||||||
|
owner: codex
|
||||||
|
topic_slug: netkingdom
|
||||||
|
planning_priority: P1
|
||||||
|
planning_order: 119
|
||||||
|
created: "2026-08-29"
|
||||||
|
updated: "2026-08-29"
|
||||||
|
---
|
||||||
|
|
||||||
|
# FLEX-WP-0019 - Layer model v0.7 conformance
|
||||||
|
|
||||||
|
The NetKingdom Security Layer Model was accepted at v0.7 on 2026-08-29 and
|
||||||
|
`INTENT.md`/`SCOPE.md` were aligned to it. The alignment review
|
||||||
|
(`history/2026-08-29-layer-model-v0.7-alignment-review.md`) identified six gaps
|
||||||
|
between what flex-auth now states and what it implements. This workplan closes
|
||||||
|
them.
|
||||||
|
|
||||||
|
Two are conformance obligations rather than features: the registry-snapshot
|
||||||
|
digest (§9.7.2 promotes it from housekeeping to a prerequisite, on flex-auth's
|
||||||
|
own argument) and the per-input-class visibility deadlines that depend on it.
|
||||||
|
|
||||||
|
Ordering is load-bearing. **T02 precedes T04** — publishing a visibility
|
||||||
|
deadline for registry-borne facts before provenance can identify the snapshot
|
||||||
|
would publish a number nobody can check.
|
||||||
|
|
||||||
|
## Assert the layer declaration mechanically
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T01
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
`INTENT.md` frontmatter carries `layer: Engine`, `role: PDP` per §11. Add a
|
||||||
|
conformance check and test asserting the declaration parses, states a layer in
|
||||||
|
the §3 vocabulary, states a role because the layer is Engine, and that no
|
||||||
|
Tooling client exists in the tree — the Engine-side analogue of ops-warden's
|
||||||
|
`scripts/check_layer_conformance.py`, which is offered estate-wide as a
|
||||||
|
reference form.
|
||||||
|
|
||||||
|
Closes G1's remaining half. Wire it into `make test`.
|
||||||
|
|
||||||
|
## Add the registry-snapshot digest to decision provenance
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T02
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
`DecisionProvenance` carries no digest of the registry snapshot that supplied
|
||||||
|
resource, subject, and relationship facts, so a decision that turned on registry
|
||||||
|
content cannot be replayed from its own record (§6.1). This is flex-auth's one
|
||||||
|
declared gap in §13 and a conformance prerequisite under §9.7.2.
|
||||||
|
|
||||||
|
Reuse the canonical-JSON plus SHA-256 pattern already in `pkg/api/canonical.go`
|
||||||
|
over `registry.Snapshot`, which is already deterministic and has a test asserting
|
||||||
|
it (`TestStoreLoadsAndSavesDeterministicSnapshot`). Thread the digest into
|
||||||
|
`DecisionProvenance`, through the standalone engine and through every delegated
|
||||||
|
adapter that shares the canonical constructor, and into
|
||||||
|
`schemas/decision_envelope.schema.json`. Add regression coverage that a changed
|
||||||
|
snapshot changes the digest and that two decisions over the same snapshot agree.
|
||||||
|
|
||||||
|
## Give every allow an explicit lifetime
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T03
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
§9.7.1 requires every allow to carry an explicit lifetime — a TTL, or a binding
|
||||||
|
to a session or obligation that ends. `DecisionEnvelope` has no lifetime field;
|
||||||
|
`ActionAuthorizationValidity` has one but belongs to the durable approval object,
|
||||||
|
not the decision.
|
||||||
|
|
||||||
|
The struct field is trivial; the semantics are not. flex-auth has no session
|
||||||
|
concept, so the first honest shape is a **policy-package-declared TTL with an
|
||||||
|
explicit default**, and a deny for any allow that would otherwise have no stated
|
||||||
|
end. That is a policy-surface change: it needs package schema support, fixtures
|
||||||
|
covering declared TTL, defaulted TTL, and the no-stated-end deny, and it must
|
||||||
|
appear in the decision record and the published schema.
|
||||||
|
|
||||||
|
## State revocation visibility deadlines per input class
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T04
|
||||||
|
status: todo
|
||||||
|
priority: high
|
||||||
|
```
|
||||||
|
|
||||||
|
§9.7.2 requires a PDP to state a deadline **per input class**, because a decision
|
||||||
|
is a join over sources with unrelated refresh behaviour. Enumerate the classes
|
||||||
|
flex-auth actually joins — approval-claim freshness, registry snapshot cadence,
|
||||||
|
policy package activation, directory ETag — and state a deadline for each, with
|
||||||
|
the mechanism that bounds it rather than an aspiration.
|
||||||
|
|
||||||
|
Depends on **T02**: the registry deadline is unfalsifiable until provenance can
|
||||||
|
identify the snapshot a decision read. Publish as
|
||||||
|
`docs/decision-input-freshness.md` and reference it from `INTENT.md`.
|
||||||
|
|
||||||
|
## Publish the decision-record schema as flex-auth's contract
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T05
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
§17 moves the decision-record schema from Taxonomy to `access-engine`, on
|
||||||
|
flex-auth's own argument that a decision record is the PDP's output artifact.
|
||||||
|
`schemas/decision_envelope.schema.json` exists and describes `binding` and
|
||||||
|
`provenance`, but carries no lifetime (T03), no snapshot digest (T02), no
|
||||||
|
policy-package **digest** — name and version only — and no input-claim digests.
|
||||||
|
|
||||||
|
Complete it, version it as a published contract rather than an internal shape,
|
||||||
|
and document it in `docs/` as the artifact consumers may rely on. Taxonomy holds
|
||||||
|
only the shared field vocabulary the claim schema references; this schema is
|
||||||
|
flex-auth's.
|
||||||
|
|
||||||
|
## Publish the request digest as the replay test
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FLEX-WP-0019-T06
|
||||||
|
status: todo
|
||||||
|
priority: medium
|
||||||
|
```
|
||||||
|
|
||||||
|
§6.4.2 makes replay permitted **iff the canonical request digest matches and the
|
||||||
|
decision's lifetime holds**, and names flex-auth's digest as the mechanical test.
|
||||||
|
The digest is computed and regression-tested but is documented nowhere a consumer
|
||||||
|
would look.
|
||||||
|
|
||||||
|
Publish what it is computed over, what normalization applies, its stability
|
||||||
|
guarantees across versions, and worked examples of a permitted retry and a
|
||||||
|
refused replay. Consumers cannot honour §6.4.2 against an undocumented digest,
|
||||||
|
and negative caching under §6.4.2 needs the same guidance.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue