QQQ 4.1.0-RC.6 (now the qbit's baseline) ships the notification SPI
(qqq#1125), so the reflection stand-in is gone: guard incidents use
QAlerts.raise, owner reminders QAlerts.notify.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- DESIGN.md decision 31 (owner, 2026-10-14): the qbit role holds
add_token (needed by service_account and by set_key); view_token_key
stays not granted.
- TokenContractIT pins 403 without add_token and 200/204 with it, and
that the alarm notifies identity-admins when the qbit's account creates
a service account (fixture = cluster-gitops#103 blueprint, verbatim).
- Reminders go through core QAlerts.notify (qqq#1125) by reflection,
never another qbit's classes (G1); guard alerts through core QAlerts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TokenContractIT now exchanges app passwords exactly like the generated
usage text (no client_secret); green on Authentik 2026.8.3. Also logs the
cause when a token scope cannot be verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lookup runs while a bearer session is still being built (no user), so
the guard refused the Authentik read and the scope failed closed for
every token. Read Authentik and the scope row as QSystemUserSession, then
restore the caller's context. Found by the kof22 adoption test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A host whose RDBMS backend maps camelCase to snake_case got
last_reminder7d, which does not match docs/schema.sql (found by the
kof22 adoption's changeset test).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Scopes: Create Token takes read only, apps and tables when
tokenScopesEnabled (validated against the instance and the operator's
own access). AuthentikTokenScopes reads the signed qqq_token claim in
both mappers (and AuthentikTokenScopes.apply for hosts with their own
customizer): no row = unscoped, deleted token = no permissions, any
verification failure = no permissions. STAND-IN for core
QCredentialScope (qqq#1168, RC.7): permissions are intersected; the
core scope is attached by reflection when present (empty dimension =
null = unrestricted).
- Last used from Authentik login events (method token, 90 days, cached
5 minutes); createdAt and scopeSummary from the scope row.
- Daily expiry reminders (7 days, 1 day) through the optional Alerts
producer, deduplicated on the scope row; guard-bypass alert.
- Admin widget on the app home (authentik.tokens.manage): by owner, by
age, unused for tokenUnusedDays, deactivated owners; bulk Revoke Token
on the list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>