tenant-engine named the relation in TEN-DEC-2026-002: `tenant` is the target
tenant record and always equals `resource.id`; the write API is cross-tenant
by design and `tenant.guardrail.read` does not differ. v2 carried no tenant
rule and a constant fixture tenant, so the deliberate scope and an omitted
rule were indistinguishable.
tenant-engine.write-api.mutate v3 (FLEX-DEC-2026-016):
- allowed requires tenant_is_target; a mismatch or absent tenant is denied
tenant_not_target (object.get, so an absent key names the right cause).
- the cross-tenant scope is stated in the package and quantified by
test_tenant_never_changes_effect over every action, three subjects and
four tenants, with guards against passing by denying everything.
- fixtures rotate tenant across four tenants; five cross-tenant allows and
two tenant_not_target denies added (42 fixtures, 33 tests, all pass).
- user-engine's tenant:platform exclusion is named as a fixed-record rule,
not a subject/tenant relation, and tested separately.
Closes FLEX-WP-0022 (T01, T02 done). Also records TEN-IN-0004 and
SECRETS-IN-0002 on FLEX-WP-0020 and acknowledges the GH-DEC-2026-017
replies on FLEX-WP-0030-T04.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703