flex-auth/workplans/FLEX-WP-0008-tenant-engine-consumer-integration.md
tegwick 67b1f9161a
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 5s
Draft FLEX-WP-0008: tenant-engine consumer integration
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>
2026-07-23 22:47:10 +02:00

125 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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`.