User-engine side of EMAIL-WP-0008: USER_ENGINE_MAIL_CLIENT_BINDINGS maps
tenant globs to a single client_id carried on invitation mail envelopes
only. Unmatched or conflicting tenants fail as mail_binding_denied before
either lane is contacted, and the outbox now records that reason instead
of collapsing it to delivery_unavailable. Unset keeps legacy envelopes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 445231@bnt-lap001
Assistant-Session: 024a807e-0cc5-4f2c-bc8a-b83322d1395d
Exposes POST /api/v1/platform/account-authority/lookup over the existing
lookup_account_authority service method, gated by a dedicated Hub workload
bearer distinct from end-user OIDC claims and the trusted proxy secret. The
route is absent unless USER_ENGINE_HUB_AUTHORITY_TOKEN is configured.
T02 (root-grant custody/mapping) and the remainder of T03 (real workload
credential admission) depend on decisions outside this repo, per
credential-routing.md and NetKingdom's root-custody canon. Requested via
State Hub messages to net-kingdom and state-hub; workplan set to blocked.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 227621@bnt-lap001
Assistant-Session: ffcc35e9-8ffa-4881-a473-02ca94d6b366
The account site said "Not signed in" while Authelia still had a session, and Sign in reused that identity. Ask Authelia who the session cookie is, show that name, and send a fresh sign-in only when a different identity is requested.
Assistant: grok
Assistant-Session: 01a0d25d-d358-7e13-b84a-d007fbb7e34f
Say "Signed in as" the identity, and describe a one-time code as a
higher security level of the NetKingdom sign-in rather than another
sign-in. The account site keeps its own session.
Assistant: grok
Assistant-Session: 01a0d25d-d358-7e13-b84a-d007fbb7e34f
USER-WP-0036 keeps the token tenant off the membership list and leaves workload decisions unchecked until the catalogue reports them.
Assistant: grok
Assistant-Session: 01a0d25d-d358-7e13-b84a-d007fbb7e34f
From the 2026-09-23 operator run: recipients try the email address, and the
admin user entry gave no sign-in address to pass on.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 58902@bnt-lap001
Assistant-Session: 7ac7f865-2dc5-4aa7-8eb7-27a342109c2f
tenant-engine has made grouping mutable through its own reclassification
route, so a tenant created as tenant:small:acme can report grouping "large".
The identifier's grouping segment is now historical and must not be parsed.
TenantRecord dropped the field entirely, so the portal read discarded the one
safe source of a tenant's classification and left an operator with nothing but
the identifier to infer from — exactly the mistake the change creates. The
record and adapter now carry grouping, the operator screen shows it with a
note that the identifier segment is not the grouping, and the OpenAPI schema
documents where to read it.
Also corrects the UpdateTenant description, which still claimed grouping was
immutable. It is mutable, but never as metadata, because it resolves a
tenant's spend ceiling.
No reclassification control is offered here: that route is not deployed yet
and, per tenant-engine, wants its own permission rather than riding on rename.
Full suite: 149 tests, 3 provider-gated skips.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TEN-WP-0005 landed the authoritative metadata update and reversible
retirement contract, so USER-WP-0021-T01's deferred tenant operations are
now implementable without user-engine inventing lifecycle semantics.
TenantManagementPort gains read, update, retire, and reactivate. The HTTP
adapter echoes the record version as an If-Match ETag (never `*`), sends an
Idempotency-Key plus actor/reason/correlation_id, and surfaces
Idempotent-Replay. Authority failures map to redacted domain errors carrying
only the contract's stable error_code; its detail text never crosses the
boundary.
Platform operators get the matching API routes and a CSRF-protected browser
screen that reads the record before mutating it and hides the metadata form
for a retired tenant. Portal OpenAPI moves to 0.3.0 with TenantRecord,
UpdateTenant, and TenantLifecycleChange.
Full suite: 145 tests, 3 external-provider skips.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>