Review NetKingdom Tenancy Posture v0.1 and declare flex-auth posture
Publishes tenancy.yaml (I1 A0 E2 P n/a R n/a, enables A3), the review answering rapp-postgres's three asks, and FLEX-WP-0015 to close the gaps. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c84f34cf5f
commit
f2b3eeefd8
3 changed files with 485 additions and 0 deletions
153
workplans/FLEX-WP-0015-tenancy-posture-conformance.md
Normal file
153
workplans/FLEX-WP-0015-tenancy-posture-conformance.md
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
id: FLEX-WP-0015
|
||||
type: workplan
|
||||
title: "Tenancy posture declaration and inbound caller authentication"
|
||||
domain: infotech
|
||||
repo: flex-auth
|
||||
status: active
|
||||
owner: claude
|
||||
topic_slug: netkingdom
|
||||
planning_priority: P1
|
||||
planning_order: 150
|
||||
depends_on_workplans: []
|
||||
related_workplans:
|
||||
- FLEX-WP-0004
|
||||
- FLEX-WP-0011
|
||||
created: "2026-08-17"
|
||||
updated: "2026-08-17"
|
||||
---
|
||||
|
||||
# FLEX-WP-0015 - Tenancy posture declaration and inbound caller authentication
|
||||
|
||||
Answer `rapp-postgres`'s review request on **NetKingdom Tenancy Posture v0.1**
|
||||
(message `82ec43ce`), publish flex-auth's posture vector, and close the one
|
||||
real defect the review surfaced.
|
||||
|
||||
**Review output:** `docs/tenancy-posture-review.md`
|
||||
**Declaration:** `tenancy.yaml` (repo root, per framework §5.1)
|
||||
|
||||
## Why this workplan exists
|
||||
|
||||
Three of the framework's five axes describe flex-auth cleanly. Assessing
|
||||
against them turned up two things we did not know we were carrying:
|
||||
|
||||
1. **`/v1/check` authenticates no caller.** Any workload with network reach to
|
||||
the ClusterIP Service can assert any subject and any tenant and receive an
|
||||
authoritative allow. flex-auth is the estate's authorization oracle and
|
||||
trusts its callers completely. Framework level `A0`.
|
||||
2. **The tenant-engine live-roles adapter is built and unwired.** No non-test
|
||||
caller exists. The IAM Profile live re-query reads as a capability we have
|
||||
and is not one.
|
||||
|
||||
The framework itself needs six amendments, two of them corrections of
|
||||
statements it makes about flex-auth. Those are in the review document and go
|
||||
back to `rapp-postgres` as review output, not as work here.
|
||||
|
||||
**Scope discipline:** this workplan closes flex-auth's own gaps and answers
|
||||
the review. It does not build fleet-level conformance tooling, does not adopt
|
||||
AuthZEN, and does not touch production enforcement (`policy.enabled` stays off
|
||||
per FLEX-WP-0007).
|
||||
|
||||
## Tasks
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0015-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Publish posture and answer the review.** Write `tenancy.yaml` and
|
||||
`docs/tenancy-posture-review.md`; reply to `rapp-postgres` with the posture
|
||||
vector, the A4 ruling, the internal-hop ruling, and the two factual
|
||||
corrections. Done 2026-08-17.
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0015-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Close the A0 — authenticate callers of `/v1/check`.** Decide first, build
|
||||
second: this is a production-facing security boundary on a service two
|
||||
consumers already depend on, and the wrong instrument is worse than the delay.
|
||||
|
||||
Record an ADR covering at minimum:
|
||||
|
||||
- What identifies a caller — Kubernetes ServiceAccount token review, mTLS via
|
||||
the cluster's own CA, or a shared secret header. Note that the Deployment
|
||||
currently sets `automountServiceAccountToken: false`, so option one changes
|
||||
the pod spec.
|
||||
- Whether caller identity only authenticates, or also constrains: may
|
||||
`user-engine` ask questions about resources owned by `tenant-engine`? A
|
||||
caller allowlist per `system` is the natural shape and flex-auth's registry
|
||||
already keys on `system`.
|
||||
- Fail-closed vs fail-open during rollout. Given `policy.enabled` is off in
|
||||
production and both consumers are ours, a warn-only phase that logs
|
||||
unauthenticated callers before rejecting them is available and probably
|
||||
right.
|
||||
- Whether NetworkPolicy is a sufficient interim control to declare `A1`
|
||||
honestly before the real fix lands.
|
||||
|
||||
Target level `A2` — a single inbound choke point binding caller identity —
|
||||
with the §13 evidence artifact: a test that an unbound request is refused.
|
||||
|
||||
Ship through the FLEX-WP-0011 staged-promotion path, not by direct apply.
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0015-T03
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
**Wire or delete `internal/adapters/tenantengine`.** The adapter is complete
|
||||
and has no non-test caller; `decision.Engine` has no field for it. Both
|
||||
outcomes are conformant, silence is not.
|
||||
|
||||
Deciding factor is whether any live policy needs `tenant_roles` for a
|
||||
privileged, destructive, credential-vending or `aal2`-class decision — the
|
||||
IAM Profile's own trigger list. If yes, wire it into the decision path with a
|
||||
timeout and an explicit unavailable-path decision (`AttachToContext` already
|
||||
carries `tenant_roles_available: false` for exactly this), and note the new
|
||||
synchronous dependency on tenant-engine's availability. If no, delete it and
|
||||
say so in the review record rather than leaving it as latent capability.
|
||||
|
||||
Update `tenancy.yaml` `I` either way.
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0015-T04
|
||||
status: wait
|
||||
priority: low
|
||||
```
|
||||
|
||||
**AuthZEN evaluation endpoint (framework `A4`).** Deliberately deferred, not
|
||||
backlogged. `POST /access/v1/evaluation` translating onto the existing engine
|
||||
beside `/v1/check`, non-breaking.
|
||||
|
||||
**Trigger to start:** either a PEP arrives that flex-auth's operator does not
|
||||
control, or a delegated backend under FLEX-WP-0004 needs uniform addressing.
|
||||
Until one of those, A4 buys swappability nobody can use.
|
||||
|
||||
Note when starting: AuthZEN standardises the envelope, not the action
|
||||
vocabulary — it does not end action-string copying between repos. The cheaper
|
||||
fix for that is serving `registry.Actions` read-only, which is independent of
|
||||
this task and may be worth doing first.
|
||||
|
||||
```task
|
||||
id: FLEX-WP-0015-T05
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
**Guard the declaration.** Framework §12 requires verifying the declared
|
||||
posture still holds — against our own declaration, not a universal maximum.
|
||||
|
||||
Small mechanical check, `make verify-posture`, in the shape tenant-engine used
|
||||
for `verify-pin` (bash, no dependency tree). Assert what code can actually
|
||||
prove: that the `/v1/check` handler has caller authentication iff
|
||||
`tenancy.yaml` claims `A >= 2`; that `tenantengine` has a non-test caller iff
|
||||
`I >= 3`; that the production Deployment carries no `--log` and no volume iff
|
||||
`R` is `n/a`. Exit 1 on drift.
|
||||
|
||||
Designed for invisible failure per §12: posture regression returns
|
||||
correct-looking responses, exactly like the two silent pin rollbacks the
|
||||
estate has already been bitten by.
|
||||
Loading…
Add table
Add a link
Reference in a new issue