Draft FLEX-WP-0008: tenant-engine consumer integration
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 5s

Registers tenant-engine as a flex-auth protected-system consumer in both
directions its boundary contract requires: tenant-engine's writes need
authorization (FlexAuthWriteAuthorizer in TEN-WP-0003 currently gets
deny/not_applicable for everything until a policy package exists), and
flex-auth's own decisions for other protected systems need tenant
capability roles as context input via a live-lookup adapter.

Scoped closer to FLEX-WP-0006/0007 (ops-warden's small security-lane
integration) than FLEX-WP-0003 (Markitect's CARING-benchmark integration)
-- tenant-engine's resource/action vocabulary is small.

Registered, not implemented.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-23 22:47:10 +02:00
parent 0ed11a7520
commit 67b1f9161a

View file

@ -0,0 +1,125 @@
---
id: FLEX-WP-0008
type: workplan
title: "tenant-engine Consumer Integration"
domain: infotech
repo: flex-auth
status: ready
owner: codex
topic_slug: flex-auth
planning_priority: P1
planning_order: 80
depends_on_workplans:
- FLEX-WP-0007
related_workplans:
- TEN-WP-0003
- KEY-WP-0005
created: "2026-07-23"
updated: "2026-07-23"
---
# FLEX-WP-0008: tenant-engine Consumer Integration
## Purpose
Make `tenant-engine` a registered protected-system consumer of flex-auth,
in both directions its boundary contract requires
(`net-kingdom/canon/standards/tenant-engine-boundary-contract_v0.1.md`):
1. **tenant-engine's writes need authorization.** `tenant-engine`'s
`FlexAuthWriteAuthorizer` (`TEN-WP-0003`) calls `POST /v1/check` for
every mutation (`tenant.create`, `tenant.role.grant`, `tenant.role.revoke`,
`tenant.plan.assign`). Until a policy package exists here, every check
resolves to `deny`/`not_applicable` — correct fail-closed behavior, but
it means `tenant-engine` cannot actually perform any write yet. This
workplan is what makes real `allow` decisions reachable.
2. **flex-auth's own decisions need tenant capability roles as input**, for
any protected system whose policy depends on a tenant's `PLTF`/`IAM`/
`VEN`/`CUS` roles (ADR-0014) at `aal2`-class decision time. flex-auth
must call `tenant-engine`'s live-lookup endpoint
(`GET /tenants/{id}/roles/live`) to enrich decision context, the same
role a `context` adapter plays for any other external fact source.
Closer in shape to `FLEX-WP-0006`/`FLEX-WP-0007` (ops-warden's small,
security-lane SSH-certificate integration) than `FLEX-WP-0003` (Markitect's
document-heavy, CARING-benchmark integration) — `tenant-engine`'s resource
and action vocabulary is small and doesn't need CARING descriptor mapping.
## Task: Define tenant-engine resource and action vocabulary
```task
id: FLEX-WP-0008-T01
status: todo
priority: high
```
Resource types: `tenant`, `role-grant`, `plan-assignment`. Actions:
`tenant.create`, `tenant.role.grant`, `tenant.role.revoke`,
`tenant.plan.assign` — matching `TEN-WP-0003-T02`'s action-name mapping
exactly (coordinate values, don't let the two repos invent different
strings for the same action). Model on `examples/ops-warden`'s fixture
shape (`schemas/check_request.schema.json`'s `resource{id,type,system}`,
`system: "tenant-engine"`), not Markitect's.
Done when: resource/action vocabulary documented under `docs/` following
the `markitect-resource-namespace.md` / `markitect-action-vocabulary.md`
naming pattern (`tenant-engine-resource-namespace.md`,
`tenant-engine-action-vocabulary.md`).
## Task: Author and register the tenant-engine policy package
```task
id: FLEX-WP-0008-T02
status: todo
priority: high
```
Policy: writes require an `aal2`+ assurance actor holding an appropriate
capability role for the action (e.g. `tenant.plan.assign` might require
`PLTF` or a platform-operator subject type; exact rules are a design
decision for this task, not pre-specified here — coordinate with ADR-0014's
role semantics, not invented fresh). Register in `registry/` per the
existing pattern; add fixtures (`allow`/`deny` request/response pairs)
mirroring `examples/ops-warden/check_request_allow_adm.json`.
Done when: `POST /v1/check` against a request matching `TEN-WP-0003`'s
`FlexAuthCheckClient` shape returns `allow` for an authorized actor/action
and `deny` for an unauthorized one, exercised by `main_test.go`-style
integration tests.
## Task: tenant-engine live-lookup context adapter
```task
id: FLEX-WP-0008-T03
status: todo
priority: medium
```
A context-enrichment adapter (mirrors `internal/adapters/{relationship,rule,topaz}`'s
shape) that calls `tenant-engine`'s `GET /tenants/{id}/roles/live` and
attaches the result to decision context for policies that need it — used by
*other* protected systems' policies that key off tenant capability role,
not only by tenant-engine's own policy from T02. Must fail closed: adapter
error or `tenant-engine` unavailability must not silently produce an empty
role list indistinguishable from "no roles granted" (same rule
`tenant-engine`'s own read endpoints already enforce — don't weaken it on
the consuming side).
Done when: a policy package referencing tenant capability role context
correctly denies when the adapter call fails, not just when it succeeds
with an empty result.
## Task: Closure review
```task
id: FLEX-WP-0008-T04
status: todo
priority: low
```
Confirm T01T03 done; run flex-auth's existing test suite plus the new
fixtures. Note in closure: `TEN-WP-0003`'s `FlexAuthWriteAuthorizer` should
be re-verified against a real `allow` decision once this workplan's policy
package exists (it was only tested against `deny`/`not_applicable`
responses when built, since this workplan didn't exist yet). Run `statehub
fix-consistency`.