Add user and group QQQ application-role access editing, bounded catalogs,
webhook inbox and SQL mirrors, refreshed session permissions, and deferred
invitation assignments. Include the isolated local review host, browser
acceptance scripts, documentation and the token-widget column mapping fix.
User approved this RC checkpoint. Full 1.0 gates remain documented, including
the schema-drift matcher and PostgreSQL integration errors from the full gate.
Companion UI: QRun-IO/qqq-frontend-next#205.
Co-Authored-By: GPT-6 <noreply@openai.com>
AuthentikMaintenance.applyPolicy(backend, groupName, policyJson,
operatorName, reason) lets reviewed host code (a run-once job) set a
group's policy as a named maintenance operator (run-once:/maintenance:),
never as a system session. It runs the same Save Policy plan and
execute: audit row before the Authentik call, custom event, guardrails
(protected and superuser groups, scope, readOnly, POLICIES), stale check,
optional two-person approval. An equivalent policy is a NO_CHANGE no-op.
Plain Java API only; nothing is exposed over HTTP.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner request (2026-10-14): a "*" access policy for full access. The
statement {"Effect":"Allow","Action":["*"],"Resource":["*"]} grants
every permission the instance defines, expanded when permissions are
computed (sign-in, resolver, access comparison, member preview), so new
tables, processes, apps, reports, widgets and features are covered with
no edit. Resource "*" with any other action rejects the document. The
canonical form is the single statement; saving needs the operator to
hold the full set. Editor payload: fullAccess.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor widget now lists the group's members (direct and through
descendant groups, active and in scope, capped at 200) with each
person's sign-in permissions WITHOUT this group's policy
(basePermissions), plus mapperEnabled. The Next widget computes the
live effective permissions for a chosen member and what the edit adds
or removes. EffectivePermissionResolver gains an exclude-one-policy
resolution; loading requires authentik.policies.manage.
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 (9 tests) against the production token blueprint
(verbatim copy of cluster-gitops kof22-qqq-tokens.yaml): caller-owned
create, PATCH defaults, expiry cap (brand, groups, user), token
exchange as the user via the broker, the deny policy for protected
users, the qqq_token claim (profile only), service_account + set_key +
PATCH, the detective alarm, and the qbit lifecycle with the one-time
key absent from audit rows and events.
- Findings now in DESIGN.md: service_account and set_key need add_token
(safe: a non-superuser create is always the caller's); set_key events
use the model reference shape.
- Service-account lifetime cap is a user attribute
(serviceAccountTokenLifetime, default days=365), not a group.
- Test fixtures carry the production role; SuperuserFloorIT accepts the
400 from /recovery/ with reset_user_password (the qbit never calls it).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the core baseline from 4.1.0-RC.2 to the released 4.1.0-RC.5. No
source changes were needed. Comments now reflect core's opt-in permission
enforcement in 4.1. The synthetic feature-permission catalog in tests is
tagged STAND-IN(core=QRun-IO/qqq#1136, removeBy=4.1.0-RC.6), because
TableFeaturePermissionsMetaData is on develop but not in RC.5.
Refs #20 (architecture review QRun-IO/qqq#1150, finding F19).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AuthentikGroupPermissionMapper implements customizeAutomatedSessionForUser.
Server-minted sessions (scheduled saved reports, SSH-key users of
qbit-file-gateway) carry no token, so they got no Authentik permissions.
The email idReference must match exactly one active Authentik user; that
user's direct groups and ancestors go through the same resolver, static
fallbacks and cut-over guard as sign-in. Anything else, or an unreadable
API, grants only the static fallbacks. customizeSession is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner decisions (2026-10-13) 23-30: tokens managed in the app and stored
in Authentik, shown once, self-service through Preferences, on by default
with an opt-out, guardrails (a)-(f), optional per-token scopes enforced
through core QCredentialScope (qqq#1153), reminders, last used, admin
views and bulk revoke.
Decision 30 records the owner-approved mechanism revision: Authentik
2026.8.3 always creates a token for the caller unless it is a superuser,
so people's tokens are created as that person through RFC 8693 token
exchange (token broker with a deny policy), service accounts through
service_account, set_key and PATCH. The qbit role gains change_token and
set_token_key and never holds add_token or view_token_key.
Adds docs/ACCESS-TOKENS.md ("Using access tokens").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The catalog lists each table's feature permissions, read generically from
PermissionsHelper.getAllAvailablePermissions (core
TableFeaturePermissionsMetaData), as a features array per table resource.
Policies grant them by name; the * wildcard still means the five
standard actions only, so existing policies grant nothing new.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AuthentikHostPermissionSource SPI (today's access) and config
mapperEnabled, cutoverGuardGroups, mapperOverride, staticGroupPermissions.
- Enforcement status OFF/ACTIVE/OVERRIDDEN/BLOCKED: banner widget on group
and policy records and the Edit Policy step ("Policies are saved but NOT
enforced at sign-in on this instance (mapper off)"), and a row in the home's
Connection card.
- Compare Access widget (authentik.admin, read only): per active person,
today vs the mapper, added/removed/unchanged, guard result.
- Cut-over guard: while a guarded-group member would lose a permission (no
override), the mapper grants today's access plus the static fallback and
bootstrap subjects instead of the policies.
- Generate Policy From Current Access group action; operator's access today
counts for the subset rule.
- DESIGN.md 12.8 with the one-switch rollback.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DESIGN.md revision 5: owner decisions of 2026-10-13 (17-22), new section 12
(policy model stored on Authentik groups, fail-closed parsing, canonical
generator with round-trip check, claim mapping, the policy editor, delete
user/group behind the DELETE feature, authentik.policies.manage), plus
docs/POLICY-FORMAT.md and the scope-mapping blueprint example.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Users can change their own email in Authentik and emails are not unique, so
bootstrapOperators (emails) let a user become an identity operator by setting
their email to the owner's. Replaced by bootstrapOperatorSubjects: token sub
(email-looking subs ignored) or, with a verified email, the single active user
with that email whose pk or uuid is configured. Emails in config fail validation.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Permissions follow the owner's full-name rule (2026-10-12; spec #1065
amended in 8ee607610): identity.users.read -> authentik.users.read, etc.,
same suffixes; the wildcard is authentik.*.
- IdentityPermission names and WILDCARD renamed; @Deprecated
LEGACY_PREFIX, LEGACY_WILDCARD and getLegacyShortName() keep the old
names for upgrade scripts. Legacy names are never granted: the resolver
reports them as unknown and the drift report warns on them.
- UPGRADE.md: rename table, update qqq.io/permissions group attributes
(UI or blueprint) before deploying, sample SQL for host-stored grants,
sign users out afterwards.
- Code comments, drift messages, test fixtures, the test bootstrap
blueprint, README, CHANGELOG and docs/DESIGN.md use authentik.*.
The identity-admins group and the "Identity" app label are unchanged.
- Tests: IdentityPermissionTest (names, session form, legacy names not
resolved), resolver test that legacy grants are unknown and grant
nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Table names are now lowercase snake_case prefixed with the qbit name:
authentik_user, authentik_group, authentik_group_member,
authentik_session, authentik_event (were authentikUser, ...).
- AuthentikQBitConfig.applyTablePrefix(name) = snake(prefix) + "_" +
snake(name), plus a toSnakeCase helper. applyPrefix keeps the camelCase
join for apps, widgets, the backend and processes (authentikAdmin,
authentikApi), as spec #1065 says.
- @Deprecated AuthentikTables.LEGACY_*_TABLE_NAME constants hold the old
names for upgrade scripts.
- UPGRADE.md covers stored references (permissions, saved views, audit
table names, links). API-backed tables, so no DDL.
- README, CHANGELOG and docs/DESIGN.md use the new names.
- Tests: snake helper, prefix composition (default, empty, custom
camelCase prefix), producer and contract tests on the new names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Set up from qbit-template-extension with the build used by
qbit-sql-workbench and qbit-quick-search: qbit-build-parent 2.0.0 with the
qqq 4.1.0-RC.2 BOM profile, Maven wrapper, Testcontainers ITs under
failsafe, JaCoCo gate, and the qqq-orb 0.6.8 CircleCI workflows (develop
snapshots, release/* RCs, v* releases). docs/DESIGN.md is the approved spec
(QRun-IO/qqq#1065). README, CLAUDE.md and AGENTS.md describe the layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>