Declare Engine/PIP and open USER-WP-0024 for layer conformance
Adopt security-layer-model v0.7 in INTENT.md in this repository's own voice, restate SCOPE.md from that declaration, and record the scope-versus-implementation assessment. USER-IN-0001 is answered; runtime follow-through is USER-WP-0024. Assistant: grok Assistant-Session: 01a04cea-f0d6-7ab3-9ffd-881eb6bea6cb
This commit is contained in:
parent
7961518be5
commit
96430299b7
5 changed files with 692 additions and 47 deletions
151
INTENT.md
151
INTENT.md
|
|
@ -1,24 +1,94 @@
|
|||
# INTENT
|
||||
---
|
||||
layer: Engine
|
||||
role: PIP
|
||||
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
|
||||
companion: net-kingdom/SECURITY-COMPANION.md
|
||||
declared: "2026-08-29"
|
||||
---
|
||||
|
||||
> **NetKingdom layering review — 2026-08-28.** This repository's role was reviewed
|
||||
> against the NetKingdom IT-security layer model: **Taxonomy → Tooling → Engines →
|
||||
> Staff**, layered by determinism and by the kind of artifact each layer produces.
|
||||
> Findings and the argument behind them:
|
||||
> `gate-house/history/2026-08-28-security-layer-model-and-gate-house-recut.md`.
|
||||
> The model is `net-kingdom/canon/standards/security-layer-model_v0.1.md` (proposed),
|
||||
> ratified by `gate-house/decisions/decisions.md` GH-DEC-2026-001.
|
||||
>
|
||||
> The layer rule that binds every repository: **Staff never touches tooling
|
||||
> directly. It acts only through engine APIs.**
|
||||
>
|
||||
> **This repository is Engine — deterministic API for a modeled concept.** Add the layer label. The existing boundary contract (`net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`) holds unchanged. Worth making explicit that user-engine supplies subject context as input to the authorization decision and never renders one.
|
||||
>
|
||||
> *This note records what should change. The body below is not yet adapted.*
|
||||
# INTENT
|
||||
|
||||
> 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.
|
||||
|
||||
## Layer
|
||||
|
||||
**Engine, role PIP.** This is user-engine's own declaration under the
|
||||
NetKingdom Security Layer Model
|
||||
([`SECURITY-COMPANION.md`](../net-kingdom/SECURITY-COMPANION.md) v0.2;
|
||||
statute [`security-layer-model_v0.7.md`](../net-kingdom/canon/standards/security-layer-model_v0.7.md),
|
||||
accepted 2026-08-29). A layer stated about this repository by another
|
||||
repository is not a declaration; this one is.
|
||||
|
||||
The same authoritative user-domain inputs yield the same result. That
|
||||
determinism is the test. user-engine is not Staff: it is not a judgment
|
||||
surface. It is not Tooling: it does not package identity infrastructure or
|
||||
hold runtime secrets. It is not the PDP: `access-engine` (`flex-auth` until
|
||||
the governed rename) is the only decision point in the estate.
|
||||
|
||||
The catalog row we accept: **users, accounts, memberships.** The existing
|
||||
boundary contract
|
||||
(`net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`) holds
|
||||
unchanged. What the model adds, and what this file now states in our own
|
||||
voice:
|
||||
|
||||
- we **supply subject context as claims** a decision consumes;
|
||||
- we **never render, cache, or compile an authorization decision**;
|
||||
- a new engine is a PIP unless the statute is amended, and we stay one.
|
||||
|
||||
**PEP-shaped, same layer.** Protected mutations in this service — account
|
||||
lifecycle, memberships, invitations, registration orchestration, hat
|
||||
selection, catalog and profile writes — proceed only after a decision from
|
||||
`access-engine`, or under a published unreachable-engine stance whose
|
||||
application is recorded in place of a decision. Being PEP-shaped does not
|
||||
move the repository out of Engine/PIP. The stance map belongs at a path
|
||||
named in the machine-readable layer declaration, registered in statute
|
||||
§13.1; shipping fail-closed in an adapter is not publication.
|
||||
|
||||
**Not contested.** Engine/PIP is the right assignment. What we raise back
|
||||
is that §4 catalogues us as Engine/PIP and does not mark the PEP shape
|
||||
that our protected mutations already have. That is a register finding,
|
||||
not a layer dispute.
|
||||
|
||||
### Binding rules this repository keeps
|
||||
|
||||
1. **One decision point.** `access-engine` renders authorization decisions.
|
||||
user-engine asks, enforces, and records. Access-control facts, hats,
|
||||
memberships, and projections are inputs and read models, never a local
|
||||
allow.
|
||||
2. **Compiled data that determines an outcome is still deciding.** A
|
||||
registry, cache, or access-profile schema that resolved a result before
|
||||
the engine ran would be an early decision. Provenance of anything we
|
||||
export as claims must remain reconstructable from the decision record
|
||||
that consumed it.
|
||||
3. **Doctrine arrives as a claim.** Nothing we hold — membership, hat,
|
||||
assurance forwarded from IAM, tenant capability roles — becomes
|
||||
authority except by reaching `access-engine` as a request claim or a
|
||||
versioned policy rule.
|
||||
4. **Adaptive systems may only tighten.** user-engine does not manufacture
|
||||
authority, and it does not assume the estate can contain anything
|
||||
automatically. Actuation is unowned and held at zero.
|
||||
5. **Every allow has a lifetime.** A decision we enforce is used within
|
||||
its stated binding and lifetime, not as a standing grant.
|
||||
6. **Evidence proves alteration and truncation, not omission at source.**
|
||||
Local audit and the durable outbox prove the records they hold. They
|
||||
do not prove that an event never sent did not happen. Completeness is
|
||||
not claimed.
|
||||
7. **Agents working this repository are Staff principals**, not a second
|
||||
layer. No standing credential, tool use only as a conduit or an Engine
|
||||
API, memory is not a state plane, every action reconstructable as the
|
||||
caller's. How to get a credential or a lane is `ops-warden`'s, not
|
||||
this file's.
|
||||
|
||||
**Tooling.** §5 binds Staff. This Engine owns the persistence of the
|
||||
concept it models (the user-domain store). It consumes verified IAM
|
||||
Profile claims from `key-cape` / Keycloak / `local-identity`, and runtime
|
||||
secret *references* injected by Railiance. It holds no OpenBao client and
|
||||
no Keycloak admin client. A `SecretProvider` port exists so an engine
|
||||
surface can replace environment injection when `secrets-engine` exposes
|
||||
one; until then that capability is at zero here, not taken locally.
|
||||
|
||||
## Purpose
|
||||
|
||||
`user-engine` exists to provide a reusable, headless user-domain and
|
||||
|
|
@ -27,6 +97,11 @@ preference, membership, identity-context, and application-specific user
|
|||
attribute management without coupling those concerns to a particular identity
|
||||
provider, authorization engine, security stack, or user interface.
|
||||
|
||||
As a PIP it is the estate's source of user-domain facts that authorization
|
||||
and consuming applications may take as claims: who the subject is in a
|
||||
domain context, which account and memberships apply, which profile
|
||||
material may be projected, and which identity-context mappings hold.
|
||||
|
||||
## Primary Utility
|
||||
|
||||
The project provides a canonical user layer that can start small in a
|
||||
|
|
@ -45,13 +120,16 @@ It manages:
|
|||
- profile projections for consuming applications;
|
||||
- lifecycle and profile-change events.
|
||||
|
||||
Those records are the PIP surface. They are not a policy package.
|
||||
|
||||
## Strategic Direction
|
||||
|
||||
`user-engine` is intended to become the NetKingdom identity-domain integration
|
||||
layer: a headless service that exposes canonical identity, user, account,
|
||||
layer: a headless Engine that exposes canonical identity, user, account,
|
||||
membership, tenant, team, profile, lifecycle, and evidence-facing concepts to
|
||||
applications without requiring those applications to know the technical IAM,
|
||||
security, authorization, audit, or secret-management implementation details.
|
||||
applications, and that supplies those facts as claims to `access-engine`,
|
||||
without requiring those applications to know the technical IAM, security,
|
||||
authorization, audit, or secret-management implementation details.
|
||||
|
||||
NetKingdom infrastructure remains the source of truth for authentication,
|
||||
credential assurance, token issuance, policy decisions, security controls,
|
||||
|
|
@ -70,6 +148,9 @@ applications and agents to answer:
|
|||
claims-enrichment contexts;
|
||||
- which lifecycle, access-review, evidence, or integration gaps need attention.
|
||||
|
||||
It should never answer whether an actor may act. That answer is
|
||||
`access-engine`'s, including when the resource is a user-engine record.
|
||||
|
||||
## Strategic Role
|
||||
|
||||
`user-engine` separates user-domain management from authentication,
|
||||
|
|
@ -85,6 +166,11 @@ identity-context mappings. It should reference, map to, or consume adjacent
|
|||
canon entities when their source of truth belongs to NetKingdom infrastructure,
|
||||
security, access-control, governance, or organization systems.
|
||||
|
||||
Hats, realms, services, assets, and access profiles stay user-domain facts
|
||||
and claim templates. They exist so `access-engine` and consuming runtimes
|
||||
can see the same subject context; they do not become a second decision
|
||||
point by compilation or by local evaluation.
|
||||
|
||||
## Intended Users
|
||||
|
||||
- application developers adding user/account functionality to a service;
|
||||
|
|
@ -96,7 +182,9 @@ security, access-control, governance, or organization systems.
|
|||
context;
|
||||
- domain services that need identity-canon aligned user, actor, principal,
|
||||
subject, tenant, team, membership, and evidence references without depending
|
||||
on technical IAM implementation details.
|
||||
on technical IAM implementation details;
|
||||
- `access-engine`, as a PIP consumer of subject, membership, and
|
||||
access-control facts.
|
||||
|
||||
## Product Boundaries
|
||||
|
||||
|
|
@ -107,15 +195,19 @@ It does not aim to be:
|
|||
- a full identity provider;
|
||||
- a password, passkey, session, or MFA system;
|
||||
- a fine-grained authorization engine;
|
||||
- the policy decision point for protected resources;
|
||||
- the policy decision point for protected resources, including its own;
|
||||
- the owner of NetKingdom security controls or runtime secrets;
|
||||
- the full organization, HR, or directory authority;
|
||||
- a directory server;
|
||||
- a UI application.
|
||||
- a UI application;
|
||||
- an observer of production security events;
|
||||
- an actuation surface for containment, step-up, or authority reduction.
|
||||
|
||||
It provides the user-domain and identity-domain APIs, mapping records, catalog
|
||||
metadata, projections, events, evidence references, and audit records that those
|
||||
surrounding systems can consume.
|
||||
metadata, projections, events, evidence references, and local audit records
|
||||
that those surrounding systems can consume. Platform audit custody stays
|
||||
with `audit-core`. Optional UI in this repository is a surface over the
|
||||
same APIs, not a product identity.
|
||||
|
||||
## Design Principles
|
||||
|
||||
|
|
@ -124,14 +216,17 @@ surrounding systems can consume.
|
|||
- standalone-friendly;
|
||||
- enterprise-integratable;
|
||||
- identity-provider agnostic;
|
||||
- authorization-engine agnostic;
|
||||
- authorization-engine agnostic — and never a substitute for one;
|
||||
- NetKingdom-integrated without hiding source-of-truth boundaries;
|
||||
- canon-aligned through explicit entity and relationship mappings;
|
||||
- catalog-driven customization;
|
||||
- explicit ownership, visibility, mutability, and sensitivity of attributes;
|
||||
- layered profiles instead of one global metadata blob;
|
||||
- deterministic and inspectable effective profile resolution;
|
||||
- evidence and lifecycle awareness for identity-domain changes;
|
||||
- evidence and lifecycle awareness for identity-domain changes, bounded by
|
||||
what an archive can actually prove;
|
||||
- fail closed on unreachable `access-engine` for protected mutations, with
|
||||
that stance published rather than implied by adapter code;
|
||||
- concrete user-domain focus with a possible future extraction path toward a
|
||||
generic profile engine.
|
||||
|
||||
|
|
@ -147,3 +242,9 @@ intent: applications should be able to consume user, account, identity-link,
|
|||
actor, principal, subject, tenant, team, membership, profile, lifecycle, and
|
||||
evidence context through stable APIs and mappings without taking a direct
|
||||
dependency on the technical IAM, authorization, security, or audit substrate.
|
||||
|
||||
It succeeds as a PIP when `access-engine` can consume those facts as claims
|
||||
and reconstruct their application from the decision record, and as a
|
||||
PEP-shaped engine when every protected mutation it performs is bound to a
|
||||
decision or to a recorded stance, with a lifetime, and without a second
|
||||
decision point hiding in a cache, a hat, or a local adapter.
|
||||
|
|
|
|||
108
SCOPE.md
108
SCOPE.md
|
|
@ -1,11 +1,25 @@
|
|||
# SCOPE
|
||||
|
||||
## Layer
|
||||
|
||||
**Engine, role PIP** — deterministic API for users, accounts, and
|
||||
memberships. Subject context is an input to the authorization decision and
|
||||
never a decision. Protected mutations are PEP-shaped: they consume
|
||||
`access-engine` (`flex-auth`) and do not substitute for it.
|
||||
|
||||
Declaration: `INTENT.md` frontmatter. Statute:
|
||||
`net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted).
|
||||
Working companion: `net-kingdom/SECURITY-COMPANION.md`. Boundary contract
|
||||
unchanged:
|
||||
`net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`.
|
||||
|
||||
## One-Liner
|
||||
|
||||
Headless user-domain and identity-domain service for accounts, identity
|
||||
links, memberships, catalogs, projections, audit, and events, with an
|
||||
Headless user-domain and identity-domain Engine (PIP) for accounts, identity
|
||||
links, memberships, catalogs, projections, local audit, and events, with an
|
||||
optional in-repo portal. It consumes NetKingdom IAM, authorization, tenant
|
||||
authority, provisioning, and delivery; it does not own them.
|
||||
authority, provisioning, and delivery; it does not own them and it does not
|
||||
decide them.
|
||||
|
||||
## In Scope
|
||||
|
||||
|
|
@ -17,8 +31,10 @@ authority, provisioning, and delivery; it does not own them.
|
|||
preferences;
|
||||
- tenant, application, team, and scope memberships;
|
||||
- hats, realms, services, assets, access profiles, and active access
|
||||
context as user-domain facts;
|
||||
context as user-domain facts and claim templates;
|
||||
- identity-context read models for domain consumers;
|
||||
- PIP exports: subject, membership, and access-control facts for
|
||||
`access-engine` and other engines to consume as claims;
|
||||
- canon interface cards, entity and relationship mappings, and explicit
|
||||
gap records;
|
||||
- application registry for profile consumers;
|
||||
|
|
@ -35,17 +51,22 @@ authority, provisioning, and delivery; it does not own them.
|
|||
(create, read, update, retire, reactivate, recover);
|
||||
- optional CSRF-protected portal over the same APIs (self-service,
|
||||
onboarding, tenant admin, platform operator);
|
||||
- standalone/local fixtures and a production PostgreSQL store;
|
||||
- standalone/local fixtures and a production PostgreSQL store of the
|
||||
modeled concept;
|
||||
- integration ports for claims, flex-auth decisions (including a rotating
|
||||
caller token), provisioning, registration verification, tenant
|
||||
management, outbox delivery, and runtime secrets.
|
||||
management, outbox delivery, and runtime secrets;
|
||||
- PEP enforcement of `access-engine` decisions on user-engine-owned
|
||||
mutations, including a published unreachable-engine stance.
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- login, OIDC/SAML token issuance, passwords, passkeys, sessions, and MFA
|
||||
lifecycle — `key-cape`, Keycloak, or `local-identity`;
|
||||
- final authorization policy decisions and the protected-system registry —
|
||||
`flex-auth`;
|
||||
`flex-auth` / `access-engine`;
|
||||
- caching or compiling an authorization decision, including from hats,
|
||||
access profiles, or memberships;
|
||||
- durable authorization grants beyond user-engine-owned memberships;
|
||||
- tenant identifier authority, grouping reclassification, and capability
|
||||
role grants — `tenant-engine`;
|
||||
|
|
@ -53,16 +74,22 @@ authority, provisioning, and delivery; it does not own them.
|
|||
consuming apps (e.g. coulomb-social) and KeyCape client policy;
|
||||
- policy, control, access-review, exception, and organization
|
||||
source-of-truth ownership;
|
||||
- runtime secret custody — OpenBao / Railiance;
|
||||
- runtime secret custody — OpenBao / Railiance; no OpenBao client here;
|
||||
- a Keycloak or key-cape admin client;
|
||||
- platform audit store and transactional SMTP — `audit-core` and
|
||||
`email-connect`;
|
||||
- full SCIM server, enterprise directory replacement, or inbound
|
||||
SAML/OIDC federation (demand-triggered; Keycloak expanded mode is the
|
||||
published path);
|
||||
- a generic extracted profile engine.
|
||||
- a generic extracted profile engine;
|
||||
- observing production security events — `kings-guard`, and currently
|
||||
unstaffed;
|
||||
- actuation: reduce authority, require step-up, isolate a workload — an
|
||||
Engine concept held at zero estate-wide.
|
||||
|
||||
The in-repo portal is an optional surface, not a UI product. Password and
|
||||
MFA screens stay on the identity provider.
|
||||
MFA screens stay on the identity provider. `LocalAuthorizationCheckPort`
|
||||
is a test and standalone double, not a production decision point.
|
||||
|
||||
## Boundary Rule
|
||||
|
||||
|
|
@ -73,6 +100,13 @@ deployment, event transport, durable audit, secrets, organization records,
|
|||
or additional UI — and they integrate through explicit adapters. They must
|
||||
not become hidden sources of profile or identity-domain truth.
|
||||
|
||||
user-engine must not become a hidden source of authorization truth.
|
||||
Memberships, hats, and access-control facts are claims. `access-engine`
|
||||
renders the decision. When `access-engine` is unreachable, shipped
|
||||
behaviour is fail-closed for protected mutations; that stance still has
|
||||
to be published, tested equal to the code, and recorded as stance
|
||||
application rather than as a minted local decision id.
|
||||
|
||||
Governing published contracts:
|
||||
|
||||
- IAM Profile v0.3 — https://policy.coulomb.social/standards/iam-profile/v0.3/
|
||||
|
|
@ -80,15 +114,23 @@ Governing published contracts:
|
|||
- NetKingdom architecture — https://policy.coulomb.social/architecture/net-kingdom/v0.1/
|
||||
- User-engine boundary contract (accepted, not yet published) —
|
||||
`~/net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`
|
||||
- NetKingdom Security Layer Model v0.7 (accepted) —
|
||||
`~/net-kingdom/canon/standards/security-layer-model_v0.7.md`
|
||||
- Working companion —
|
||||
`~/net-kingdom/SECURITY-COMPANION.md`
|
||||
|
||||
## Current Status
|
||||
|
||||
Workplans `USER-WP-0001` through `USER-WP-0023` are finished. There is no
|
||||
active workplan. The isolated MVP, multi-tenancy, catalogs, canon
|
||||
alignment, durable PostgreSQL store, self-service and admin portal,
|
||||
public-registration orchestration, and flex-auth caller identity (live A2
|
||||
on `flex-auth-user-engine`) are in the repo and, where applicable, on
|
||||
Railiance.
|
||||
Workplans `USER-WP-0001` through `USER-WP-0023` are finished. The isolated
|
||||
MVP, multi-tenancy, catalogs, canon alignment, durable PostgreSQL store,
|
||||
self-service and admin portal, public-registration orchestration, and
|
||||
flex-auth caller identity (live A2 on `flex-auth-user-engine`) are in the
|
||||
repo and, where applicable, on Railiance.
|
||||
|
||||
`USER-WP-0024` is the active workplan: layer declaration is in `INTENT.md`;
|
||||
machine-readable conformance, the published PEP stance map, decision
|
||||
lifetime, evidence cadence, and the access-control-fact claim contract
|
||||
are not yet shipped.
|
||||
|
||||
Still operator-owned, not remaining product scope:
|
||||
|
||||
|
|
@ -100,10 +142,25 @@ Still operator-owned, not remaining product scope:
|
|||
- `policy.enabled` and tenant-engine caller `enforce` belong to flex-auth
|
||||
/ tenant-engine.
|
||||
|
||||
Layer-model residue that is remaining product scope, tracked in
|
||||
`USER-WP-0024` and assessed in
|
||||
`history/2026-08-29-security-layer-scope-intent-assessment.md`:
|
||||
|
||||
- no `layer.yaml` and no conformance check;
|
||||
- unreachable-engine stance is fail-closed in
|
||||
`FlexAuthHTTPAdapter` but unpublished, untested against a map, and
|
||||
recorded as a locally minted `decision_id`;
|
||||
- `AuthorizationDecision` carries no lifetime;
|
||||
- denials have no declared emission cadence or heartbeat;
|
||||
- `LocalAuthorizationCheckPort` defaults to allow and is a second
|
||||
decision point if a production runtime ever constructed it.
|
||||
|
||||
## Against INTENT.md
|
||||
|
||||
INTENT is the stable aspiration. Against it, the repo now does the job it
|
||||
set out to do.
|
||||
INTENT is the stable aspiration. Against the pre-layer product aims, the
|
||||
repo still does the job it set out to do. Against the layer declaration
|
||||
now in INTENT, SCOPE is narrower than INTENT on conformance artifacts
|
||||
and PEP obligations.
|
||||
|
||||
| INTENT aim | Status |
|
||||
| --- | --- |
|
||||
|
|
@ -112,10 +169,17 @@ set out to do.
|
|||
| Users, links, memberships, catalogs, projections, events | Met. |
|
||||
| NetKingdom identity-domain integration layer | Met for the owned slice. Consumes KeyCape, flex-auth, tenant-engine, identity-provisioner, audit-core, email-connect. |
|
||||
| Applications answer who / which scopes / what to project | Met via `/me`, identity context, catalogs, and projections. |
|
||||
| Engine / PIP declaration in own voice | Met in `INTENT.md` as of 2026-08-29. Closes the declaration half of `USER-IN-0001`. |
|
||||
| Subject context is a claim, never a decision | Held in production path (`FlexAuthHTTPAdapter`). Not yet proven for hats/access-control facts under §6.1, and the local double can still decide. |
|
||||
| PEP-shaped: no side effect without a decision or recorded stance | Partial. Production asks flex-auth and fail-closes on errors. Stance is unpublished; unavailable DENY mints a local `decision_id`. |
|
||||
| Published unreachable-engine stance map, tested equal to shipped behaviour | Missing. |
|
||||
| Every allow has a lifetime | Missing on `AuthorizationDecision`. |
|
||||
| Evidence bound: no completeness claim; cadence for load-bearing events | Partial. Mutations enqueue audit+outbox in the same store transaction. Completeness is not claimed in code; docs do not classify load-bearing vs attributive or declare a cadence. |
|
||||
| Not an IdP, PDP, secret store, directory, or org authority | Held. |
|
||||
| Optional UI, not UI-driven | Held, with a narrower reading: an optional portal now lives *in this repo* over the same APIs. INTENT's "not a UI application" still applies to product identity. |
|
||||
| Canon-aligned mappings without taking IAM as SoT | Met (`USER-WP-0007`, interface card). Access-review, policy, and control remain references, not owned records. |
|
||||
| Path from local setup to governed NetKingdom deploy | Met. |
|
||||
| No OpenBao / key-cape admin client | Held. `SecretProvider` is an unused port; runtime reads env. |
|
||||
|
||||
Still aspirational, and deliberately not started here:
|
||||
|
||||
|
|
@ -123,6 +187,10 @@ Still aspirational, and deliberately not started here:
|
|||
demand, targeting published Keycloak expanded mode;
|
||||
- first-class access-review and governance records;
|
||||
- a dedicated agent consumption product (projections exist);
|
||||
- extracting a generic profile engine.
|
||||
- extracting a generic profile engine;
|
||||
- observing production, or actuating containment — estate-wide zeros,
|
||||
not this repo's gaps to close.
|
||||
|
||||
Those remain INTENT, not a hole in SCOPE.
|
||||
Those remain INTENT, not a hole in SCOPE, except the layer-conformance
|
||||
rows above, which are now SCOPE because INTENT has adopted the accepted
|
||||
standard.
|
||||
|
|
|
|||
317
history/2026-08-29-security-layer-scope-intent-assessment.md
Normal file
317
history/2026-08-29-security-layer-scope-intent-assessment.md
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
# Security layer model — scope vs intent vs implementation
|
||||
|
||||
**Date:** 2026-08-29
|
||||
**Repository:** user-engine
|
||||
**Audience:** user-engine, gate-house, flex-auth, ops-warden
|
||||
**Status:** current-state review, not a decision record
|
||||
**Sources:**
|
||||
|
||||
- `net-kingdom/SECURITY-COMPANION.md` v0.2 (operative form; start here)
|
||||
- `net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted statute)
|
||||
- `net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`
|
||||
- `INTENT.md` and `SCOPE.md` as adapted this session
|
||||
- `intakes/intakes.md` `USER-IN-0001`
|
||||
- gate-house broadcast 2026-08-29 (accepted v0.7; nine undeclared repositories)
|
||||
- working references: `ops-warden/layer.yaml`, `ops-warden/pep-stance.yaml`,
|
||||
`kings-guard/layer.yaml`
|
||||
- implementation: `src/user_engine/service.py`,
|
||||
`src/user_engine/adapters/flex_auth.py`,
|
||||
`src/user_engine/adapters/local.py`,
|
||||
`src/user_engine/domain/models.py`,
|
||||
`src/user_engine/runtime.py`,
|
||||
`src/user_engine/projections.py`
|
||||
|
||||
The statute governs where the companion and the statute disagree. No
|
||||
disagreement was found that this review needed to work around.
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive assessment
|
||||
|
||||
user-engine is already the product INTENT described before the layer
|
||||
model: a headless user-domain service with ports, a PostgreSQL store, a
|
||||
portal, and a live flex-auth caller. That slice is finished through
|
||||
`USER-WP-0023`.
|
||||
|
||||
The accepted layer model asks for something the product workplans never
|
||||
carried: an own-voice Engine/PIP declaration, a machine-readable
|
||||
conformance surface, and the PEP obligations that attach to any runtime
|
||||
that causes a protected side effect.
|
||||
|
||||
Until this session the repository carried only a gate-house review note
|
||||
on `INTENT.md` that named a layer and admitted the body was unadapted.
|
||||
That is not a declaration (companion §2, statute §11). `USER-IN-0001`
|
||||
stayed open.
|
||||
|
||||
This review records the declaration, the SCOPE restatement, and the
|
||||
implementation gaps that must move. It does not contest Engine/PIP.
|
||||
|
||||
---
|
||||
|
||||
## 2. What we declare, and what we do not contest
|
||||
|
||||
| Item | Position |
|
||||
| --- | --- |
|
||||
| Layer | **Engine** |
|
||||
| Role | **PIP** |
|
||||
| Catalog owns | users, accounts, memberships |
|
||||
| Boundary contract | unchanged |
|
||||
| One decision point | `access-engine` / `flex-auth`; we supply claims and enforce results |
|
||||
| Contest the proposed layer? | **No.** Same inputs, same user-domain result. Not inference, not Tooling, not the PDP. |
|
||||
|
||||
**Finding, not a contest.** Statute §4 catalogues user-engine as Engine/PIP
|
||||
and does not mark it PEP-shaped. Companion §5 and statute §6.4 say a PEP
|
||||
is any runtime that causes a protected side effect; being PEP-shaped does
|
||||
not change layer. user-engine's production mutations (account lifecycle,
|
||||
memberships, invitations, registration, hat selection, catalog and
|
||||
profile writes) are protected side effects gated on flex-auth. We are
|
||||
PEP-shaped in fact. §13.1 currently inventories `ops-warden` (published)
|
||||
and `ops-mason` (missing). user-engine is a third PEP-shaped consumer
|
||||
with no row. One row was already the finding; a silent third is worse.
|
||||
|
||||
Raised for gate-house to inventory. We do not ask to be recatalogued as
|
||||
Staff.
|
||||
|
||||
---
|
||||
|
||||
## 3. Intent vs scope after the adaptation
|
||||
|
||||
INTENT is now the layer declaration plus the previous product aspiration.
|
||||
SCOPE is the implemented product plus the layer obligations that are now
|
||||
in-scope because INTENT adopted them.
|
||||
|
||||
| Area | INTENT | SCOPE after this session | Implementation |
|
||||
| --- | --- | --- | --- |
|
||||
| Engine / PIP declaration | Required, own voice, frontmatter | Declared; points at companion and statute | Frontmatter present. No `layer.yaml`. |
|
||||
| Users, accounts, memberships | Own them | Own them | Shipped. |
|
||||
| Claims, not decisions | Subject context is a PIP input | Explicit; local double excluded from production | Production asks flex-auth. Hats/facts not yet proven under §6.1. Local port can still decide. |
|
||||
| PEP stance map | Published, tested equal to code, inventoried in §13.1 | Named as remaining product scope | Fail-closed in `FlexAuthHTTPAdapter`; unpublished. |
|
||||
| Allow lifetime | Every allow has a lifetime | Named as missing | `AuthorizationDecision` has effect, id, reason, obligations. No TTL or binding. |
|
||||
| Evidence bound | No completeness claim; cadence for load-bearing | Named as partial | Local outbox is transactional with mutations. No classification, no cadence. |
|
||||
| Tooling contacts | No OpenBao or key-cape admin client | Out of scope | Held. Env-injected secrets. Unused `SecretProvider` port. |
|
||||
| Observation / actuation | Do not assume either exists | Out of scope | Not implemented. Correct. |
|
||||
|
||||
SCOPE is not silently claiming INTENT's new layer obligations as done.
|
||||
The remaining holes are listed in SCOPE "Current Status" and mapped to
|
||||
`USER-WP-0024`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Implementation assessment against the companion
|
||||
|
||||
Companion sections are the working checklist. Statute citations in
|
||||
parentheses.
|
||||
|
||||
### 4.1 Declare your layer (companion §2 / statute §11)
|
||||
|
||||
**Before this session:** undeclared. Gate-house prose in `INTENT.md` is
|
||||
explicitly not a declaration.
|
||||
|
||||
**After this session:** `INTENT.md` frontmatter `layer: Engine`,
|
||||
`role: PIP`, plus own-voice body. That is the form companion §2 asks
|
||||
for.
|
||||
|
||||
**Still missing:** a machine-readable declaration file equivalent to
|
||||
`ops-warden/layer.yaml`. Statute §11 allows frontmatter *or* an
|
||||
equivalent file; the working references use a file because that is what
|
||||
a conformance script can fail a commit against. user-engine has no
|
||||
checker, so a new OpenBao import would not fail the build. Necessity:
|
||||
add `layer.yaml` and a check adapted from kings-guard (Engine, not Staff;
|
||||
expect no Tooling client, record non-Tooling clients).
|
||||
|
||||
### 4.2 Rules that bind everyone (companion §3 / statute §6, §8, §9.7)
|
||||
|
||||
| Rule | Shipped behaviour | Gap |
|
||||
| --- | --- | --- |
|
||||
| One decision point | Production `FlexAuthHTTPAdapter` POSTs `/v1/check`. Service `_authorize` denies on non-allow. | `LocalAuthorizationCheckPort` *is* a local PDP (default ALLOW, reason `"local"`). Runtime assembly uses flex-auth only, but nothing prevents a production constructor from passing the local port. |
|
||||
| Compiled data still deciding | Access-control facts and hats are documented as claim templates (`docs/hats-realms-services-assets-access-profiles.md`). Projections cache profile material only (`projections.py`). | No test that a consumer cannot treat `AccessControlFact` or an active hat as an allow. Tenant capability roles are forwarded, not evaluated — held, documented in the architecture blueprint. |
|
||||
| Doctrine as a claim | We do not apply zone stance or maturity ourselves. | None for doctrine we author — we author none. |
|
||||
| Adaptive systems only tighten | We do not raise authority on missing evidence. | Held. Do not plan around actuation; it is at zero. |
|
||||
| Staff never touches Tooling | We are Engine; §5 does not bind this shape the same way. PostgreSQL is the modeled-concept store, not a §4 Tooling row. | Record PostgreSQL, State Hub, and env-injected secrets as non-Tooling / own-store in `layer.yaml` so the check is total. |
|
||||
| Every allow has a lifetime | Not modelled. | `AuthorizationDecision` must carry a lifetime (TTL or session/obligation binding). Replay of a stored verdict outside that lifetime is a second decision point. Today we do not cache verdicts, which is the safe subset, but we also cannot state a deadline (statute §9.7.2: a PEP MUST state one). |
|
||||
|
||||
### 4.3 If you touch Tooling (companion §4 / statute §5)
|
||||
|
||||
Catalogued Tooling is `key-cape` and `OpenBao`.
|
||||
|
||||
| Contact | Present? | Shape |
|
||||
| --- | --- | --- |
|
||||
| OpenBao HTTP/CLI | No | Blocked-clean on a secrets-engine signing/read surface. Runtime secrets come from the environment / projected files (`runtime.py`). |
|
||||
| key-cape admin / LDAP | No | Consumes verified IAM Profile claims (OIDC/JWKS). That is Engine input, not a Staff Tooling client. |
|
||||
| PostgreSQL | Yes — own store | Modeled-concept persistence for a PIP. Not §4 Tooling. List it in the declaration so the check is total. |
|
||||
| State Hub | Agents writing progress, not the service | Not catalogued. List as non-Tooling. Carve-out sunsets; we do not become a second state plane. |
|
||||
|
||||
No §5.1/§5.2/§5.3 Staff contact exists. Conformance state for Tooling
|
||||
contact is **conforming** (Engine with no catalogued Tooling client),
|
||||
provided we declare the own-store and non-Tooling clients rather than
|
||||
leave them silent.
|
||||
|
||||
`SecretProvider` in `ports.py` has no implementation. Leave it as a port.
|
||||
Do not add an OpenBao adapter to close it.
|
||||
|
||||
### 4.4 If you cause side effects (companion §5 / statute §6.4)
|
||||
|
||||
user-engine is PEP-shaped. Four obligations:
|
||||
|
||||
1. **No side effect without a decision record, or a recorded stance.**
|
||||
Mutations go through `_authorize` then `_record_mutation` inside
|
||||
`store.transaction()`. On flex-auth transport/parse failure,
|
||||
`FlexAuthHTTPAdapter` returns `DENY` with reason `"authorization
|
||||
service unavailable"` and a **locally minted** `decision_id`
|
||||
(`AuthorizationDecision.decision_id` default factory). `_authorize`
|
||||
then writes that id onto the deny audit record. That is a fake
|
||||
decision id, not a recorded stance application. Statute v0.7
|
||||
obligation 1 is explicit: where the engine is unreachable, record
|
||||
the application of the stance *in place of* the decision.
|
||||
`decision_id` must be absent unless a decision was rendered.
|
||||
|
||||
2. **Do not replay a verdict outside its binding and lifetime.** No
|
||||
verdict cache exists in the flex-auth adapter. Good. Negative
|
||||
caching is not used. Keep it that way unless a cache is declared
|
||||
with lifetime. The mechanical replay test (canonical request digest
|
||||
+ lifetime) is not implemented because we do not replay; still need
|
||||
a lifetime on the decision we *hold for the mutation*.
|
||||
|
||||
3. **Publish the unreachable-engine stance map.** Shipped behaviour is
|
||||
fail-closed for every call — no per-zone map, no published file, no
|
||||
test that file equals code. `runtime.py` comment says "Production
|
||||
authorization and delivery are fail-closed HTTP boundaries." That is
|
||||
a comment, which statute §6.4 forbids as the form of a stance.
|
||||
Reference shape: `ops-warden/pep-stance.yaml`. user-engine's map can
|
||||
be simpler (one protected-system, fail-closed total, including
|
||||
unknown) but it must be total, published, and tested.
|
||||
|
||||
4. **Stay reconstructable**, bounded by evidence (below). Deny audits
|
||||
are written outside the mutation transaction, which is correct
|
||||
(there is no mutation). They currently look like engine decisions.
|
||||
|
||||
### 4.5 Evidence (companion §6 / statute §9.6)
|
||||
|
||||
| Kind | What we have | Classification |
|
||||
| --- | --- | --- |
|
||||
| Successful user-domain mutation | `append_audit` + `append_outbox` inside the same `store.transaction()` as the save | Accidental omission of the *local* record is prevented. Drain to `audit-core` is after commit (local outbox pattern). |
|
||||
| Authorization denial | `append_audit` in `_authorize`, not transactional with a mutation | Load-bearing if any control treats absence of a deny as "it was allowed". Today nothing else branches on that record — attributive in practice, load-bearing in intent (denials are the class the statute names). |
|
||||
| Membership removal / account disable | Mutation path with outbox | Load-bearing for access-review and for PIP consumers who cache facts. |
|
||||
|
||||
What we may not claim, and currently do not claim in code:
|
||||
|
||||
- the audit record proves it happened;
|
||||
- there is no record, so it did not happen.
|
||||
|
||||
Docs (`docs/evidence-gap-examples.md`) talk about missing *external*
|
||||
review references, not about this bound. Completeness of the local trail
|
||||
is easy to over-claim in portal copy and operability docs. Necessity:
|
||||
classify events, declare attributive vs load-bearing, declare a cadence
|
||||
or heartbeat for denials and revocations (rate monitoring will not work
|
||||
at this volume), and never describe the trail as complete.
|
||||
|
||||
No production observation exists to cite (companion §10). This review
|
||||
does not.
|
||||
|
||||
### 4.6 Agents (companion §7 / statute §3.4)
|
||||
|
||||
The service is an Engine. Agents *working the repository* are Staff
|
||||
principals. Credential routing is already inlined in `AGENTS.md` via
|
||||
`warden route`. No standing user-engine credential is vended to agents.
|
||||
No change to runtime is required; INTENT now states the four agent
|
||||
rules so a future convenience (a long-lived portal token in an agent
|
||||
session, treating tool availability as permission) fails the
|
||||
declaration.
|
||||
|
||||
### 4.7 Conformance state (companion §8 / statute §11)
|
||||
|
||||
| Question | State |
|
||||
| --- | --- |
|
||||
| Tooling contact | **Conforming** — none to catalogued Tooling, once listed |
|
||||
| Capability we refuse to take locally (secrets-engine API, actuation, observation) | **Blocked-clean** — not worse than conforming |
|
||||
| PEP stance unpublished; fake decision ids | **Undeclared violation** of §6.4 until the map and recording ship |
|
||||
| Layer declaration | **In progress** — own-voice frontmatter done; machine-readable file and checker not done |
|
||||
|
||||
Blocked-clean on actuation and observation is the correct posture.
|
||||
Do not open a kings-guard or OpenBao client to look more complete.
|
||||
|
||||
### 4.8 Railiance workloads (companion §9)
|
||||
|
||||
`rapp-user-engine` is the managed package. Decisions come from
|
||||
flex-auth; credentials from the platform after deploy-time injection;
|
||||
evidence toward `audit-core` via the outbox. Axis-to-layer mapping is
|
||||
unsettled (statute §20.3); this review does not invent one.
|
||||
|
||||
### 4.9 Estate zeros (companion §10)
|
||||
|
||||
Do not cite "observed in operation." Do not plan automatic containment,
|
||||
step-up, or isolation as user-engine work.
|
||||
|
||||
---
|
||||
|
||||
## 5. Necessities for the current implementation
|
||||
|
||||
Ranked by whether the accepted standard is already violated in shipped
|
||||
behaviour, versus missing declaration machinery.
|
||||
|
||||
### Must change (shipped behaviour vs v0.7)
|
||||
|
||||
1. **Stop minting a local `decision_id` on engine-unavailable DENY.**
|
||||
Record stance application (zone or equivalent scope, failure mode,
|
||||
outcome). `decision_id` present only when flex-auth rendered one.
|
||||
2. **Publish `pep-stance.yaml`** (or equivalent) named from the layer
|
||||
declaration. Total, no implicit default. Test: published map equals
|
||||
`FlexAuthHTTPAdapter` behaviour. Ask gate-house to add the row to
|
||||
§13.1.
|
||||
3. **Give `AuthorizationDecision` a lifetime** and refuse to treat an
|
||||
allow with no end as a standing grant. Even without a verdict cache,
|
||||
the PEP must state one deadline.
|
||||
|
||||
### Must add (declaration and checkability)
|
||||
|
||||
4. **`layer.yaml`** plus a conformance script/test adapted from
|
||||
kings-guard: Engine/PIP, empty `tooling_contacts`, listed
|
||||
non-Tooling clients (Postgres own-store, State Hub, env secrets,
|
||||
flex-auth Engine API, key-cape OIDC as claim input).
|
||||
5. **Confine `LocalAuthorizationCheckPort`** to tests and explicitly
|
||||
standalone fixtures. Production `create_application()` already uses
|
||||
flex-auth; make construction of a default-allow adapter in the
|
||||
runtime path fail.
|
||||
|
||||
### Should add (evidence and PIP contract)
|
||||
|
||||
6. **Classify local audit/outbox events** as load-bearing or
|
||||
attributive. Declare a heartbeat or reconciliation for denials and
|
||||
membership/account revocations. Fix docs language so the trail is
|
||||
never "complete."
|
||||
7. **Prove hats / `AccessControlFact` are claims.** A test that
|
||||
selecting a hat or exporting facts never returns an allow/deny, and
|
||||
a consumer contract sentence in the hats doc and the boundary-facing
|
||||
docs: compiling those facts into a local decision is §6.1.
|
||||
|
||||
### Do not do
|
||||
|
||||
- Do not add an OpenBao or key-cape admin client.
|
||||
- Do not cache flex-auth allows.
|
||||
- Do not observe production or build containment.
|
||||
- Do not treat `USER-IN-0001` as closed by the old gate-house note;
|
||||
it closes when this repository's own files declare, which they now
|
||||
do for INTENT, with implementation follow-through on `USER-WP-0024`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Mapping to work
|
||||
|
||||
| Necessity | Workplan task |
|
||||
| --- | --- |
|
||||
| Own-voice INTENT + SCOPE + this review | `USER-WP-0024-T01` (done this session) |
|
||||
| `layer.yaml` + conformance check | `USER-WP-0024-T02` |
|
||||
| PEP stance map, stance recording, lifetime, local-port confinement | `USER-WP-0024-T03` |
|
||||
| Evidence classification and cadence | `USER-WP-0024-T04` |
|
||||
| Access-control facts as claims | `USER-WP-0024-T05` |
|
||||
| Intake close and §13.1 registration request | `USER-WP-0024-T06` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Adoption note for gate-house
|
||||
|
||||
user-engine answers `USER-IN-0001`: **Engine, role PIP**, in our own
|
||||
voice, in `INTENT.md`. We do not contest the proposed layer. We raise
|
||||
that we are PEP-shaped for our own mutations and are absent from
|
||||
statute §13.1. Findings against the accepted text remain welcome; this
|
||||
review is one.
|
||||
|
|
@ -7,7 +7,7 @@ id: USER-IN-0001
|
|||
kind: intake
|
||||
title: 'Declaration requested: state this repository''s layer in INTENT.md (security
|
||||
layer model §11)'
|
||||
status: open
|
||||
status: answered
|
||||
origin: cross-repo
|
||||
origin_ref: net-kingdom security-layer-model_v0.4 §11
|
||||
priority: low
|
||||
|
|
@ -32,5 +32,12 @@ description: 'A conformance sweep on 2026-08-28 found this repository has no lay
|
|||
for what this repository actually does, that is more useful to us than a label added
|
||||
to close a checkbox. Standard: net-kingdom/canon/standards/security-layer-model_v0.4.md.'
|
||||
created: '2026-08-28T21:02:12.760565Z'
|
||||
updated: '2026-08-28T21:02:12.760565Z'
|
||||
updated: '2026-08-29'
|
||||
answered: '2026-08-29'
|
||||
answer: >-
|
||||
Own-voice declaration in INTENT.md: layer Engine, role PIP. Subject
|
||||
context is a claim, never a decision. Protected mutations are PEP-shaped
|
||||
without changing layer. Not contested. Runtime follow-through is
|
||||
USER-WP-0024. Assessment:
|
||||
history/2026-08-29-security-layer-scope-intent-assessment.md.
|
||||
```
|
||||
|
|
|
|||
152
workplans/USER-WP-0024-security-layer-conformance.md
Normal file
152
workplans/USER-WP-0024-security-layer-conformance.md
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
---
|
||||
id: USER-WP-0024
|
||||
type: workplan
|
||||
title: "Security layer model conformance for Engine/PIP"
|
||||
domain: communication
|
||||
repo: user-engine
|
||||
status: active
|
||||
owner: grok
|
||||
topic_slug: netkingdom
|
||||
created: "2026-08-29"
|
||||
updated: "2026-08-29"
|
||||
depends_on:
|
||||
- USER-WP-0023
|
||||
---
|
||||
|
||||
# USER-WP-0024 — security layer model conformance
|
||||
|
||||
Adopt the accepted NetKingdom Security Layer Model
|
||||
(`net-kingdom/canon/standards/security-layer-model_v0.7.md`, companion
|
||||
`net-kingdom/SECURITY-COMPANION.md`) as this repository's own declaration
|
||||
and close the implementation gaps that leave a PEP-shaped Engine short of
|
||||
the standard.
|
||||
|
||||
Assessment:
|
||||
`history/2026-08-29-security-layer-scope-intent-assessment.md`.
|
||||
|
||||
Working references: `ops-warden/layer.yaml` and
|
||||
`kings-guard/layer.yaml` (no Tooling contacts). Credential and lane
|
||||
questions go to `ops-warden`, not this workplan.
|
||||
|
||||
## T01 — Declare Engine/PIP in own voice
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
Replace the gate-house review note in `INTENT.md` with this repository's
|
||||
own declaration: frontmatter `layer: Engine`, `role: PIP`, plus prose that
|
||||
subject context is a claim, never a decision, and that protected
|
||||
mutations are PEP-shaped without changing layer. Restate `SCOPE.md` from
|
||||
that INTENT. Record the scope-vs-intent-vs-implementation assessment
|
||||
under `history/`.
|
||||
|
||||
Done 2026-08-29. Closes the declaration half of `USER-IN-0001`. Does not
|
||||
by itself make the runtime conforming.
|
||||
|
||||
## T02 — Machine-readable layer declaration and check
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Add `layer.yaml` (or equivalent) naming Engine/PIP, empty catalogued
|
||||
Tooling contacts, non-Tooling / own-store clients (PostgreSQL modeled
|
||||
concept, State Hub, env-injected secrets, flex-auth Engine API, OIDC
|
||||
claim input), and the path of the PEP stance map. Adapt
|
||||
`kings-guard/scripts/check_layer_conformance.py` and a unit test so an
|
||||
undeclared OpenBao, Vault, LDAP, or cluster client fails the commit that
|
||||
introduces it.
|
||||
|
||||
Do not add a Tooling client to have something to declare.
|
||||
|
||||
**Done when:** `layer.yaml` is the machine-readable declaration, the
|
||||
checker exits 0 on the current tree, and a test covers the empty
|
||||
Tooling-contact claim.
|
||||
|
||||
## T03 — PEP obligations on the production path
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T03
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Ship the four §6.4 obligations for this PEP-shaped Engine:
|
||||
|
||||
1. Publish `pep-stance.yaml` (total, no implicit default). Production
|
||||
remains fail-closed, including unknown. A test asserts the file equals
|
||||
`FlexAuthHTTPAdapter` behaviour.
|
||||
2. On engine-unavailable DENY, record stance application (scope, failure
|
||||
mode, outcome). `decision_id` is present only when flex-auth rendered
|
||||
a decision. Stop minting a local id via `AuthorizationDecision`'s
|
||||
default factory on that path.
|
||||
3. Give `AuthorizationDecision` an explicit lifetime (TTL or
|
||||
session/obligation binding). Do not add a verdict cache.
|
||||
4. Confine `LocalAuthorizationCheckPort` to tests and standalone
|
||||
fixtures. Production `create_application()` must be unable to
|
||||
construct a default-allow adapter.
|
||||
|
||||
**Done when:** the published map matches shipped fail-closed behaviour,
|
||||
unavailable DENY audits carry no engine decision id, allows carry a
|
||||
lifetime, and the local port cannot enter the production runtime
|
||||
assembly.
|
||||
|
||||
## T04 — Evidence bound and cadence
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T04
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Classify local audit and outbox events as load-bearing or attributive.
|
||||
Keep mutation+audit+outbox atomic in the store transaction (already
|
||||
true). For denials and membership/account revocations — low-volume
|
||||
load-bearing classes — declare a heartbeat or reconciliation, not a
|
||||
rate. Update `docs/evidence-gap-examples.md` and operability copy so the
|
||||
trail is never described as complete, and so absence of a record is not
|
||||
read as non-occurrence.
|
||||
|
||||
**Done when:** the classification is in-repo, the heartbeat or
|
||||
reconciliation form is named, and docs use the sound evidence sentences.
|
||||
|
||||
## T05 — Access-control facts remain claims
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T05
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Prove under statute §6.1 that hats, access profiles, and
|
||||
`AccessControlFact` exports cannot be mistaken for an authorization
|
||||
decision. Add a test that selection and export never return allow/deny.
|
||||
Document the consumer contract: compiling those facts into a local
|
||||
decision is an early decision and is forbidden.
|
||||
|
||||
**Done when:** a test and the hats/boundary docs state the claim
|
||||
contract, and no user-engine API on that path exposes an effect.
|
||||
|
||||
## T06 — Close the intake and request the stance-map row
|
||||
|
||||
```task
|
||||
id: USER-WP-0024-T06
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Mark `USER-IN-0001` answered: Engine/PIP, not contested. Message
|
||||
`gate-house` with the declaration path, the PEP-shaped finding for
|
||||
statute §13.1 (user-engine is a third PEP-shaped consumer; the register
|
||||
currently has one published row), and a pointer at this workplan for the
|
||||
runtime follow-through.
|
||||
|
||||
Done 2026-08-29. Intake marked answered in `intakes/intakes.md`. Message
|
||||
`c014d12a-fe7a-4a90-ba73-03a5ac3e7f73` to `gate-house` carries the
|
||||
declaration, the non-contest, and the §13.1 request (row to be added
|
||||
when `pep-stance.yaml` ships in T03).
|
||||
Loading…
Add table
Add a link
Reference in a new issue