--- # 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 > **Layer declaration.** flex-auth is **Engine / PDP** under the NetKingdom > Security Layer Model (`net-kingdom/canon/standards/security-layer-model_v0.7.md`, > accepted 2026-08-29). It is **the only policy decision point in NetKingdom** > (§6): no other repository, in any layer, renders or caches an authorization > decision. The frontmatter above is the machine-readable form §11 requires; this > paragraph is the declaration in flex-auth's own voice. > > The layer rule that binds every repository: **Staff never touches Tooling > directly. It acts only through Engine APIs.** flex-auth is one of those APIs. > > **What PDP means here, and what it does not.** As the estate's only PDP, > flex-auth's outage is *consumer residue*, not input degradation (§9.3): when > flex-auth is unreachable there is no evaluator in the path, so what happens > next is the consumer's declared stance and never flex-auth's to express. > Fail-open is not expressible by a PDP at all. When flex-auth is reachable but > 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. > > flex-auth reached this position by review rather than assertion, and holds > three records: `FLEX-DEC-2026-001` (Engine framing, the `access-engine` name, > the authoring/evaluation split), `FLEX-DEC-2026-002` (§9.3 contested and > upheld), and `FLEX-DEC-2026-003` (v0.6 review; §6.4.2, §9.7.2 and §17 as > adopted in v0.7). > > *One item remains open: the ruled rename to `access-engine`. It is a separate > 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 > pin binds tokens to the protected-system name; and `FLEX-WP` prefix ownership > stays with the repository.* > This file captures **why this repository exists**, the **direction it is > moving toward**, and the **kind of system it is meant to become**. > It is intentionally **aspirational and stable**, not a description of > current implementation. ## Intent Flex-auth is a policy-as-code authorization registry and **decision engine** for organizations that want to grow from simple access rules into enterprise-grade authorization without giving up clear ownership, local development ergonomics, or inspectable policy decisions. It is an **Engine**, role **PDP**, in the NetKingdom security layer model (`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 same result. Within NetKingdom it is **the only policy decision point** (standard §6). No 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 protected resources: ```text verified identity claims -> flex-auth policy-as-code and authorization registry -> protected systems and their resources ``` Flex-auth should run usefully on its own, and should also be able to delegate to or coordinate established authorization engines — relationship/graph engines, rule and attribute policy engines, and directory systems — without binding its own model to any one of them. ## Why This Exists Most organizations start with coarse roles, groups, and application-specific conditionals. Over time they need richer policy: - resource hierarchies and inherited access - project/team/tenant boundaries - relationship-based authorization - attribute and context based rules - emergency/break-glass controls - policy tests and reviewable changes - durable decision logs and explainability - integration with identity, MFA, service accounts, and directory groups Flex-auth should give those organizations a path that starts small and grows cleanly instead of forcing an early leap into a large IAM platform or letting authorization logic sprawl across applications. ## Responsibility Boundary Flex-auth consumes **verified identity claims** as normative input and never re-defines them. Identity proves who an actor is and how they were authenticated; flex-auth decides what that actor is allowed to do. ### The Identity Layer Owns Identity - Authentication, login, MFA, and token issuance and lifecycle. - The canonical identity claim contract and required claims. - Coarse roles, scopes, and assurance claims. ### Flex-Auth Owns the Decision - **Evaluation — exclusively.** Rendering the decision, in-path, deterministically. - Protected-system registration. - Resource namespaces and resource hierarchy. - Canonical action vocabulary. - The policy-as-code mechanism: package format, tests, versions, and rollout. - Mapping enterprise groups, app roles, scopes, tenants, and assurance claims into resource-specific authorization. - Relationship facts and inherited access. - PDP adapter coordination. - 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 Authoring and governing security doctrine is Staff work. `gate-house` owns the invariants policy must satisfy, the authority ceilings, the assistant and autonomous operating modes, and the **authority context** — principal, actor, runtime identity, tenant, mandate, operating mode — which flex-auth consumes as input claims alongside verified identity claims. The division is between *authoring the rules of the game* and *rendering a result*: gate-house designs the approval contract and the invariants; flex-auth validates approvals and renders decisions at request time. Neither can do the other's half. Policy **content** for a given protected system remains authored by that system's owner, within flex-auth's mechanism and gate-house's doctrine. Gate House holds no runtime position and never renders a decision. A deterministic authority boundary inside a non-deterministic layer would violate the invariant the estate is built on. One condition follows from that, drawn by flex-auth on review (FLEX-DEC-2026-001): an authority ceiling that determines an outcome must reach the decision either as an input claim on the request or as a rule in the versioned policy package, so that its application is reconstructable from the decision record. A ceiling that resolves an outcome before evaluation runs has decided early. This is not a limit on gate-house's authorship — it is what keeps that authorship auditable at decision time, and it is the same test flex-auth applied to zone-engine's zone stance and, in the note above, to its own registry. ### Protected Systems Own Enforcement Applications remain policy enforcement points. They extract resource metadata, call flex-auth for decisions, enforce allow/deny/redact results, and emit local diagnostics. They do not own central policy administration. ### Access Lanes Are Not Access Rules The estate uses "access" for two different things, and the demarcation is normative (standard §8): - **ops-warden and ops-mason own access lanes** — how a worker reaches a host: routes, tunnels, SSH certificates, credential lanes. - **flex-auth owns access rules** — whether an actor may act at all. A lane delivers someone to the door. This repository decides whether the door opens. Neither substitutes for the other, and neither owns the other's word. ## Design Principles - Policy is code: versioned, reviewed, tested, and explainable. - Identity is not authorization: identity claims are inputs, not final decisions. - Start standalone, scale outward: a local flex-auth deployment should be useful before any external policy engine integration is available. - Backend-neutral core: flex-auth has its own resource, action, request, decision, and audit vocabulary. - Pluggable PDPs: relationship, rule, and directory engines are adapters, not hard dependencies. - Fail visibly: denied, redacted, stale, partial, and uncertain decisions must produce useful diagnostics. - Grow into enterprise: the same model should support local dev, small teams, and larger enterprise environments. ## First-Class Concepts - Subject: human, service account, group, team, tenant, emergency principal. - Resource: protected object registered by a system. - Namespace: resource type and ownership boundary. - Action: operation requested on a resource. - Context: request, environment, assurance, workflow, or runtime attributes. - Policy package: versioned policy-as-code bundle with tests and metadata. - Relationship fact: subject-resource or resource-resource relation. - Decision: allow, deny, redact, audit-only, or not-applicable with reason. - Audit event: durable decision record with policy version and provenance. ## Initial API Shape ```text register_system(system_manifest) register_resource(resource_manifest) sync_relationships(relationship_manifest) check(subject, action, resource, context) -> decision batch_check(subject, action, resources, context) -> decisions list_allowed(subject, action, resource_type, filters, context) -> resources explain(decision_id) -> explanation publish_policy_package(package) test_policy_package(package, fixtures) activate_policy_version(policy_id, version) record_decision(decision) ``` ## Standalone Mode Standalone flex-auth should provide: - local resource registry - local subject/group/team registry - local relationship facts - policy package validation - deterministic check and batch-check APIs - local decision log - CLI and service mode - test fixtures for representative identity claims Standalone mode should be enough for development, smaller deployments, and integration tests. ## Delegated Mode Delegated mode should let flex-auth coordinate established systems without adopting their models as its own: - relationship/graph engines for relationship-heavy authorization - rule and attribute policy engines for attribute/rule policies - directory systems for group resolution - a local directory plus policy-evaluation engine for self-contained delegated setups Flex-auth remains the stable decision point even when the backend changes. ## Consumer Patterns Two consumer shapes drive flex-auth, and the first one to ship deliberately is not a document pipeline — proving the decision engine stays generic. **First shipped consumer — an action gate (ops-warden SSH signing).** A protected system asks flex-auth a single "may this actor perform this action now?" question before doing irreversible work: - it registers a protected system, a resource type (`ssh-certificate`), and an action (`sign`) - it sends one policy check per request, passing subject, resource, and context (actor type, principals, TTL, key fingerprint) - it enforces the allow/deny decision and records the decision id for audit - flex-auth owns the policy and durable decision log; the protected system keeps custody of its own keys and secrets This first consumer validated that flex-auth's resource/action/context model, `POST /v1/check` contract, and decision envelope work for a non-document, high-stakes gate without any consumer-specific routes. **First knowledge-pipeline consumer (planned) — a document and knowledge pipeline (Markitect):** - it registers knowledge bases, repositories, documents, sections, context packages, workflow artifacts, and exports - it sends policy checks before returning query/search/context results - it can redact or drop results based on decisions - flex-auth owns central policy administration and durable audit Together these shape flex-auth around real authorization needs — both point-in-time action gates and result-filtering pipelines — without making the 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 - Flex-auth is not an identity provider. - Flex-auth is not a replacement for an identity or SSO system. - Flex-auth is not a mandatory dependency for every local development use case. - Flex-auth should not force one PDP backend. - Flex-auth should not hide policy complexity behind opaque admin toggles. ## Early Work 1. Define the resource/action/decision model. 2. Define policy package structure and test fixtures. 3. Implement standalone registry and check API. 4. Add a first protected-system resource manifest and policy adapter. 5. Evaluate a delegated directory-plus-policy backend. 6. Add relationship-engine and rule-engine adapter spikes. 7. Add identity and enterprise-directory integration examples.