feat(security): DashboardTags on API-key constraints; sessions inherit owner tags (SEC-25 groundwork)
Adds a dashboard event-visibility tag to ApiKeyConstraints, riding in the existing constraints JSON blob so no auth-store schema migration is needed (design docs/plans/2026-07-10-dashboard-session-acl-tst15.md sections 3/3.1, open call settled per its own recommendation). The tag is visibility-only: no read, write, browse, or subscribe path consults it, and HasRead/HasWriteConstraints ignore it. GatewaySession gains an immutable, ordinal-ignore-case Tags set stamped at construction from the owning API key, forwarded by MxAccessGatewayService.OpenSession from the resolved ApiKeyIdentity — never from the wire request, so a client cannot label its own session with another tenant's tag. ISessionManager gains a tag-carrying OpenSessionAsync overload whose default implementation forwards to the tagless one, so an implementation that does not model tags opens an untagged (least visible) session. apikey create-key gains --dashboard-tags team-a,team-b (repeatable, trimmed, de-duplicated; an empty segment is rejected rather than dropped) and list-keys prints the tags column. No enforcement yet — the EventsHub ACL that consumes the tag is a later change.
This commit is contained in:
@@ -32,11 +32,17 @@ public sealed class MxAccessGatewayService(
|
||||
try
|
||||
{
|
||||
requestValidator.ValidateOpenSession(request);
|
||||
|
||||
// The session's owner id and its dashboard-visibility tags both come from the resolved
|
||||
// API key identity, never from the request: the key is the tenant principal, so a
|
||||
// client cannot label its own session with another tenant's tag (SEC-25).
|
||||
ApiKeyIdentity? owner = identityAccessor.Current;
|
||||
GatewaySession session = await sessionManager
|
||||
.OpenSessionAsync(
|
||||
SessionOpenRequest.FromContract(request),
|
||||
ResolveClientIdentity(),
|
||||
identityAccessor.Current?.KeyId,
|
||||
owner?.KeyId,
|
||||
owner?.EffectiveConstraints.DashboardTags,
|
||||
context.CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user