23 Commits
Author SHA1 Message Date
james.maesandGPT-6 2e356b8117 feat(authentik): checkpoint application access and identity synchronization RC
QRun-IO/ci-policy: ci / fork-guard (pull_request) Skipped
QRun-IO/ci-policy: native / fork-deny (pull_request) Skipped
QRun-IO/ci-policy: native / dotnet-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / Scoped workflow [workflow f1d46718955078331817c6206b822a94bc7d769f] (pull_request) Successful in 9s
QRun-IO/ci-policy: ci / head-profile (pull_request) Skipped
QRun-IO/ci-policy: native / native-result (pull_request) Successful in 9s
QRun-IO/ci-policy: ci / repository-policy (pull_request) Skipped
QRun-IO/ci-policy: ci / application-template-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / gradle-1 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (pull_request) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (pull_request) Skipped
QRun-IO/ci-policy: ci / node-8 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-9 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-10 (pull_request) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (pull_request) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-13 (pull_request) Skipped
QRun-IO/ci-policy: ci / source-config-14 (pull_request) Skipped
QRun-IO/ci-policy: ci / android-0 (pull_request) Skipped
QRun-IO/ci-policy: ci / original-business (pull_request) Skipped
QRun-IO/ci-policy: ci / original-mcp (pull_request) Skipped
QRun-IO/ci-policy: ci / original-voyage (pull_request) Skipped
QRun-IO/ci-policy: ci / original-cli (pull_request) Skipped
QRun-IO/ci-policy: ci / not-enrolled (pull_request) Skipped
QRun-IO/ci-policy: ci / shared-pipeline (pull_request) Skipped
Shared Java Maven CI with Docker / secrets (push) Successful in 38s
QRun-IO/ci-policy: Shared Java Maven CI with Docker / secrets (pull_request) Successful in 38s
qbit release candidate / cut-rc (pull_request) Failing after 18s
Release candidate / release-rc (pull_request) Failing after 18s
qbit release candidate / tag-and-release (pull_request) Skipped
QRun-IO/ci-policy: Shared Java Maven CI with Docker / verify (pull_request) Failing after 15m39s
QRun-IO/ci-policy: Shared Java Maven CI with Docker / gate (pull_request) Failing after 24s
QRun-IO/ci-policy: ci / java-docker-3 (pull_request) Failing after 1h14m34s
QRun-IO/ci-policy: ci / ci-result (pull_request) Failing after 10s
Shared Java Maven CI with Docker / verify (push) Failing after 17m19s
Shared Java Maven CI with Docker / gate (push) Failing after 24s
qrun-release / release (push) Failing after 1h16m30s
qrun-release / postpublish (push) Skipped
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>
2026-11-05 05:29:54 -06:00
james.maesandClaude Opus 5.5 b196109d84 feat(admin): maintenance API to apply a policy through the audited Save Policy path
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>
2026-10-14 15:17:28 -05:00
james.maesandClaude Opus 5.5 4d2bd07e4b feat(policy): full-access statement (Resource "*" + Action "*")
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>
2026-10-14 15:09:34 -05:00
james.maesandClaude Opus 5.5 612307bde8 feat(policy): member preview payload for the policy editor
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>
2026-10-14 12:13:13 -05:00
james.maesandClaude Opus 5.5 3722380db0 feat(tokens): owner decision A (add_token); alarm on service-account creation; core notify SPI
- 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>
2026-10-14 07:57:19 -05:00
james.maes eb74cd12db Merge remote-tracking branch 'origin/feature/token-management' into feature/token-scopes 2026-10-14 07:21:06 -05:00
james.maes 9dfef79929 Merge remote-tracking branch 'origin/develop' into feature/token-management
# Conflicts:
#	CHANGELOG.md
2026-10-14 07:20:40 -05:00
james.maesandClaude Opus 5.5 6c56a24960 docs(spec): no client secret for the PAT exchange; async one-time hand-off
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:28:57 -05:00
james.maesandClaude Opus 5.5 26a449c9e6 test(tokens): contract tests on Authentik 2026.8.3 and service-account lifetime on the user
- 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>
2026-10-13 21:59:00 -05:00
james.maes 38d9776f25 Merge remote-tracking branch 'origin/develop' into feature/arch-rc5
# Conflicts:
#	CHANGELOG.md
2026-10-13 20:18:53 -05:00
james.maes 9eece9cde5 Merge pull request #21 from QRun-IO/feature/token-spec
docs(spec): access tokens as QQQ's personal access tokens (revision 6)
2026-10-13 20:01:45 -05:00
james.maesandClaude Opus 5.5 d138c5c911 chore(deps): build on QQQ 4.1.0-RC.5
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>
2026-10-13 19:51:47 -05:00
james.maesandClaude Opus 5.5 2aaedacffd docs(spec): token lifetime cap on the brand, claim bound to profile, separate broker blueprint
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:48:42 -05:00
james.maesandClaude Opus 5.5 f151a7344a feat(permissions): Authentik permissions for automated sessions
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>
2026-10-13 19:48:33 -05:00
james.maesandClaude Opus 5.5 d9431e7e6b docs(spec): access tokens as QQQ's personal access tokens (revision 6)
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>
2026-10-13 19:42:28 -05:00
james.maesandClaude Opus 5.5 d3b740785f feat(policy): grant table feature permissions (analyze, comment, ...)
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>
2026-10-13 15:30:15 -05:00
james.maesandClaude Opus 5.5 af970d32db feat(policy): safe cut-over to policies (status, compare, guard, generate)
- 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>
2026-10-13 14:39:05 -05:00
james.maesandClaude Opus 5.5 077d9abbe8 docs(spec): policies (IAM-style statements) and full user/group CRUD
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>
2026-10-13 13:21:27 -05:00
james.maesandClaude Sonnet 5.5 645f782e42 fix(security): bootstrap operators keyed on immutable ids, never email
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>
2026-10-12 17:02:09 -05:00
james.maesandClaude Sonnet 5.5 ebd56d6ca4 feat: write contract tests, docs, status; recovery email prerequisites
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 16:54:45 -05:00
james.maesandClaude Opus 5.5 338b591a7f fix(naming): rename identity.* permissions to authentik.* (owner naming rule)
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>
2026-10-12 14:29:15 -05:00
james.maesandClaude Opus 5.5 ecad3e2e5b fix(naming): snake_case authentik_ table names (owner naming rule)
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>
2026-10-12 14:16:37 -05:00
james.maesandClaude Opus 5.5 6afe1b045a chore: scaffold qbit-authentik (build, CI, docs, design)
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>
2026-10-11 19:54:03 -05:00