flex-auth/workplans/FLEX-WP-0022-tenant-scope-coverage.md
tegwick 3f60797c0a
All checks were successful
CI Smoke / host-smoke (push) Successful in 2s
CI Smoke / container-smoke (push) Successful in 5s
Record the first returned rename handoff and re-ask the tenant-scope question.
FLEX-WP-0020-T04: reuse-surface is the first owner to return a live work-record
(REUSE-WP-0023, two tasks, both deliberately in wait). Recorded in the handoff
evidence and verified rather than taken on report — the hub record is active,
access-engine raw returns 404, flex-auth returns 303, so the rename has not
landed and their refusal to pre-rewrite the federation source URL is correct.

That refusal changed the plan rather than only their side: flipping an enabled,
publish-passing source before the rename drops a live capability from the
composed federated index, so the source rewrite is ordered after T06, and
flex-auth owes them a ping when access-engine serves the capabilities index.
Nine owners remain pending; T05 stays blocked.

FLEX-WP-0022-T01: re-asked tenant-engine what CheckRequest.tenant denotes on the
write API, stating that "none" is a complete answer. Their code copies tenant_id
onto both tenant and resource.id, but that is observation, not admission, and
encoding a rule from it would make flex-auth the author of their tenancy model.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 28468@bnt-lap001
Assistant-Session: c76569b2-6056-4dad-aea4-49cd7a018f5d
2026-09-20 23:52:31 +02:00

4.9 KiB

id type title domain repo status flavor depends_on owner topic_slug planning_priority planning_order depends_on_workplans related_workplans created updated state_hub_workstream_id
FLEX-WP-0022 workplan Tenant scoping is unstated in tenant-engine and untested in two more packages infotech flex-auth active implementation
FLEX-WP-0021
claude netkingdom P1 220
FLEX-WP-0021
FLEX-WP-0010
FLEX-WP-0014
2026-09-06 2026-09-15 804c588c-f47a-50c4-bdd7-51b24bbf9539

FLEX-WP-0022 — Tenant scoping is unstated in tenant-engine and untested in two more packages

Opened by the sweep in FLEX-DEC-2026-008, which found secrets-engine.catalog-lane.lifecycle v1 allowing a foreign tenant and then asked whether the other packages shared the defect.

What the sweep found

Package Fixture tenants Tenant rule State
secrets-engine 3 distinct added at v2 fixed, FLEX-DEC-2026-008
qonto-assistant 2 distinct wrong_tenant fine
user-engine 2 distinct cross_tenant fine
ops-warden constant wrong_tenant rule real, fixtures do not vary it
railiance-platform constant wrong_tenant same
tenant-engine constant none deployed, unscoped

Verified against tenant-engine: an allowed tenant.create re-sent under tenant: tenant:coulomb returns allow / write_api_policy_matched.

Why tenant-engine is not the same fix

secrets-engine sends its own calling identity's tenant, so a constant known_tenant is the right rule. tenant-engine is different in kind: its subjects all sit in tenant:platform while its fixtures send tenant:friendly:binky, so the request tenant names the target of the operation. A service whose purpose is creating and retiring tenants acts across them by design, and a constant would break it on its first real call.

The defect today is therefore not "the rule is missing" but "nobody can tell whether it is missing": a deliberate cross-tenant scope and an omitted rule look identical in the artifact. That is the same publishing-shape argument gate-house made for §12's derived-artifact rule.

1. Get the intended tenant relation from tenant-engine

id: FLEX-WP-0022-T01
status: progress
priority: high
state_hub_task_id: "a84dcee5-9426-5b30-8dd3-f4c076d00174"

Owner: flex-auth to ask; tenant-engine owns the answer.

  • Ask what the CheckRequest tenant denotes on the write API: the caller's tenant, the target tenant record, or the tenant a guardrail applies to.
  • Ask whether any of the nine write actions must be refused cross-tenant, and whether tenant.guardrail.read (which flex-auth itself calls) differs.

Gate: the relation is named by tenant-engine, not inferred here. This is the FLEX-WP-0021-T01 rule applied to a field rather than to an action list.

2026-09-15: asked tenant-engine to name the relation (e8ba6a53-0093-4dc0-ad70-01f6b8c8e76b). Their live FlexAuthWriteAuthorizer.authorize copies tenant_id onto both CheckRequest.tenant and resource.id. That is observation, not admission.

2026-09-20: re-asked after five days of silence, restating the three questions and saying plainly that "none" is a complete answer. The gate is unchanged: a policy rule inferred from reading their code would make flex-auth the author of their tenancy model, which is the boundary FLEX-WP-0021-T01 exists to hold. T02 stays wait rather than being guessed forward.

2. Encode the relation, or record that there is none

id: FLEX-WP-0022-T02
status: wait
priority: high
state_hub_task_id: "712ac826-845f-54bd-8446-f11258d21eb4"

Owner: flex-auth.

If a relation exists, encode it in tenant-engine.write-api.mutate as a new version — fail-open corrections are visible as version changes (FLEX-DEC-2026-008) — with a fixture per side.

If the scope is genuinely unrestricted, say so in the package: a stated "this package is deliberately cross-tenant, because the caller administers tenants" is a rule a reviewer can check. Silence is not.

Either way the fixtures must vary tenant, so the suite reports on the field.

3. Vary tenant in the two suites that hold it constant

id: FLEX-WP-0022-T03
status: done
priority: medium
state_hub_task_id: "3058f171-99d2-526b-a1bb-bd7aed87d10a"

Owner: flex-auth.

ops-warden and railiance-platform have working wrong_tenant rules exercised only by Rego tests. Add a wrong-tenant deny fixture to each so the fixture suite covers what the rule claims. No policy change and no version bump: the behaviour is already correct, only the evidence is thin.

Gate: no package's fixture suite holds tenant constant.

2026-09-15: added fixture:ops-warden-wrong-tenant-deny and fixture:credential-grant-wrong-tenant-deny plus matching check_request_deny_wrong_tenant.json files. Both suites now vary tenant. test-policy and flex-auth check return deny / wrong_tenant. No policy or version change.