The dark theme overrides in ak-pagination assigned the disabled color
variable to the active button and the active color variable to the
overridden disabled-color custom property. As a result, the active arrow
appeared muted and the disabled arrow appeared highlighted on the first
and last pages of paginated lists.
Swap the two values so the active arrow uses the m-plain color and the
disabled custom property keeps the m-plain disabled color.
Closes#22607
Co-authored-by: nicedevil007 <nicedevil007@users.noreply.github.com>
Rename the PFColor.Grey enum member to Gray and the FONT_COLOUR_*/fontColour chart identifiers to FONT_COLOR_*/fontColor (PatternFly's pf-m-grey CSS class is left as-is), plus American spellings in comments and a UI string. Part of enabling cspell's British-spelling rule; the rule itself lands in a separate PR once all areas are clean.
Co-authored-by: Playpen Agent <279763771+playpen-agent@users.noreply.github.com>
* ## What
window.authentik.flow = {
"layout": "{{ flow.layout }}",
+ "background": "{{ flow.background }}",
+ "title": "{{ flow.title }}",
};
Amends the `flow.html` template and `GlobalAuthentik` parser to include new parameters, `background` and `title`, in the flow-specific part of the configuration written to the HTML `<head>` object, and to provide those parameters to client code.
## Why
The `layout` is start-up critical: it tells the Flow interface how the admin wants the Flow page to look, and allows the HTML and CSS to be pre-aligned to that condition. `layout` is determined on a per-Flow bases, not a per-Stage basis; Flows are derived from a tuple of `(Brand, Application?)`, where the opening policy *may* direct a user to a different flow if the user reached authentik via a redirect from a specific application, but will otherwise fall back to the default Flow for the Brand.
The `background` is a field that is required if the `Flow`’s layout is of type `frame_background`; in this case, the part of the viewport not dedicated to the FlowExecutor is reserved for an `<iframe>` that will be filled in with whatever the administrator specifies. Although this gives it the same priority as `layout` (whether it’s provided or undefined) for describing the [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome) around a challenge, it is currently not provided to the application in the start-up config; it is provided in the `challenge` and renders the IFrame as part of the initial challenge.
This patch fixes that; if `layout` is provided, `background` ought to be as well, even if it’s empty. The execution of a Challenge ought not have any influence over the look and feel of the Flow-defined appearance *around* that Challenge.
I have added `title` as well; with that, all of the current theme-and-appearance related configuration details are placed into `<head>` and can be removed from the FlowExecutor.
Server-side, `background` is currently specified: `background = FileField(blank=True, default="")` which is … interesting since we also appear to store URLs in it. I don’t see anything in the FlowSerializer that would change that from a client’s point of view.
This patch furthers the effort to separate flow execution from flow presentation.
- \[🐰\] The code has been formatted (`make web`)
* web/maint: Move sync into the components folder; adjust imports accordingly
# What
1. Moves the sync folder from elements to components: sync is very API-aware.
2. Adjusts all the imports correctly.
* ## What
window.authentik.flow = {
"layout": "{{ flow.layout }}",
+ "background": "{{ flow.background }}",
+ "title": "{{ flow.title }}",
};
Amends the `flow.html` template and `GlobalAuthentik` parser to include new parameters, `background` and `title`, in the flow-specific part of the configuration written to the HTML `<head>` object, and to provide those parameters to client code.
## Why
The `layout` is start-up critical: it tells the Flow interface how the admin wants the Flow page to look, and allows the HTML and CSS to be pre-aligned to that condition. `layout` is determined on a per-Flow bases, not a per-Stage basis; Flows are derived from a tuple of `(Brand, Application?)`, where the opening policy *may* direct a user to a different flow if the user reached authentik via a redirect from a specific application, but will otherwise fall back to the default Flow for the Brand.
The `background` is a field that is required if the `Flow`’s layout is of type `frame_background`; in this case, the part of the viewport not dedicated to the FlowExecutor is reserved for an `<iframe>` that will be filled in with whatever the administrator specifies. Although this gives it the same priority as `layout` (whether it’s provided or undefined) for describing the [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome) around a challenge, it is currently not provided to the application in the start-up config; it is provided in the `challenge` and renders the IFrame as part of the initial challenge.
This patch fixes that; if `layout` is provided, `background` ought to be as well, even if it’s empty. The execution of a Challenge ought not have any influence over the look and feel of the Flow-defined appearance *around* that Challenge.
I have added `title` as well; with that, all of the current theme-and-appearance related configuration details are placed into `<head>` and can be removed from the FlowExecutor.
Server-side, `background` is currently specified: `background = FileField(blank=True, default="")` which is … interesting since we also appear to store URLs in it. I don’t see anything in the FlowSerializer that would change that from a client’s point of view.
This patch furthers the effort to separate flow execution from flow presentation.
- \[🐰\] The code has been formatted (`make web`)
* web/maint: move special-purpose support elements closer to what they support
Moves the `./element/oauth` components to `./admin/users`. They're API-aware (so they're components, not elements) and they're not general-purpose (used only by Admin, so they should be closer to where they're used).
Not sure why `uv.lock` changed.
\# What
\# Why
\# How
\# Designs
\# Test Steps
\# Other Notes
* This should not be different.
* ## What
window.authentik.flow = {
"layout": "{{ flow.layout }}",
+ "background": "{{ flow.background }}",
+ "title": "{{ flow.title }}",
};
Amends the `flow.html` template and `GlobalAuthentik` parser to include new parameters, `background` and `title`, in the flow-specific part of the configuration written to the HTML `<head>` object, and to provide those parameters to client code.
## Why
The `layout` is start-up critical: it tells the Flow interface how the admin wants the Flow page to look, and allows the HTML and CSS to be pre-aligned to that condition. `layout` is determined on a per-Flow bases, not a per-Stage basis; Flows are derived from a tuple of `(Brand, Application?)`, where the opening policy *may* direct a user to a different flow if the user reached authentik via a redirect from a specific application, but will otherwise fall back to the default Flow for the Brand.
The `background` is a field that is required if the `Flow`’s layout is of type `frame_background`; in this case, the part of the viewport not dedicated to the FlowExecutor is reserved for an `<iframe>` that will be filled in with whatever the administrator specifies. Although this gives it the same priority as `layout` (whether it’s provided or undefined) for describing the [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome) around a challenge, it is currently not provided to the application in the start-up config; it is provided in the `challenge` and renders the IFrame as part of the initial challenge.
This patch fixes that; if `layout` is provided, `background` ought to be as well, even if it’s empty. The execution of a Challenge ought not have any influence over the look and feel of the Flow-defined appearance *around* that Challenge.
I have added `title` as well; with that, all of the current theme-and-appearance related configuration details are placed into `<head>` and can be removed from the FlowExecutor.
Server-side, `background` is currently specified: `background = FileField(blank=True, default="")` which is … interesting since we also appear to store URLs in it. I don’t see anything in the FlowSerializer that would change that from a client’s point of view.
This patch furthers the effort to separate flow execution from flow presentation.
- \[🐰\] The code has been formatted (`make web`)
* web/maint: Move notifications into the components folder; adjust imports accordingly
# What
1. Moves the notifications folder from elements to components: the API and Notifications drawers are API-aware. If we want to separate that out and do something unique, we can, but for now, let’s just get things where they should be.
2. Adjusts all the imports correctly.
3. (Minor): Mutating the array and then calling `requestUpdate()`, especially when the array is then sorted-and-reversed, doesn’t save anything over creating a new array with the new item shifted onto the head, sorted once, and then saved to the property, which triggers an update automatically.
* web/table: fetch on first render when already visible
Tables inside `<ak-modal>` rendered empty until the user clicked the
refresh button. The 2026.5 RC native-`<dialog>` migration taught
`AKModal.updated()` to force `visible = true` on its slotted child, but
`Table.firstUpdated()` was delegating to `#synchronizeRefreshSchedule()`,
which only flushes a *previously deferred* refresh. With visibility
forced on before the first update cycle, no deferred refresh was ever
queued, so the synchronizer no-op'd and nothing fetched.
Switch the first-update hook to call `fetch()` directly. `fetch()`
already handles both states correctly: if the table is visible it
issues the request immediately, and if it isn't it queues the deferred
refresh that the synchronizer flushes when visibility flips on. Beyond
the modal case this also covers any future caller that mounts a Table
already-visible.
Reproduced and verified against the user-library RAC endpoint launcher
(the surface from the beta report). Added a Playwright e2e
(`rac-launch-modal.test.ts`) that seeds a RAC provider + two endpoints
via the API, opens the launcher, and asserts the endpoint rows appear
without a manual refresh — fails on `main`, passes with this change.
A 2026.5 backport will follow as a separate PR.
Co-Authored-By: Agent (authentik-m-triage-rac-proper-shared-lilac) <279763771+playpen-agent@users.noreply.github.com>
* web/test: silence cspell on AK_TEST_BOOTSTRAP_TOKEN fallback
`changeme` in the playpen-specific default for `AK_TEST_BOOTSTRAP_TOKEN`
trips the spellcheck lint job. Add an inline `cspell:ignore` directive
so the fallback can stay (CI sets the env var so the default is only
used locally inside playpen sandboxes).
* Flesh out RAC test coverage.
* Use simple search for applications list.
* Add order.
* Ignore playwright result.
* Remove unused.
* Tidy for test.
* Fix test selectors.
* Fix overlap.
* Defer to connected callback.
* Use consistent Patternfly input outline.
* Clean up labels.
* Only trigger navigation on non-current entries.
* Ensure that selected type is retained.
---------
Co-authored-by: Agent (authentik-m-triage-rac-proper-shared-lilac) <279763771+playpen-agent@users.noreply.github.com>
* core: add .npmrc baseline to block dependency lifecycle scripts
Set ignore-scripts=true at the repo root, plus engine-strict, save-exact,
audit, and prefer-offline. This neutralizes the dominant npm supply-chain
attack vector — postinstall scripts in transitive dependencies — at the
cost of requiring an explicit rebuild for the handful of packages that
legitimately need install scripts (esbuild, chromedriver, tree-sitter,
tree-sitter-json). The next commit wires that rebuild into the Makefile.
Co-Authored-By: Playpen Agent <279763771+playpen-agent@users.noreply.github.com>
* core: route node installs through make to retire website preinstall hook
Make docs-install depend on a new root-node-install so the root deps
are guaranteed before the website install runs, removing the need for
the website/preinstall lifecycle script. Rebuild the small audited list
of trusted packages (esbuild, chromedriver, tree-sitter, tree-sitter-json)
after the web install so ignore-scripts=true remains the only path that
needs maintenance. web/README documents the new workflow.
Co-Authored-By: Playpen Agent <279763771+playpen-agent@users.noreply.github.com>
* Clean up install scripts.
* Track .npmrc in CODEOWNERS
* Fix formatter config. Reformat.
* Fix mounted references.
* Flesh out node scripts.
* Bump engines.
* Prep containers.
* Update makefile.
* Flesh out github actions.
* Clean up docs container.
* lint.
Bump.
Lint.
Bump NPM version.
* Add limits.
* collapse the composite's three setup-node calls to one cache restore
* Add SHA.
* Bump NPM range.
* Run formatter.
* Bump NPM.
* Remove extra install.
* Fix website deps.
* Use local prettier. Fix drift in CI.
* ci: build frontend in CI with node_env production
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* Install docusaurus config.
* Fix linter warning, order.
* Add linter commands.
* Add timeout.
* Remove pre install check.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Playpen Agent <279763771+playpen-agent@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
* web/bug: Fix wild regexp self-ddos recursion bug in compatibility mode.
# What
Replace CSS *not x or y* with *not x and not y* constructs. The form:
:host([expanded][position="left"]:not([inline], [static]))
… becomes …
:host([expanded][position="left"]:not([inline]):not([static]))
Minor: Removed the `export` declaration on a helper function in the Drawer story file.
# Why
The first expression triggered an obscure regex recursion bug in `polyfill.js` when converting the CSS to a format that works when the browser’s shadowDOM features are disabled. It does not handle complex CSS Level 4 Selectors very well.
The unneeded `export` was confusing Storybook and causing it to render an empty story on the Drawer’s component overview page.
* .
* Did I miss something?
* That was a stupid spelling error.
* ## What
Extend ak-drawer to comply with the full specification; port ak-drawer to use Patternfly 5; vendor the Patternfly 5 subsystems directly responsible for the Drawer into the CSS.
## Why
To meet the requirements of the Drawer, of the LightDOM project, and of the Patternfly 5 vendoring port.
## Details
The Drawer’s internal CSS is now entirely within the Lit framework; the controlling CSS is namespaced to `ak-v2-c--drawer` and placed into the global CSS. Every bit of the drawer has a `part` name, so it can be customized to your heart’s content.
Added stylelint to make sure I’m doing this correctly.
* TSC (!) had opinions.
* Re-arranged to avoid having a 'devDependencies' block.
* Nobody liked this choice.
* Extend ak-drawer to comply with the full specification; port ak-drawer to use Patternfly 5; vendor the Patternfly 5 subsystems directly responsible for the Drawer into the CSS.
This drawer is completely independent of Patternfly 4; it brings everything in-house, everything is under `ak-v2-c-drawer`, and we read our variables from `ak-v2-global` entries as part of the style folder.
The contents of the folder are slotted, so they’re part of the parent DOM and parent CSS context, and can be controlled from there without having to do any magic on the Drawer.
To comply with the standards of the HTML disclosure pattern, the drawer uses `expanded` instead of `open`; it listens for an event to trigger open/close; it emits a `toggle` event when completed. Shortcoming: to completely comply with the disclosure pattern, it should emit a `beforeToggle` to let other clients intercept the request and prevent it from happening, but we don’t do that yet.
Unlike the previous drawer, this one has `resizable`, `position`, `inline/static`, and responsive width breakpoints, all features of the Patternfly 5 React web-component. The resizable variant gives you a visible handle, and even responds to keyborad controls.
Along with the native control through CSS Custom Properties, every part of the component has a `part` declaration, so if you *really* want to customize the thing that’s now possible.
Unlike the Patternfly 5 React version, we impose **no** structure on the internals of the component; no padding, no margin, no header/main/footer segmentation. That pattern is universal, and doesn’t need to be specified for each and every component. If you need that, build it into whatever element you put into the unnamed “main” or `panel` slots.
There is a comprehensive Storybook story page for the component.
To meet the requirements of the Drawer, of the LightDOM project, and of the Patternfly 5 vendoring port.
* Prettier has opinions, as usual.
* UV lockfile update required.
* Restoring from main.
* Merge screwed up the library resolveds again.
* A hail-mary pass.
* Still trying to get this past lint.
- Use the pending lockdown target in the example blueprint warning and avoid repeating the username when email/name is not distinct.
- Hide the admin Account Lockdown action for internal service accounts.
* web/admin: fix log-viewer layout again
I thought I only recently fixed this...?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* switch closeAfterSuccessfulSubmit -> keepOpenAfterSubmit with correct attribute name and false as default
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
web/rac: ignore empty remote clipboard payloads
Some remote sessions (notably SSH) push empty or whitespace-only
clipboard updates that overwrite the user's local clipboard, leaving
subsequent paste attempts with nothing to deliver. Filter those payloads
in the StringReader.onend callback so the local clipboard is preserved.
Closes#21439
Co-authored-by: Agent (authentik-i21439-featured-elevated-kobicha) <279763771+playpen-agent@users.noreply.github.com>
* web: fix identification stage OUIA attributes
* tests/e2e: update OUIA selectors for identification stage
Match the rename of ouiaId to data-ouia-component-id in
IdentificationStage.ts so the enroll and recovery flow tests can
locate the links again.
* ## What
window.authentik.flow = {
"layout": "{{ flow.layout }}",
+ "background": "{{ flow.background }}",
+ "title": "{{ flow.title }}",
};
Amends the `flow.html` template and `GlobalAuthentik` parser to include new parameters, `background` and `title`, in the flow-specific part of the configuration written to the HTML `<head>` object, and to provide those parameters to client code.
## Why
The `layout` is start-up critical: it tells the Flow interface how the admin wants the Flow page to look, and allows the HTML and CSS to be pre-aligned to that condition. `layout` is determined on a per-Flow bases, not a per-Stage basis; Flows are derived from a tuple of `(Brand, Application?)`, where the opening policy *may* direct a user to a different flow if the user reached authentik via a redirect from a specific application, but will otherwise fall back to the default Flow for the Brand.
The `background` is a field that is required if the `Flow`’s layout is of type `frame_background`; in this case, the part of the viewport not dedicated to the FlowExecutor is reserved for an `<iframe>` that will be filled in with whatever the administrator specifies. Although this gives it the same priority as `layout` (whether it’s provided or undefined) for describing the [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome) around a challenge, it is currently not provided to the application in the start-up config; it is provided in the `challenge` and renders the IFrame as part of the initial challenge.
This patch fixes that; if `layout` is provided, `background` ought to be as well, even if it’s empty. The execution of a Challenge ought not have any influence over the look and feel of the Flow-defined appearance *around* that Challenge.
I have added `title` as well; with that, all of the current theme-and-appearance related configuration details are placed into `<head>` and can be removed from the FlowExecutor.
Server-side, `background` is currently specified: `background = FileField(blank=True, default="")` which is … interesting since we also appear to store URLs in it. I don’t see anything in the FlowSerializer that would change that from a client’s point of view.
This patch furthers the effort to separate flow execution from flow presentation.
- \[🐰\] The code has been formatted (`make web`)
* The status label was using HTML booleans incorrectly. It is impossible for a boolean to be null. The default red was alarming, so I chose a neutral grey for the 'not default' state.
* It is not enough to provide a blank cell to ensure the header is spaced correctly; if the table is empty, that will collapse to zero width. Providing the classes that go with the 'this cell may contain a toggle' provides the correct spacing as well.
* Fix inconsistent wording between menu and page; make the 'select type' radiocard and radiolist interfaces flush with the top of the form container, removing a weird jagged visual line between the menu and the content.
* Document adding 'toggle' to Table classes.
* Fix how the buttons for TablePage's empty state align; slots are still wonky when responding to content layout that we do not control ourselves.
* Do not show pagination controls when there are no pages to turn.
* Fix spacing after ak-alert in documentation show in the front-end. Without this, headers and paragraphs were edging well into the alert's drop-shadow.
* Remove separator line from radio entries; P4-ism that was visually confusing.
* Make the empty state a slot, so it can be easily overriden, and provide a default if the slot isn't filled from a lightDOM entry. Add one to the columnWidth, since columnWidth doesn't include the action column; this fixes a visual tic where the empty state did not look correctly centered.
* web: Gracefully handle missing element construction.
* web: Tailor missing element message based on debug capability. (#22048)
Show a developer-oriented hint when CanDebug is set, and an
end-user-friendly suggestion (refresh / clear cache) otherwise.
Co-authored-by: Agent (authentik-i21787-graceful-gross-chrome) <279763771+playpen-agent@users.noreply.github.com>
---------
Co-authored-by: Agent (authentik-i21787-graceful-gross-chrome) <279763771+playpen-agent@users.noreply.github.com>
* ## What
window.authentik.flow = {
"layout": "{{ flow.layout }}",
+ "background": "{{ flow.background }}",
+ "title": "{{ flow.title }}",
};
Amends the `flow.html` template and `GlobalAuthentik` parser to include new parameters, `background` and `title`, in the flow-specific part of the configuration written to the HTML `<head>` object, and to provide those parameters to client code.
## Why
The `layout` is start-up critical: it tells the Flow interface how the admin wants the Flow page to look, and allows the HTML and CSS to be pre-aligned to that condition. `layout` is determined on a per-Flow bases, not a per-Stage basis; Flows are derived from a tuple of `(Brand, Application?)`, where the opening policy *may* direct a user to a different flow if the user reached authentik via a redirect from a specific application, but will otherwise fall back to the default Flow for the Brand.
The `background` is a field that is required if the `Flow`’s layout is of type `frame_background`; in this case, the part of the viewport not dedicated to the FlowExecutor is reserved for an `<iframe>` that will be filled in with whatever the administrator specifies. Although this gives it the same priority as `layout` (whether it’s provided or undefined) for describing the [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome) around a challenge, it is currently not provided to the application in the start-up config; it is provided in the `challenge` and renders the IFrame as part of the initial challenge.
This patch fixes that; if `layout` is provided, `background` ought to be as well, even if it’s empty. The execution of a Challenge ought not have any influence over the look and feel of the Flow-defined appearance *around* that Challenge.
I have added `title` as well; with that, all of the current theme-and-appearance related configuration details are placed into `<head>` and can be removed from the FlowExecutor.
Server-side, `background` is currently specified: `background = FileField(blank=True, default="")` which is … interesting since we also appear to store URLs in it. I don’t see anything in the FlowSerializer that would change that from a client’s point of view.
This patch furthers the effort to separate flow execution from flow presentation.
- \[🐰\] The code has been formatted (`make web`)
* The status label was using HTML booleans incorrectly. It is impossible for a boolean to be null. The default red was alarming, so I chose a neutral grey for the 'not default' state.
* It is not enough to provide a blank cell to ensure the header is spaced correctly; if the table is empty, that will collapse to zero width. Providing the classes that go with the 'this cell may contain a toggle' provides the correct spacing as well.
* Fix inconsistent wording between menu and page; make the 'select type' radiocard and radiolist interfaces flush with the top of the form container, removing a weird jagged visual line between the menu and the content.
* Document adding 'toggle' to Table classes.
* enterprise/lifecycle: allow multiple rules to apply to a single object (and thus, multiple concurrent reviews)
* enterprise/lifecyle: add missing migration to allow multiple lifecycle rules per object, add tests, update documentation
* enterprise/lifecycle: add a bit of padding to individual review iterations on Review tab for better visual separation
* enterprise/lifecycle: remove validation preventing the creation of multiple lifecycle rules for one object type
* enterprise/lifecycle: change the approach to querying the list of reviews with user_is_reviewer annotation to prevent duplicate rows
* enterprise/lifecycle: add custom per-type logic to get object name for use in a notification to prevent texts like "Review is due for Group Group X"
* enterprise/lifecycle: updated wording on lifecycle rule form and preview banner padding
* enterprise/lifecycle: remove task list from lifecycle rules and switch to using per-rule schedules
* enterprise/lifecycle: add a title to the lifecycle tab
* Revert "enterprise/lifecycle: remove task list from lifecycle rules and switch to using per-rule schedules"
This reverts commit 8a060015b693f65f651a71bdb0c47092d3463af1.
* enterprise/lifecycle: remove task list from the lifecycle rule list page and attach the tasks to the schedule
* enterprise/lifecycle: add proper caption when there are no reviews for an object
* enterprise/lifecycle: attach individual apply_lifecycle_rule tasks to the schedule when launched from apply_lifecycle_rules
* enterprise/lifecycle: update generated API clients
* enterprise/lifecycle: update wording
* enterprise/lifecycle: fix ts issues after rebase
* Update website/docs/sys-mgmt/object-lifecycle-management.md
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Alexander Tereshkin <96586+atereshkin@users.noreply.github.com>
* enterprise/lifecycle: remove fmall code artifact
---------
Signed-off-by: Alexander Tereshkin <96586+atereshkin@users.noreply.github.com>
Co-authored-by: Dominic R <dominic@sdko.org>
* web: Clear remember me before navigation.
* web: fix stray > in "Not you?" link and add Playwright regression for #21571
Move the closing > of the opening <a> tag so the rendered link text no longer
carries a leading > glyph. Add a browser test that seeds the identification
stage with enable_remember_me, walks the identify -> password -> "Not you?"
path, and asserts the link text, the cleared username field, and the cleared
remember-me localStorage key.
Co-Authored-By: Agent (authentik-i21647-current-instant-chili) <279763771+playpen-agent@users.noreply.github.com>
* Flesh out remember me lifecycle. Fix edgecases where it doesn't keep up with the e2e suite.
* Fix for submit events, labels.
---------
Co-authored-by: Agent (authentik-i21647-current-instant-chili) <279763771+playpen-agent@users.noreply.github.com>