Skip to content

web/standards: fix boolean attribute abuse #14662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 58 commits into
base: main
Choose a base branch
from

Conversation

kensternberg-authentik
Copy link
Contributor

web/maintenance: correct the usage of boolean (false) attributes

What

Just cleaning up a bad habit; we have a lot of ?attribute=${true|false} (or, more alarmingly, .attribute=${true|false}. These should just be attribute or be missing; anything else is unnecessary.

Where the attribute is true by default, no changes have been made; there are only a few of them, and they require re-working of the logic to assist with the changes. Booleans should never be true by default, and if you absolutely cannot find an alternative phrasing that makes having them be false by default a valid choice, they should be reflect: true to make their presence visible to screen readers and debuggers.

Why

Removing non-standard HTML uses from web components matches our programming standards and is an important step toward the Authentik Elements NPM package, as well as the Schema-Driven Forms update.

How

Aside from the few hand-edits which are documented in the PR, 99% of this work was realized with these two lines:

perl -pi.bak -e 's/\?(\w+)="?\$\{true\}"?/\1/' $(rg -l '\?(\w+)="?\$\{true\}"?')
perl -pi.bak -e 's/\.(removable|expanded)="?\$\{true\}"?/\1/' $(rg -l '\.(removable|expanded)="?\$\{true\}"?')

Boring excessive detail.

Because there is literally 104 changes, I’ve documented the boring ones here.

Changes that do not meet the basic criteria of “made the component comply with the standards” are commented in the PR.

There are three code blocks:

  • All the Boolean declarations that are false by default, for information purposes.
  • Every pair of old/new changes showing where the declarations were fixed (when true) or removed (when false)
  • The collection of declarations that were not changed because they are not false by default.

First: all the Boolean property declarations in the system, delta the ones that declare = true; those are documented at the bottom of this commit, and are not addressed in this PR.

components/ak-switch-input.ts:
    @property({ type: Boolean })
    checked: boolean = false;
--
components/ak-switch-input.ts:
    @property({ type: Boolean })
    required = false;
--
components/ak-file-input.ts:
    @property({ type: Boolean })
    required = false;
--
components/HorizontalLightComponent.ts:
    @property({ type: Boolean })
    required = false;
--
components/ak-multi-select.ts:
    @property({ type: Boolean })
    required = false;
--
elements/TreeView.ts:
    @property({ type: Boolean })
    open = false;
--
components/ak-status-label.ts:
    @property({ type: Boolean })
    good = false;
--
components/ak-status-label.ts:
    @property({ type: Boolean })
    compact = false;
--
elements/CodeMirror.ts:
    @property({ type: Boolean })
    readOnly = false;
--
elements/buttons/ModalButton.ts:
    @property({ type: Boolean })
    open = false;
--
elements/EmptyState.ts:
    @property({ type: Boolean })
    fullHeight = false;
--
elements/Tabs.ts:
    @property({ type: Boolean })
    vertical = false;
--
elements/ak-checkbox-group/ak-checkbox-group.ts:
    @property({ type: Boolean })
    required = false;
--
elements/Label.ts:
    @property({ type: Boolean })
    compact = false;
--
elements/forms/FormGroup.ts:
    @property({ type: Boolean, reflect: true })
    expanded = false;
--
elements/Expand.ts:
    @property({ type: Boolean })
    expanded = false;
--
elements/forms/HorizontalFormElement.ts:
    @property({ type: Boolean })
    required = false;
--
elements/forms/HorizontalFormElement.ts:
    @property({ type: Boolean })
    slugMode = false;
--
elements/forms/SearchSelect/ak-portal.ts:
    @property({ type: Boolean, reflect: true })
    open = false;
--
elements/Alert.ts:
    @property({ type: Boolean })
    inline = false;
--
elements/forms/SearchSelect/ak-search-select-view.ts:
    @property({ type: Boolean, reflect: true })
    open = false;
--
elements/forms/SearchSelect/ak-search-select-view.ts:
    @property({ type: Boolean })
    blankable = false;
--
elements/sidebar/SidebarItem.ts:
    @property({ type: Boolean })
    expanded = false;
--
admin/stages/StageWizard.ts:
    @property({ type: Boolean })
    showBindingPage = false;
--
elements/forms/FormElement.ts:
    @property({ type: Boolean })
    required = false;
--
admin/common/ak-flow-search/FlowSearch.ts:
    @property({ type: Boolean })
    required?: boolean = false;
--
admin/applications/ProviderSelectModal.ts:
    @property({ type: Boolean })
    backchannel = false;
--
elements/forms/SearchSelect/SearchSelect.ts:
    @property({ type: Boolean })
    blankable = false;
--
admin/applications/components/ak-provider-search-input.ts:
    @property({ type: Boolean })
    required = false;
--
admin/applications/components/ak-provider-search-input.ts:
    @property({ type: Boolean })
    blankable = false;
--
admin/applications/components/ak-backchannel-input.ts:
    @property({ type: Boolean })
    required = false;
--
admin/policies/PolicyWizard.ts:
    @property({ type: Boolean })
    showBindingPage = false;

Note: The attribute ‘required’ is an HTML native, and is false by default. Wrappers around HTML Input fields should still declare it, for consistency and to help lit-analyze, cem-analyze, and Storybook work correctly.

Next, here are all the change pairs around HTML attributes:

$ git diff | rg -A 1 '\?(backchannel|blankable|checked|compact|expanded|fullHeight|good|inline|open|readOnly|required|showBindingPage|slugMode|vertical)\b' 

-                ?required=${true}
+                required

-                    <ak-provider-select-table ?backchannel=${true} .confirm=${this.confirm}>
+                    <ak-provider-select-table backchannel .confirm=${this.confirm}>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${false}

-                    ?required=${true}
+                    required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                                  ?blankable=${true}
+                                  blankable

-                        ?required=${true}
+                        required

-                ?blankable=${true}
+                blankable

-                ?blankable=${true}
+                blankable

-            ?required=${true}
+            required

-            ?required=${true}
+            required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
+        return html` <ak-form-element-horizontal label=${msg("Name")} name="name" required>

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    ?blankable=${true}
+                    blankable

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Severity")} ?required=${true} name="severity">
+            <ak-form-element-horizontal label=${msg("Severity")} required name="severity">

-                        ?showBindingPage=${true}
+                        showBindingPage

-                ?showBindingPage=${true}
+                showBindingPage

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Title")} ?required=${true} name="title">
+            <ak-form-element-horizontal label=${msg("Title")} required name="title">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            ?required=${true}
+            required

-            <ak-form-element-horizontal label=${msg("Stage")} ?required=${true} name="stage">
+            <ak-form-element-horizontal label=${msg("Stage")} required name="stage">

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    ?blankable=${true}
+                    blankable

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("Type")} required name="type">

-                    ?blankable=${true}
+                    blankable

-                        <ak-label color=${PFColor.Green} ?compact=${true}>
+                        <ak-label color=${PFColor.Green} compact>

-                            ? html`<ak-label color=${PFColor.Red} ?compact=${true}
+                            ? html`<ak-label color=${PFColor.Red} compact

-                            : html`<ak-label color=${PFColor.Green} ?compact=${true}
+                            : html`<ak-label color=${PFColor.Green} compact

-                    ? html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    ? html`<ak-label color=${PFColor.Orange} compact>

-                    : html`<ak-label color=${PFColor.Green} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Green} compact>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Docker URL")} ?required=${true} name="url">
+            <ak-form-element-horizontal label=${msg("Docker URL")} required name="url">

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?showBindingPage=${true}
+                        showBindingPage

-                      ?showBindingPage=${true}
+                      showBindingPage

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-            <ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout">
+            <ak-form-element-horizontal label=${msg("Timeout")} required name="timeout">

-                    ? html`<ak-label color=${PFColor.Green} ?compact=${true}>
+                    ? html`<ak-label color=${PFColor.Green} compact>

-                    : html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Orange} compact>

-        return html`<ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
+        return html`<ak-form-element-horizontal label=${msg("User")} required name="user">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                      ?readOnly=${true}
+                      readOnly

-            return html`<ak-empty-state loading ?fullHeight=${true}></ak-empty-state>`;
+            return html`<ak-empty-state loading fullHeight></ak-empty-state>`;

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                    ?required=${true}
+                    required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-            ?required=${true}
+            required

-                    ?required=${true}
+                    required

-                                        ?blankable=${true}
+                                        blankable

-            <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
+            <ak-form-element-horizontal label=${msg("Name")} name="name" required>

-            <ak-form-element-horizontal label=${msg("Protocol")} ?required=${true} name="protocol">
+            <ak-form-element-horizontal label=${msg("Protocol")} required name="protocol">

-            <ak-form-element-horizontal label=${msg("Host")} name="host" ?required=${true}>
+            <ak-form-element-horizontal label=${msg("Host")} name="host" required>

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                    ?required=${false}

-                        ?blankable=${true}
+                        blankable

-                        ?blankable=${true}
+                        blankable

-        return html`<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html`<ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                                      ?readOnly=${true}
+                                      readOnly

-                                    ?blankable=${true}
+                                    blankable

-        return html`<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html`<ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    : html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Orange} compact>

-                <ak-label color=${PFColor.Grey} ?compact=${true}> ${msg("Built-in")}</ak-label>
+                <ak-label color=${PFColor.Grey} compact> ${msg("Built-in")}</ak-label>

-            return html`<ak-empty-state loading ?fullHeight=${true}></ak-empty-state>`;
+            return html`<ak-empty-state loading fullHeight></ak-empty-state>`;

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${false}>
+            <ak-form-group>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                        ?required=${true}
+                        required

-                                ?readOnly=${true}
+                                readOnly

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                <ak-form-element-horizontal label=${msg("SMTP Host")} ?required=${true} name="host">
+                <ak-form-element-horizontal label=${msg("SMTP Host")} required name="host">

-                <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
+                <ak-form-element-horizontal label=${msg("SMTP Port")} required name="port">

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                    ?blankable=${true}
+                    blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        <ak-alert ?inline=${true}>
+                        <ak-alert inline>

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    <ak-form-element-horizontal label=${msg("Mode")} ?required=${true} name="mode">
+                    <ak-form-element-horizontal label=${msg("Mode")} required name="mode">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                <ak-form-element-horizontal label=${msg("SMTP Host")} ?required=${true} name="host">
+                <ak-form-element-horizontal label=${msg("SMTP Host")} required name="host">

-                <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
+                <ak-form-element-horizontal label=${msg("SMTP Port")} required name="port">

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                ?slugMode=${true}
+                slugMode

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Expires")} ?required=${true} name="expires">
+            <ak-form-element-horizontal label=${msg("Expires")} required name="expires">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                        ?required=${true}
+                        required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Field Key")} ?required=${true} name="fieldKey">
+            <ak-form-element-horizontal label=${msg("Field Key")} required name="fieldKey">

-            <ak-form-element-horizontal label=${msg("Label")} ?required=${true} name="label">
+            <ak-form-element-horizontal label=${msg("Label")} required name="label">

-            <ak-form-element-horizontal label=${msg("Type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("Type")} required name="type">

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Source")} ?required=${true} name="source">
+            <ak-form-element-horizontal label=${msg("Source")} required name="source">

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        <ak-alert ?inline=${true}>
+                        <ak-alert inline>

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
+            <ak-form-element-horizontal label=${msg("User")} required name="user">

-            <ak-form-element-horizontal label=${msg("Intent")} ?required=${true} name="intent">
+            <ak-form-element-horizontal label=${msg("Intent")} required name="intent">

-                ?required=${true}
+                required

-                    <input class="pf-c-switch__input" type="checkbox" ?checked=${true} />
+                    <input class="pf-c-switch__input" type="checkbox" checked />

-                    <input class="pf-c-switch__input" type="checkbox" ?checked=${true} />
+                    <input class="pf-c-switch__input" type="checkbox" checked />

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("User type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("User type")} required name="type">

-            <ak-form-element-horizontal label=${msg("Path")} ?required=${true} name="path">
+            <ak-form-element-horizontal label=${msg("Path")} required name="path">

-            ?required=${true}
+            required

-            ?required=${true}
+            required

-            <ak-tabs pageIdentifier="userCredentialsTokens" ?vertical=${true}>
+            <ak-tabs pageIdentifier="userCredentialsTokens" vertical>

-                <ak-status-label ?good=${true}></ak-status-label>
+                <ak-status-label good></ak-status-label>

-                    ?open=${true}
+                    open

-                ?blankable=${true}
+                blankable

-                <ak-tabs ?vertical="${true}">
+                <ak-tabs vertical>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

The following issues are the true by default Booleans. As mentioned, these are not addressed by this PR.

elements/table/Table.ts::
    @property({ type: Boolean })
    paginated = true;

elements/forms/ModalForm.ts::
    @property({ type: Boolean })
    closeAfterSuccessfulSubmit = true;

elements/forms/ModalForm.ts::
    @property({ type: Boolean })
    showSubmitButton = true;

elements/CodeMirror.ts::
    @property({ type: Boolean })
    parseValue = true;

elements/LoadingOverlay.ts::
    @property({ type: Boolean })
    loading = true;

admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts::
    @property({ type: Boolean })
    showConfigurationStages = true;

elements/user/sources/SourceSettings.ts::
    @property({ type: Boolean })
    canConnect = true;

admin/outposts/OutpostHealthSimple.ts::
    @property({ attribute: false })
    showVersion = true;

elements/wizard/Wizard.ts::
    @property({ type: Boolean })
    canCancel = true;

elements/wizard/Wizard.ts::
    @property({ type: Boolean })
    canBack = true;
  • The code has been formatted (make web)

## What

- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
  - Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
    to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`

## Note

Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.
* main: (43 commits)
  core, web: update translations (#11858)
  web/admin: fix code-based MFA toggle not working in wizard (#11854)
  sources/kerberos: add kiprop to ignored system principals (#11852)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11846)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#11845)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#11847)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11848)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11849)
  translate: Updates for file web/xliff/en.xlf in it (#11850)
  website: 2024.10 Release Notes (#11839)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11814)
  core, web: update translations (#11821)
  core: bump goauthentik.io/api/v3 from 3.2024083.13 to 3.2024083.14 (#11830)
  core: bump service-identity from 24.1.0 to 24.2.0 (#11831)
  core: bump twilio from 9.3.5 to 9.3.6 (#11832)
  core: bump pytest-randomly from 3.15.0 to 3.16.0 (#11833)
  website/docs: Update social-logins github (#11822)
  website/docs: remove � (#11823)
  lifecycle: fix kdc5-config missing (#11826)
  website/docs: update preview status of different features (#11817)
  ...
* main:
  website: bump elliptic from 6.5.7 to 6.6.0 in /website (#11869)
  core: bump selenium from 4.25.0 to 4.26.0 (#11875)
  core: bump goauthentik.io/api/v3 from 3.2024083.14 to 3.2024100.1 (#11876)
  website/docs: add info about invalidation flow, default flows in general (#11800)
  website: fix docs redirect (#11873)
  website: remove RC disclaimer for version 2024.10 (#11871)
  website: update supported versions (#11841)
  web: bump API Client version (#11870)
  root: backport version bump 2024.10.0 (#11868)
  website/docs: 2024.8.4 release notes (#11862)
  web/admin: provide default invalidation flows for LDAP and Radius (#11861)
* main:
  core: add `None` check to a device's `extra_description` (#11904)
  providers/oauth2: fix size limited index for tokens (#11879)
  web: fix missing status code on failed build (#11903)
  website: bump docusaurus-theme-openapi-docs from 4.1.0 to 4.2.0 in /website (#11897)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11891)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#11884)
  translate: Updates for file web/xliff/en.xlf in tr (#11878)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in tr (#11866)
  core: bump google-api-python-client from 2.149.0 to 2.151.0 (#11885)
  core: bump selenium from 4.26.0 to 4.26.1 (#11886)
  core, web: update translations (#11896)
  website: bump docusaurus-plugin-openapi-docs from 4.1.0 to 4.2.0 in /website (#11898)
  core: bump watchdog from 5.0.3 to 6.0.0 (#11899)
  core: bump ruff from 0.7.1 to 0.7.2 (#11900)
  core: bump django-pglock from 1.6.2 to 1.7.0 (#11901)
  website/docs: fix release notes to say Federation (#11889)
* main:
  web: bump API Client version (#11909)
  enterprise/rac: fix API Schema for invalidation_flow (#11907)
* main:
  website/docs: fix slug matching redirect URI causing broken refresh (#11950)
  website/integrations: jellyfin: update plugin catalog location (#11948)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11942)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11946)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11947)
  website/docs: clarify traefik ingress setup (#11938)
  core: bump importlib-metadata from 8.4.0 to 8.5.0 (#11934)
  web: bump API Client version (#11930)
  root: backport version bump `2024.10.1` (#11929)
  website/docs: `2024.10.1` Release Notes (#11926)
  website: bump path-to-regexp from 1.8.0 to 1.9.0 in /website (#11924)
  core: bump sentry-sdk from 2.17.0 to 2.18.0 (#11918)
  website: bump the docusaurus group in /website with 9 updates (#11917)
  core: bump goauthentik.io/api/v3 from 3.2024100.1 to 3.2024100.2 (#11915)
  core, web: update translations (#11914)
* main:
  ci: fix dockerfile warning (#11956)
* main: (21 commits)
  web: bump API Client version (#11997)
  sources/kerberos: use new python-kadmin implementation (#11932)
  core: add ability to provide reason for impersonation (#11951)
  website/integrations:  update vcenter integration docs (#11768)
  core, web: update translations (#11995)
  website: bump postcss from 8.4.48 to 8.4.49 in /website (#11996)
  web: bump API Client version (#11992)
  blueprints: add default Password policy (#11793)
  stages/captcha: Run interactive captcha in Frame (#11857)
  core, web: update translations (#11979)
  core: bump packaging from 24.1 to 24.2 (#11985)
  core: bump ruff from 0.7.2 to 0.7.3 (#11986)
  core: bump msgraph-sdk from 1.11.0 to 1.12.0 (#11987)
  website: bump the docusaurus group in /website with 9 updates (#11988)
  website: bump postcss from 8.4.47 to 8.4.48 in /website (#11989)
  stages/password: use recovery flow from brand (#11953)
  core: bump golang.org/x/sync from 0.8.0 to 0.9.0 (#11962)
  web: bump cookie, swagger-client and express in /web (#11966)
  core, web: update translations (#11959)
  core: bump debugpy from 1.8.7 to 1.8.8 (#11961)
  ...
* main:
  providers/ldap: fix global search_full_directory permission not being sufficient (#12028)
  website/docs: 2024.10.2 release notes (#12025)
  lifecycle: fix ak exit status not being passed (#12024)
  core: use versioned_script for path only (#12003)
  core, web: update translations (#12020)
  core: bump google-api-python-client from 2.152.0 to 2.153.0 (#12021)
  providers/oauth2: fix manual device code entry (#12017)
  crypto: validate that generated certificate's name is unique (#12015)
  core, web: update translations (#12006)
  core: bump google-api-python-client from 2.151.0 to 2.152.0 (#12007)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12011)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12010)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12012)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12013)
  providers/proxy: fix Issuer when AUTHENTIK_HOST_BROWSER is set (#11968)
  website/docs: move S3 ad GeoIP to System Management/Operations (#11998)
  website/integrations: nextcloud: add SSE warning (#11976)
* main:
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12045)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12047)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12044)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12046)
  web/flows: fix invisible captcha call (#12048)
  rbac: fix incorrect object_description for object-level permissions (#12029)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#12036)
  core: bump coverage from 7.6.4 to 7.6.5 (#12037)
  ci: bump codecov/codecov-action from 4 to 5 (#12038)
  release: 2024.10.2 (#12031)
* main: (28 commits)
  providers/scim: accept string and int for SCIM IDs (#12093)
  website: bump the docusaurus group in /website with 9 updates (#12086)
  core: fix source_flow_manager throwing error when authenticated user attempts to re-authenticate with existing link (#12080)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#12079)
  scripts: remove read_replicas from generated dev config (#12078)
  core: bump geoip2 from 4.8.0 to 4.8.1 (#12071)
  core: bump goauthentik.io/api/v3 from 3.2024100.2 to 3.2024102.2 (#12072)
  core: bump maxmind/geoipupdate from v7.0.1 to v7.1.0 (#12073)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12074)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12075)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12076)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12077)
  web/admin: auto-prefill user path for new users based on selected path (#12070)
  core: bump aiohttp from 3.10.2 to 3.10.11 (#12069)
  web/admin: fix brand title not respected in application list (#12068)
  core: bump pyjwt from 2.9.0 to 2.10.0 (#12063)
  web: add italian locale (#11958)
  web/admin: better footer links (#12004)
  core, web: update translations (#12052)
  core: bump twilio from 9.3.6 to 9.3.7 (#12061)
  ...
* main: (33 commits)
  ci: mirror repo to internal repo (#12160)
  core: bump goauthentik.io/api/v3 from 3.2024102.2 to 3.2024104.1 (#12149)
  core: bump debugpy from 1.8.8 to 1.8.9 (#12150)
  core: bump webauthn from 2.2.0 to 2.3.0 (#12151)
  core: bump pydantic from 2.10.0 to 2.10.1 (#12152)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12156)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12157)
  core: bump sentry-sdk from 2.18.0 to 2.19.0 (#12153)
  web: bump API Client version (#12147)
  root: Backport version change (#12146)
  website/docs: update info about footer links to match new UI (#12120)
  website/docs: prepare release notes (#12142)
  providers/oauth2: fix migration (#12138)
  providers/oauth2: fix migration dependencies (#12123)
  web: bump API Client version (#12129)
  providers/oauth2: fix redirect uri input (#12122)
  providers/proxy: fix redirect_uri (#12121)
  website/docs: prepare release notes (#12119)
  web: bump API Client version (#12118)
  security: fix CVE 2024 52289 (#12113)
  ...
* main:
  ci: only mirror if secret is available (#12181)
  root: fix database ssl options not set correctly (#12180)
  core, web: update translations (#12145)
  core: bump tornado from 6.4.1 to 6.4.2 (#12165)
  website: bump the docusaurus group in /website with 9 updates (#12172)
  website: bump typescript from 5.6.3 to 5.7.2 in /website (#12173)
  ci: bump actions/checkout from 3 to 4 (#12174)
  core: bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#12175)
  core: bump coverage from 7.6.7 to 7.6.8 (#12176)
  core: bump ruff from 0.7.4 to 0.8.0 (#12177)
* main:
  website/docs: Fix CSP syntax (#12124)
* main:
  website/docs: Add note about single group per role (#12169)
  website/docs: Fix documentation about attribute merging for indirect membership (#12168)
  root: support running authentik in subpath (#8675)
  docs: fix contribution link (#12189)
  core, web: update translations (#12190)
  core: Bump msgraph-sdk from 1.12.0 to 1.13.0 (#12191)
  core: Bump selenium from 4.26.1 to 4.27.0 (#12192)
* main: (31 commits)
  web/admin: bugfix: dual select initialization revision (#12051)
  web: update tests for Chromedriver 131 (#12199)
  website/integrations: add Aruba Orchestrator (#12220)
  core: bump aws-cdk-lib from 2.167.1 to 2.171.1 (#12237)
  website: bump aws-cdk from 2.167.1 to 2.171.1 in /website (#12241)
  core, web: update translations (#12236)
  core: bump python-kadmin-rs from 0.2.0 to 0.3.0 (#12238)
  core: bump pytest from 8.3.3 to 8.3.4 (#12239)
  core: bump drf-spectacular from 0.27.2 to 0.28.0 (#12240)
  core, web: update translations (#12222)
  core: Bump ruff from 0.8.0 to 0.8.1 (#12224)
  core: Bump ua-parser from 0.18.0 to 1.0.0 (#12225)
  core: Bump msgraph-sdk from 1.13.0 to 1.14.0 (#12226)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#12234)
  website/docs: install: add aws (#12082)
  core: Bump pyjwt from 2.10.0 to 2.10.1 (#12217)
  core: Bump fido2 from 1.1.3 to 1.2.0 (#12218)
  core: Bump cryptography from 43.0.3 to 44.0.0 (#12219)
  providers/oauth2: allow m2m for JWKS without alg in keys (#12196)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#12210)
  ...
* main:
  web: simplify `?inline` handler for Storybook (#12246)
  website/docs: Update Traefik middleware example to reflect latest version of Traefik (#12267)
  website/docs: add . in https://netbird.company* (#12166)
  core: bump goauthentik.io/api/v3 from 3.2024104.1 to 3.2024104.2 (#12263)
  core: bump pydantic from 2.10.2 to 2.10.3 (#12262)
  core: bump github.com/getsentry/sentry-go from 0.29.1 to 0.30.0 (#12264)
  core, web: update translations (#12268)
  website: bump @types/react from 18.3.12 to 18.3.13 in /website (#12269)
  website: bump prettier from 3.4.1 to 3.4.2 in /website (#12270)
  ci: bump actions/attest-build-provenance from 1 to 2 (#12271)
  core: bump golang.org/x/sync from 0.9.0 to 0.10.0 (#12272)
  core: bump django from 5.0.9 to 5.0.10 (#12273)
  core: bump webauthn from 2.3.0 to 2.4.0 (#12274)
  website/integrations: add The Lounge (#11971)
  core: bump python-kadmin-rs from 0.3.0 to 0.4.0 (#12257)
  root: fix health status code (#12255)
  ci: fix should_push always being false (#12252)
  web: bump API Client version (#12251)
  providers/oauth2: Add provider federation between OAuth2 Providers (#12083)
  website/integrations: mastodon: set correct uid field (#11945)
* main:
  website/docs: add page about the Cobalt pentest (#12249)
  core: bump aws-cdk-lib from 2.171.1 to 2.172.0 (#12296)
  website: bump aws-cdk from 2.171.1 to 2.172.0 in /website (#12295)
  core: bump sentry-sdk from 2.19.1 to 2.19.2 (#12297)
  core: bump coverage from 7.6.8 to 7.6.9 (#12299)
  core, web: update translations (#12290)
  root: fix override locale only if it is not empty (#12283)
  translate: Updates for file web/xliff/en.xlf in fr (#12276)
  core: bump twilio from 9.3.7 to 9.3.8 (#12282)
  website: bump path-to-regexp and express in /website (#12279)
  core: bump sentry-sdk from 2.19.0 to 2.19.1 (#12280)
  core: bump ruff from 0.8.1 to 0.8.2 (#12281)
  website/docs: fix lint (#12287)
  website/integrations: netbird: fix redirect URI regex (#12284)
* main:
  flows: better test stage's challenge responses (#12316)
  enterprise/stages/authenticator_endpoint_gdtc: don't set frame options globally (#12311)
  stages/identification: fix invalid challenge warning when no captcha stage is set (#12312)
  website/docs: prepare 2024.10.5 release notes (#12309)
  website: bump nanoid from 3.3.7 to 3.3.8 in /website (#12307)
  flows: silent authz flow (#12213)
  root:  use healthcheck in depends_on for postgres and redis (#12301)
  ci: ensure mark jobs always run and reflect correct status (#12288)
  enterprise: allow deletion/modification of users when in read-only mode (#12289)
  web/flows: resize captcha iframes (#12260)
* main: (118 commits)
  outposts: fix version label (#12486)
  web: only load version context when authenticated (#12482)
  core: bump goauthentik.io/api/v3 from 3.2024120.2 to 3.2024121.2 (#12478)
  ci: bump helm/kind-action from 1.11.0 to 1.12.0 (#12479)
  web: fix build dev build (#12473)
  root: fix dev build version being invalid semver (#12472)
  internal: fix missing trailing slash in outpost websocket (#12470)
  web: bump API Client version (#12469)
  admin: monitor worker version (#12463)
  core: bump jinja2 from 3.1.4 to 3.1.5 (#12467)
  web: bump API Client version (#12468)
  release: 2024.12.1 (#12466)
  web: misc fixes for admin and flow inspector (#12461)
  website/docs: 2024.12.1 release notes (#12462)
  core: bump goauthentik.io/api/v3 from 3.2024120.1 to 3.2024120.2 (#12456)
  core: bump urllib3 from 2.2.3 to 2.3.0 (#12457)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12454)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12453)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12455)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12458)
  ...
…ing.

\# What

\# Why

\# How

\# Designs

\# Test Steps

\# Other Notes
* main:
  website/integrations: meshcentral: document (#12509)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#12524)
  core: bump goauthentik.io/api/v3 from 3.2024121.2 to 3.2024121.3 (#12522)
  web: bump API Client version (#12520)
  website/integrations: chronograf: document (#12474)
  website/integrations: update preparation placeholder (#12507)
  providers/saml: fix handle Accept: application/xml for SAML Metadata endpoint (#12483) (#12518)
  core: bump aws-cdk-lib from 2.173.3 to 2.173.4 (#12513)
  website: bump aws-cdk from 2.173.3 to 2.173.4 in /website (#12514)
  core: bump coverage from 7.6.9 to 7.6.10 (#12499)
  core: bump aws-cdk-lib from 2.173.2 to 2.173.3 (#12500)
  website: bump aws-cdk from 2.173.2 to 2.173.3 in /website (#12501)
  core: bump github.com/go-ldap/ldap/v3 from 3.4.9 to 3.4.10 (#12502)
  website/docs: New "Whats Up Docker" URL (#12488)
* main:
  core: bump github.com/getsentry/sentry-go from 0.30.0 to 0.31.1 (#12543)
  core: bump google-api-python-client from 2.156.0 to 2.157.0 (#12544)
  core: bump ruff from 0.8.4 to 0.8.5 (#12545)
  core: bump msgraph-sdk from 1.15.0 to 1.16.0 (#12546)
  Update index.mdx (#12542)
  web: fix source selection and outpost integration health (#12530)
  Ading a step to paperless guide (#12539)
  website/integrations: Semaphore (#12515)
  website/integrations: komga: document (#12476)
  website/integrations: fix missing quote in paperless-ngx (#12537)
  website/integrations: cloudflare access: upd placeholder for saas (#12536)
  website/integrations: veeam-enterprise-manager: don't hardcode helpcenter doc version (#12538)
* main:
  core: bump golang.org/x/oauth2 from 0.24.0 to 0.25.0 (#12571)
  website: bump the docusaurus group in /website with 9 updates (#12569)
  core: bump github.com/coreos/go-oidc/v3 from 3.11.0 to 3.12.0 (#12572)
  core: bump ruff from 0.8.5 to 0.8.6 (#12573)
  ci: release: fix AWS cfn template permissions (#12576)
  translate: Updates for file web/xliff/en.xlf in fr (#12578)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#12577)
  sources/kerberos: authenticate with the user's username instead of the first username in authentik (#12497)
  website/integrations: Fix deprecated terraform ressource authentik_scope_mapping in docs (#12554)
  website/user-sources Fix Free IPA docs page (#12549)
  core: bump aws-cdk-lib from 2.173.4 to 2.174.0 (#12574)
  website/integrations: semaphore: fix formatting (#12567)
  website: bump aws-cdk from 2.173.4 to 2.174.0 in /website (#12570)
  website/integrations: Update Frappe Application index.md (#12527)
  website: add api reference docs to redirect file (#12551)
* main:
  lib: add expression helper ak_create_jwt to create JWTs (#12599)
  api: cleanup owner permissions (#12598)
  website: bump aws-cdk from 2.174.0 to 2.174.1 in /website (#12593)
  core: bump aws-cdk-lib from 2.174.0 to 2.174.1 (#12594)
  website/integrations: portainer: group config steps (#12548)
  translate: Updates for file web/xliff/en.xlf in fi (#12586)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fi (#12584)
  website/docs: fix Nginx redirection example (#12561)
* main:
  website: revise full development environment instructions (#12638)
  website: bump typescript from 5.7.2 to 5.7.3 in /website (#12620)
  website: bump aws-cdk from 2.174.1 to 2.175.0 in /website (#12621)
  ci: bump docker/setup-qemu-action from 3.2.0 to 3.3.0 (#12622)
  core: bump twilio from 9.4.1 to 9.4.2 (#12623)
  core: bump python-kadmin-rs from 0.5.2 to 0.5.3 (#12624)
  core: bump ruff from 0.8.6 to 0.9.0 (#12625)
  core: bump pydantic from 2.10.4 to 2.10.5 (#12626)
  core: bump google-api-python-client from 2.157.0 to 2.158.0 (#12628)
  core: bump goauthentik.io/api/v3 from 3.2024121.3 to 3.2024122.1 (#12629)
  web: bump API Client version (#12617)
  release: 2024.12.2 (#12615)
  website/docs: prepare 2024.12.2 release notes (#12614)
  providers/saml: fix invalid SAML Response when assertion and response are signed (#12611)
  core: fix error when creating new user with default path (#12609)
  rbac: permissions endpoint: allow authenticated users (#12608)
  website/docs: update customer portal (#12603)
  website/docs: policy for email whitelist: modernize (#12558)
* main: (65 commits)
  stages/redirect: fix query parameter when redirecting to flow (#12750)
  website/integrations: cloudflare-access: refactor (#12663)
  sources/kerberos: handle principal expire time (#12748)
  lifecycle: build binary dependencies which link against SSL directly (#12724)
  website/docs: style guide: document styling preferences for URLs (#12715)
  website/integrations: nextcloud: fix broken link (#12744)
  core: bump selenium from 4.27.1 to 4.28.0 (#12745)
  lifecycle: move AWS CFN generation to lifecycle and fix CI (#12743)
  core: search users' attributes (#12740)
  web/components: ak-number-input: add support for min (#12703)
  website/integrations: nextcloud: fix url for "disable username changes" (#12725)
  core: bump pytest-github-actions-annotate-failures from 0.2.0 to 0.3.0 (#12735)
  website: bump katex from 0.16.11 to 0.16.21 in /website (#12731)
  web: bump katex from 0.16.11 to 0.16.21 in /web (#12730)
  website/integrations: Fix URL for authentik installation instead of mobilizon installation (#12729)
  core: bump debugpy from 1.8.11 to 1.8.12 (#12718)
  core: bump ruff from 0.9.1 to 0.9.2 (#12717)
  core: bump webauthn from 2.4.0 to 2.5.0 (#12719)
  core: bump structlog from 24.4.0 to 25.1.0 (#12720)
  website/integrations: all: install -> installation (#12676)
  ...
* main:
  web: update gen-client-ts to OpenAPI 7.11.0 (#12756)
  website/integrations: rustdesk-server-pro (#12706)
  core: bump codespell from 2.3.0 to 2.4.0 (#12762)
  root: docker: ensure apt packages are up-to-date (#12683)
  ci: fix missing build args for dev and release (#12760)
  web: bump vite from 5.4.11 to 5.4.14 in /web (#12757)
  web: bump undici from 6.21.0 to 6.21.1 in /web (#12755)
  lifecycle: fix cryptography's OpenSSL path (#12753)
* main: (111 commits)
  root: correctly use correct schema for install_id (#13018)
  website: bump docusaurus-plugin-openapi-docs from 4.3.3 to 4.3.4 in /website (#13011)
  web: bump API Client version (#13017)
  core: bump aws-cdk-lib from 2.178.1 to 2.178.2 (#13013)
  core: bump oss/go/microsoft/golang from 1.23-fips-bookworm to 1.24-fips-bookworm (#13012)
  website: bump docusaurus-theme-openapi-docs from 4.3.3 to 4.3.4 in /website (#13010)
  lifecycle/aws: bump aws-cdk from 2.178.1 to 2.178.2 in /lifecycle/aws (#13009)
  core: bump github.com/sethvargo/go-envconfig from 1.1.0 to 1.1.1 (#13008)
  web/admin: fix source selection for identification stage (#13007)
  core: bump sentry-sdk from 2.20.0 to 2.21.0 (#13014)
  website/integrations: Open WebUI (#12939)
  root: use correct default schema for install_id (#13006)
  website/docs: fix a minor typo (#13004)
  enterprise/providers/ssf: fixes v2 (#13003)
  root: make default postgres schema configurable (#12949)
  providers/oauth2: cleanup tokens when user is deactivated (#12859)
  website/docs: fix Nginx redirection example (#12920)
  core: bump twilio from 9.4.4 to 9.4.5 (#12993)
  core: bump coverage from 7.6.11 to 7.6.12 (#12994)
  core: bump cryptography from 44.0.0 to 44.0.1 (#12992)
  ...
* main:
  website: add a better edit this page element (#13391)
  web/admin: allow user lists to show active only (#13403)
  core: Tidy contributor onboarding, fix typos. (#12700)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#13418)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#13417)
  lib/config: fix conn_max_age parsing (#13370)
  core: bump golang.org/x/sync from 0.11.0 to 0.12.0 (#13407)
  stages/authenticator_email: Fix Enroll dropdown in the MFA Devices page (#13404)
  core: bump golang.org/x/oauth2 from 0.27.0 to 0.28.0 (#13408)
  core: bump aws-cdk-lib from 2.181.1 to 2.182.0 (#13409)
  core: bump google-api-python-client from 2.162.0 to 2.163.0 (#13410)
  core: bump msgraph-sdk from 1.22.0 to 1.23.0 (#13411)
  core: bump jinja2 from 3.1.5 to 3.1.6 (#13412)
  web/user: ensure modal container on user-settings page is min-height: 100% (#13402)
  core, web: update translations (#13405)
  web/admin: add button to clear application cache (#13399)
  blueprints: Adjust title for MFA set up (#13400)
* main:
  translate: Updates for file web/xliff/en.xlf in fr (#13431)
  lifecycle/aws: bump aws-cdk from 2.1002.0 to 2.1003.0 in /lifecycle/aws (#13426)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#13428)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#13429)
  core, web: update translations (#13423)
* main:
  web: admin interface: faster card load (#13331)
  web/admin: fix display bug for assigned users in application bindings in the wizard (#13435)
  website: bump the build group across 1 directory with 9 updates (#13442)
  core: bump django from 5.0.12 to 5.0.13 (#13425)
  providers/SCIM: fix object exists error for users, attempt to look up user ID in remote system (#13437)
  website/docs: sys mgmt: document authentik backups/restoration (#12943)
  website: fix build in docker (#13430)
  website/integrations: zipline: add (#13257)
* main:
  web: Ignore Storybook when running codespell. (#13454)
  core: bump ruff from 0.9.9 to 0.9.10 (#13448)
  core: bump webauthn from 2.5.1 to 2.5.2 (#13449)
  website/docs: backup and restore: remove extra period (#13440)
  website: bump prismjs from 1.29.0 to 1.30.0 in /website (#13456)
  web: bump prismjs from 1.29.0 to 1.30.0 in /web (#13455)
* main:
  stages/email: token_expiry format (#13394)
  core, web: update translations (#13438)
  website/docs: in developer docs replace deprecated poetry shell command (#13460)
* main: (44 commits)
  providers/rac: fix signals and Endpoint caching (#13529)
  web/flows: fix missing padding on authenticator_validate card (#13420)
  web/user: show admin interface button on mobile (#13421)
  website: Bump the build group in /website with 6 updates (#13501)
  core: Bump goauthentik.io/api/v3 from 3.2025021.3 to 3.2025021.4 (#13495)
  core: Bump importlib-metadata from 8.5.0 to 8.6.1 (#13499)
  core: Bump msgraph-sdk from 1.23.0 to 1.24.0 (#13500)
  core: Bump google-api-python-client from 2.163.0 to 2.164.0 (#13498)
  core: Bump aws-cdk-lib from 2.182.0 to 2.183.0 (#13496)
  core: Bump psycopg from 3.2.5 to 3.2.6 (#13497)
  translate: Updates for file web/xliff/en.xlf in fr (#13514)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13513)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#13510)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#13511)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#13509)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13508)
  core, web: update translations (#13494)
  website: remove the last updated option from footer (#13493)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13487)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13488)
  ...
* main:
  website/docs: dev docs: bump node/postgres requirements  (#13516)
  sources: prevent deletion of built-in source (#12914)
  core: bump django-tenants (#13536)
  website/docs: dev docs: full: remove note on installing shell plugin (#13515)
  sources/oauth: fix duplicate authentication (#13322)
  web/admin: fix comment being rendered (#13530)
  core: Bump aws-cdk-lib from 2.183.0 to 2.184.0 (#13522)
  core, web: update translations (#13520)
  lifecycle/aws: Bump aws-cdk from 2.1003.0 to 2.1004.0 in /lifecycle/aws (#13524)
  core: Bump github.com/coreos/go-oidc/v3 from 3.12.0 to 3.13.0 (#13525)
* main: (76 commits)
  admin: fix system API when using bearer token (#13651)
  website: bump the build group in /website with 6 updates (#13645)
  core: bump goauthentik.io/api/v3 from 3.2025022.5 to 3.2025022.6 (#13646)
  translate: Updates for file web/xliff/en.xlf in fr (#13653)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13652)
  website/integrations: add tandoor (#13560)
  core, web: update translations (#13642)
  providers/scim: fix group membership check failing (#13644)
  ci: add semgrep (#13643)
  flows: fix API not returning configured background (#13641)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13631)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#13633)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#13632)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#13634)
  brands: fix migration 0008 by removing incorrect context manager usage (#13635)
  web: Fix prop. (#13630)
  core, web: update translations (#13628)
  web/admin: reworked sync status card (#13625)
  core: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 (#13626)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#13622)
  ...
* main:
  ci: stop publishing latest tag (#13245)
  root: fix dependency install due to description-file (#13655)
* main: (204 commits)
  core: bump protobuf from 5.29.4 to v6.30.2 (#13950)
  core: bump pyasn1-modules from 0.4.1 to v0.4.2 (#13951)
  core: bump microsoft-kiota-authentication-azure from 1.9.2 to v1.9.3 (#13948)
  core: bump microsoft-kiota-http from 1.9.2 to v1.9.3 (#13949)
  core: bump trio-websocket from 0.11.1 to v0.12.2 (#13934)
  core: bump msgraph-core from 1.3.1 to v1.3.3 (#13900)
  core: bump jsii from 1.109.0 to v1.111.0 (#13886)
  core: bump setuptools from 72.1.0 to v78.1.0 (#13928)
  core: bump kombu from 5.3.7 to v5.5.2 (#13888)
  core: bump msgpack from 1.0.8 to v1.1.0 (#13899)
  core: bump msgraph-sdk from 1.24.0 to v1.26.0 (#13901)
  core: bump proto-plus from 1.24.0 to v1.26.1 (#13910)
  core: bump protobuf from 5.27.2 to v5.29.4 (#13911)
  core: bump pydantic from 2.10.6 to v2.11.3 (#13914)
  core: bump rich from 13.7.1 to v14.0.0 (#13922)
  core: bump twisted from 24.7.0 to v24.11.0 (#13936)
  core: bump watchfiles from 0.22.0 to v1.0.5 (#13941)
  core: bump typing-extensions from 4.12.2 to v4.13.1 (#13937)
  core: bump multidict from 6.0.5 to v6.2.0 (#13902)
  core: bump sentry-sdk from 2.22.0 to v2.25.1 (#13927)
  ...
* main: (93 commits)
  core: bump google-auth from 2.38.0 to v2.39.0 (#14076)
  core: bump sentry-sdk from 2.25.1 to v2.26.1 (#14079)
  core: bump prompt-toolkit from 3.0.50 to v3.0.51 (#14078)
  core: bump boto3 from 1.37.33 to v1.37.34 (#14074)
  core: bump msgraph-sdk from 1.27.0 to v1.28.0 (#14077)
  website/docs: fix minor typo in working_with_policies.md (#14071)
  core, web: update translations (#14064)
  stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#14065)
  core: bump goauthentik.io/api/v3 from 3.2025024.4 to 3.2025024.6 (#14069)
  Small fix for Actual-Budget wiki guide (#14066)
  root: support db pool (#13534)
  rbac: add `InitialPermissions` (#13795)
  web: bump API Client version (#14058)
  core: Bump django from 5.0.14 to 5.1.8 (#14059)
  core: bump django-rest-framework from 3.14.0 to 3.16.0 (#14057)
  policies/reputation: limit reputation score (#14008)
  ci: fix api-py-publish by disabling poetry cache (#14010)
  core: bump goauthentik/fips-python from 3.12.9-slim-bookworm-fips to 3.12.10-slim-bookworm-fips (#14044)
  ci: add NPM packages publish (#13974)
  root: add packages/ to codeowners (#13975)
  ...
* main: (49 commits)
  core: bump uvicorn from 0.34.1 to v0.34.2 (#14175)
  website/integrations: add xcreds (#14163)
  core, web: update translations (#14179)
  web: update default flow background (#14115)
  web: bump API Client version (#14176)
  enterprise/policies: Add Password Uniqueness History Policy (#13453)
  web/xliff: fix duplicated translations (#14164)
  website/docs: fix postgres pool recommended settings (#14149)
  core: bump astral-sh/uv from 0.6.14 to 0.6.16 (#14161)
  web: fix scrollbar styling (#12600)
  website: integrations: gravity: fix issuer URL (#14155)
  web: Packagify live reload plugin. (#14134)
  web: bump API Client version (#14062)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#14146)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#14145)
  core: bump goauthentik.io/api/v3 from 3.2025024.7 to 3.2025024.8 (#14143)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#14144)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#14139)
  core, web: update translations (#14142)
  core: bump yarl from 1.19.0 to v1.20.0 (#14128)
  ...
* main:
  packages/docusaurus-theme: Fix header alignment, overscroll, vertical padding. (#14120)
  outposts: add support for gateway API (#13272)
  translate: Updates for file web/xliff/en.xlf in fr (#14200)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#14199)
  website/docs: adds code examples for getting user objects from a group object (#14101)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#14198)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#14195)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#14197)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#14196)
  website/integrations: mealie add integration (#14188)
  core, web: update translations (#14187)
  core: bump goauthentik.io/api/v3 from 3.2025024.8 to 3.2025024.9 (#14189)
  website/docs: update user object doc (#14132)
  website/docs: dev-docs: style guide: no longer using italic for vars (#14185)
  website/docs: dev docs: style guide: update style conventions for urls (#14184)
  website/integrations: paperless: use <slug>. instead of hardcoded slug value (#14183)
  website/docs: updates style guide code block section (#14088)
  website: components: delete multilinecodeblock src (#14094)
  Revert "policies: buffered policy access view for concurrent authorization attempts when unauthenticated (#13629)" (#14180)
* main:
  web: Safari fixes merge branch (#14181)
  website: bump the build group in /website with 9 updates (#14204)
  website: bump typescript from 5.8.2 to 5.8.3 in /website (#13786)
  lifecycle/migrate: fix migration failing if killed during first startup (#14207)
  core, web: update translations (#14203)
  lifecycle/aws: bump aws-cdk from 2.1010.0 to 2.1012.0 in /lifecycle/aws (#14205)
  website/integrations: improves netbird documentation (#14191)
  website/docs: updated user count info (#14186)
  website/docs: rearranged brands docs (#14116)
  website: integrations: apache guacamole: remove redirect URI comments (#14113)
* main: (33 commits)
  website/integrations: adds missing trailing slash in homarr doc (#14249)
  lifecycle: fix test-all in docker (#14244)
  core, web: update translations (#14243)
  web/admin: prevent default logo flashing in admin interface (#13960)
  website/docs: Update release notes for 2025.4 (#14158)
  core, web: update translations (#14241)
  Updates for file web/xliff/en.xlf in zh_TW [Manual Sync] (#14225)
  translate: Updates for file web/xliff/en.xlf in nl [Manual Sync] (#14217)
  translate: Updates for file web/xliff/en.xlf in fi [Manual Sync] (#14219)
  translate: Updates for file web/xliff/en.xlf in de [Manual Sync] (#14220)
  translate: Updates for file web/xliff/en.xlf in fr [Manual Sync] (#14221)
  translate: Updates for file web/xliff/en.xlf in pl [Manual Sync] (#14222)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in es [Manual Sync] (#14223)
  translate: Updates for file web/xliff/en.xlf in zh-Hans [Manual Sync] (#14224)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in de [Manual Sync] (#14226)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fi [Manual Sync] (#14227)
  translate: Updates for file web/xliff/en.xlf in tr [Manual Sync] (#14228)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in pl [Manual Sync] (#14229)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in ko [Manual Sync] (#14230)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in it [Manual Sync] (#14231)
  ...
* main: (54 commits)
  ci: use dependabot for compose correctly? (#14340)
  website/docs: use Universal Device Trust for GDTC instead of Okta (#14335)
  ci: use dependabot for docker-compose files (#14336)
  website/docs: fix dry-run release highlight (#14337)
  rbac: fix RoleObjectPermissionTable not showing `add_user_to_group` (#14312)
  core, web: update translations (#14326)
  core: bump github.com/sethvargo/go-envconfig from 1.2.0 to 1.3.0 (#14327)
  web: bump vite from 5.4.16 to 5.4.19 in /web (#14324)
  core: bump setuptools from 78.1.0 to v79.0.0 (#14173)
  core: bump ruff from 0.11.5 to v0.11.6 (#14171)
  core: bump s3transfer from 0.11.4 to v0.11.5 (#14172)
  core: bump packaging from 24.2 to v25.0 (#14169)
  core: bump aiohttp from 3.11.16 to v3.11.18 (#14166)
  core: bump boto3 from 1.37.35 to v1.37.38 (#14167)
  core: bump frozenlist from 1.5.0 to v1.6.0 (#14168)
  core: bump pdoc from 15.0.1 to v15.0.3 (#14170)
  core: bump trio from 0.29.0 to v0.30.0 (#14174)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#14271)
  website: bump the build group across 1 directory with 9 updates (#14293)
  core, web: update translations (#14309)
  ...
* main: (45 commits)
  web, website: update browserslist (#14386)
  core, web: update translations (#14383)
  website/integrations: add atlassian (#14209)
  core: bump github.com/pires/go-proxyproto from 0.8.0 to 0.8.1 (#14388)
  ci: bump golangci/golangci-lint-action from 7 to 8 (#14389)
  core: bump axllent/mailpit from v1.24.1 to v1.24.2 in /tests/e2e (#14390)
  translate: Updates for file web/xliff/en.xlf in it (#14372)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#14374)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#14375)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in pt (#14379)
  website/integrations: Fix outpost link for Home Assistant configuration (#14382)
  website/docs: fix leftover placeholder in release notes (#14377)
  website/integrations: minio: fix typo (#14376)
  core: bump goauthentik/fips-python from 3.12.10-slim-bookworm-fips to 3.13.3-slim-bookworm-fips (#12763)
  core: bump axllent/mailpit from v1.6.5 to v1.24.1 in /tests/e2e (#14341)
  core: bump selenium/standalone-chrome from 122.0 to 135.0 in /tests/e2e (#14342)
  core: bump lxml from 5.3.2 to v5.4.0 (#14355)
  core: bump azure-core from 1.33.0 to v1.34.0 (#14345)
  core: bump boto3 from 1.37.35 to v1.38.7 (#14346)
  core: bump celery from 5.5.1 to v5.5.2 (#14347)
  ...
* main: (60 commits)
  website: bump the build group in /website with 6 updates (#14502)
  core: remove `OldAuthenticatedSession` content type (#14507)
  core: bump msgraph-sdk from 1.29.0 to 1.30.0 (#14503)
  core: bump twilio from 9.6.0 to 9.6.1 (#14505)
  core: bump psycopg[c,pool] from 3.2.8 to 3.2.9 (#14504)
  enterprise: fix expired license's users being counted (#14451)
  website/integrations: fix missing closing brace for semaphore (#14467)
  tests/e2e: Add E2E tests for Flow SFE (#14484)
  website: bump semver from 7.7.1 to 7.7.2 in /website (#14491)
  core: bump django from 5.1.8 to 5.1.9 (#14483)
  core: bump psycopg[c,pool] from 3.2.7 to 3.2.8 (#14481)
  core: bump sentry-sdk from 2.27.0 to 2.28.0 (#14482)
  root: pin package version in pyproject for dependabot (#14469)
  core: fix session migration when old session can't be loaded (#14466)
  root: temporarily deactivate database pool option (#14443)
  website: bump the build group in /website with 3 updates (#14475)
  website/docs: stages: fix-typo (#14477)
  website/docs: Update Kubernetes Bootstrap Instructions (#14471)
  root: improve sentry distributed tracing (#14468)
  Revert "web/admin: fix enterprise menu display" (#14458)
  ...
* main: (55 commits)
  web: Fix missing Enterprise sidebar entries. (#14615)
  core, web: update translations (#14626)
  esbuild-plugin-live-reload: Publish. (#14624)
  web/NPM Workspaces: Prep ESBuild plugin for publish. (#14552)
  lifecycle: fix arguments not being passed to worker command (#14574)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#14611)
  providers/proxy: kubernetes outpost: fix reconcile when ingress class name changed (#14612)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#14608)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#14607)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#14609)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#14606)
  root: move forked dependencies to goauthentik org (#14590)
  core: bump library/node from 22 to 24 (#14410)
  core: bump django-guardian from 2.4.0 to v3.0.0 (#14453)
  enterprise/stages/mtls: improve certificate validation (#14582)
  translate: Updates for file web/xliff/en.xlf in it (#14575)
  core, web: update translations (#14578)
  core: bump sentry-sdk from 2.28.0 to 2.29.1 (#14579)
  core: bump astral-sh/uv from 0.7.5 to 0.7.6 (#14580)
  web/NPM Workspaces: ESbuild version cleanup (#14541)
  ...
## What

Just cleaning up a bad habit; we have a lot of `?attribute=${true|false}` (or, more alarmingly,
`.attribute=${true|false}`.  These should just be `attribute` or be missing; anything else is
unnecessary.

Where the attribute is `true` by default, no changes have been made; there are only a few of them,
and they require re-working of the logic to assist with the changes. Booleans should never be `true` by
default, and if you absolutely cannot find an alternative phrasing that makes having them be `false`
by default a valid choice, they should be `reflect: true` to make their presence visible to screen
readers and debuggers.

## Why

Removing non-standard HTML uses from web components matches our programming standards and is an
important step toward the Authentik Elements NPM package, as well as the Schema-Driven Forms update.

## Boring excessive detail.

Because there are literally hundreds of changes, I've documented the boring ones here.

Changes that do *not* meet the basic criteria of "made the component comply with the standards" are
commented in the PR.

Here are all the Boolean property declarations in the system, delta the ones that declare `= true`;
those are documented at the bottom of this commit, and are not addressed in this PR.  This
information is included to guide your decision making.  The second block, below, documents the
actual changes made to component declarations throughout our code.  The third block, at the bottom,
documents changes not made due to logic and effort constraints.

```
components/ak-switch-input.ts:
    @Property({ type: Boolean })
    checked: boolean = false;
--
components/ak-switch-input.ts:
    @Property({ type: Boolean })
    required = false;
--
components/ak-file-input.ts:
    @Property({ type: Boolean })
    required = false;
--
components/HorizontalLightComponent.ts:
    @Property({ type: Boolean })
    required = false;
--
components/ak-multi-select.ts:
    @Property({ type: Boolean })
    required = false;
--
elements/TreeView.ts:
    @Property({ type: Boolean })
    open = false;
--
components/ak-status-label.ts:
    @Property({ type: Boolean })
    good = false;
--
components/ak-status-label.ts:
    @Property({ type: Boolean })
    compact = false;
--
elements/CodeMirror.ts:
    @Property({ type: Boolean })
    readOnly = false;
--
elements/buttons/ModalButton.ts:
    @Property({ type: Boolean })
    open = false;
--
elements/EmptyState.ts:
    @Property({ type: Boolean })
    fullHeight = false;
--
elements/Tabs.ts:
    @Property({ type: Boolean })
    vertical = false;
--
elements/ak-checkbox-group/ak-checkbox-group.ts:
    @Property({ type: Boolean })
    required = false;
--
elements/Label.ts:
    @Property({ type: Boolean })
    compact = false;
--
elements/forms/FormGroup.ts:
    @Property({ type: Boolean, reflect: true })
    expanded = false;
--
elements/Expand.ts:
    @Property({ type: Boolean })
    expanded = false;
--
elements/forms/HorizontalFormElement.ts:
    @Property({ type: Boolean })
    required = false;
--
elements/forms/HorizontalFormElement.ts:
    @Property({ type: Boolean })
    slugMode = false;
--
elements/forms/SearchSelect/ak-portal.ts:
    @Property({ type: Boolean, reflect: true })
    open = false;
--
elements/Alert.ts:
    @Property({ type: Boolean })
    inline = false;
--
elements/forms/SearchSelect/ak-search-select-view.ts:
    @Property({ type: Boolean, reflect: true })
    open = false;
--
elements/forms/SearchSelect/ak-search-select-view.ts:
    @Property({ type: Boolean })
    blankable = false;
--
elements/sidebar/SidebarItem.ts:
    @Property({ type: Boolean })
    expanded = false;
--
admin/stages/StageWizard.ts:
    @Property({ type: Boolean })
    showBindingPage = false;
--
elements/forms/FormElement.ts:
    @Property({ type: Boolean })
    required = false;
--
admin/common/ak-flow-search/FlowSearch.ts:
    @Property({ type: Boolean })
    required?: boolean = false;
--
admin/applications/ProviderSelectModal.ts:
    @Property({ type: Boolean })
    backchannel = false;
--
elements/forms/SearchSelect/SearchSelect.ts:
    @Property({ type: Boolean })
    blankable = false;
--
admin/applications/components/ak-provider-search-input.ts:
    @Property({ type: Boolean })
    required = false;
--
admin/applications/components/ak-provider-search-input.ts:
    @Property({ type: Boolean })
    blankable = false;
--
admin/applications/components/ak-backchannel-input.ts:
    @Property({ type: Boolean })
    required = false;
--
admin/policies/PolicyWizard.ts:
    @Property({ type: Boolean })
    showBindingPage = false;
```

The attribute 'required' is an HTML native, and is false by default.

Here are all the change pairs around HTML attrbutes:

```
$ git diff | rg -A 1 '\?(backchannel|blankable|checked|compact|expanded|fullHeight|good|inline|open|readOnly|required|showBindingPage|slugMode|vertical)\b'

-                ?required=${true}
+                required

-                    <ak-provider-select-table ?backchannel=${true} .confirm=${this.confirm}>
+                    <ak-provider-select-table backchannel .confirm=${this.confirm}>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${false}

-                    ?required=${true}
+                    required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                                  ?blankable=${true}
+                                  blankable

-                        ?required=${true}
+                        required

-                ?blankable=${true}
+                blankable

-                ?blankable=${true}
+                blankable

-            ?required=${true}
+            required

-            ?required=${true}
+            required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
+        return html` <ak-form-element-horizontal label=${msg("Name")} name="name" required>

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    ?blankable=${true}
+                    blankable

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Severity")} ?required=${true} name="severity">
+            <ak-form-element-horizontal label=${msg("Severity")} required name="severity">

-                        ?showBindingPage=${true}
+                        showBindingPage

-                ?showBindingPage=${true}
+                showBindingPage

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Title")} ?required=${true} name="title">
+            <ak-form-element-horizontal label=${msg("Title")} required name="title">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            ?required=${true}
+            required

-            <ak-form-element-horizontal label=${msg("Stage")} ?required=${true} name="stage">
+            <ak-form-element-horizontal label=${msg("Stage")} required name="stage">

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    ?blankable=${true}
+                    blankable

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("Type")} required name="type">

-                    ?blankable=${true}
+                    blankable

-                        <ak-label color=${PFColor.Green} ?compact=${true}>
+                        <ak-label color=${PFColor.Green} compact>

-                            ? html`<ak-label color=${PFColor.Red} ?compact=${true}
+                            ? html`<ak-label color=${PFColor.Red} compact

-                            : html`<ak-label color=${PFColor.Green} ?compact=${true}
+                            : html`<ak-label color=${PFColor.Green} compact

-                    ? html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    ? html`<ak-label color=${PFColor.Orange} compact>

-                    : html`<ak-label color=${PFColor.Green} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Green} compact>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Docker URL")} ?required=${true} name="url">
+            <ak-form-element-horizontal label=${msg("Docker URL")} required name="url">

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?showBindingPage=${true}
+                        showBindingPage

-                      ?showBindingPage=${true}
+                      showBindingPage

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-            <ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout">
+            <ak-form-element-horizontal label=${msg("Timeout")} required name="timeout">

-                    ? html`<ak-label color=${PFColor.Green} ?compact=${true}>
+                    ? html`<ak-label color=${PFColor.Green} compact>

-                    : html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Orange} compact>

-        return html`<ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
+        return html`<ak-form-element-horizontal label=${msg("User")} required name="user">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                      ?readOnly=${true}
+                      readOnly

-            return html`<ak-empty-state loading ?fullHeight=${true}></ak-empty-state>`;
+            return html`<ak-empty-state loading fullHeight></ak-empty-state>`;

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                    ?required=${true}
+                    required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-            ?required=${true}
+            required

-                    ?required=${true}
+                    required

-                                        ?blankable=${true}
+                                        blankable

-            <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
+            <ak-form-element-horizontal label=${msg("Name")} name="name" required>

-            <ak-form-element-horizontal label=${msg("Protocol")} ?required=${true} name="protocol">
+            <ak-form-element-horizontal label=${msg("Protocol")} required name="protocol">

-            <ak-form-element-horizontal label=${msg("Host")} name="host" ?required=${true}>
+            <ak-form-element-horizontal label=${msg("Host")} name="host" required>

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                    ?required=${false}

-                        ?blankable=${true}
+                        blankable

-                        ?blankable=${true}
+                        blankable

-        return html`<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html`<ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                                      ?readOnly=${true}
+                                      readOnly

-                                    ?blankable=${true}
+                                    blankable

-        return html`<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html`<ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    : html`<ak-label color=${PFColor.Orange} ?compact=${true}>
+                    : html`<ak-label color=${PFColor.Orange} compact>

-                <ak-label color=${PFColor.Grey} ?compact=${true}> ${msg("Built-in")}</ak-label>
+                <ak-label color=${PFColor.Grey} compact> ${msg("Built-in")}</ak-label>

-            return html`<ak-empty-state loading ?fullHeight=${true}></ak-empty-state>`;
+            return html`<ak-empty-state loading fullHeight></ak-empty-state>`;

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${false}>
+            <ak-form-group>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                            ?blankable=${true}
+                            blankable

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                ?required=${true}
+                required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-                        ?required=${true}
+                        required

-                                ?readOnly=${true}
+                                readOnly

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Slug")} ?required=${true} name="slug">
+            <ak-form-element-horizontal label=${msg("Slug")} required name="slug">

-            <ak-form-group ?expanded=${true}>
+            <ak-form-group expanded>

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                <ak-form-element-horizontal label=${msg("SMTP Host")} ?required=${true} name="host">
+                <ak-form-element-horizontal label=${msg("SMTP Host")} required name="host">

-                <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
+                <ak-form-element-horizontal label=${msg("SMTP Port")} required name="port">

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                ?required=${true}
+                required

-                    ?blankable=${true}
+                    blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        <ak-alert ?inline=${true}>
+                        <ak-alert inline>

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                    <ak-form-element-horizontal label=${msg("Mode")} ?required=${true} name="mode">
+                    <ak-form-element-horizontal label=${msg("Mode")} required name="mode">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                <ak-form-element-horizontal label=${msg("SMTP Host")} ?required=${true} name="host">
+                <ak-form-element-horizontal label=${msg("SMTP Host")} required name="host">

-                <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
+                <ak-form-element-horizontal label=${msg("SMTP Port")} required name="port">

-                    ?required=${true}
+                    required

-                    ?required=${true}
+                    required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                ?slugMode=${true}
+                slugMode

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Expires")} ?required=${true} name="expires">
+            <ak-form-element-horizontal label=${msg("Expires")} required name="expires">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                            ?blankable=${true}
+                            blankable

-                        ?required=${true}
+                        required

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Field Key")} ?required=${true} name="fieldKey">
+            <ak-form-element-horizontal label=${msg("Field Key")} required name="fieldKey">

-            <ak-form-element-horizontal label=${msg("Label")} ?required=${true} name="label">
+            <ak-form-element-horizontal label=${msg("Label")} required name="label">

-            <ak-form-element-horizontal label=${msg("Type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("Type")} required name="type">

-            <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
+            <ak-form-element-horizontal label=${msg("Order")} required name="order">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Source")} ?required=${true} name="source">
+            <ak-form-element-horizontal label=${msg("Source")} required name="source">

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                        ?required=${true}
+                        required

-                        <ak-alert ?inline=${true}>
+                        <ak-alert inline>

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-                        ?required=${true}
+                        required

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-            <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+            <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                            ?blankable=${true}
+                            blankable

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("User")} ?required=${true} name="user">
+            <ak-form-element-horizontal label=${msg("User")} required name="user">

-            <ak-form-element-horizontal label=${msg("Intent")} ?required=${true} name="intent">
+            <ak-form-element-horizontal label=${msg("Intent")} required name="intent">

-                ?required=${true}
+                required

-                    <input class="pf-c-switch__input" type="checkbox" ?checked=${true} />
+                    <input class="pf-c-switch__input" type="checkbox" checked />

-                    <input class="pf-c-switch__input" type="checkbox" ?checked=${true} />
+                    <input class="pf-c-switch__input" type="checkbox" checked />

-                ?required=${true}
+                required

-            <ak-form-element-horizontal label=${msg("User type")} ?required=${true} name="type">
+            <ak-form-element-horizontal label=${msg("User type")} required name="type">

-            <ak-form-element-horizontal label=${msg("Path")} ?required=${true} name="path">
+            <ak-form-element-horizontal label=${msg("Path")} required name="path">

-            ?required=${true}
+            required

-            ?required=${true}
+            required

-            <ak-tabs pageIdentifier="userCredentialsTokens" ?vertical=${true}>
+            <ak-tabs pageIdentifier="userCredentialsTokens" vertical>

-                <ak-status-label ?good=${true}></ak-status-label>
+                <ak-status-label good></ak-status-label>

-                    ?open=${true}
+                    open

-                ?blankable=${true}
+                blankable

-                <ak-tabs ?vertical="${true}">
+                <ak-tabs vertical>

-        return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
+        return html` <ak-form-element-horizontal label=${msg("Name")} required name="name">

-                ?required=${true}
+                required

```

The following issues are the `true` by default Booleans.  As mentioned, these are **not addressed** by this PR.

```
elements/table/Table.ts::
    @Property({ type: Boolean })
    paginated = true;

elements/forms/ModalForm.ts::
    @Property({ type: Boolean })
    closeAfterSuccessfulSubmit = true;

elements/forms/ModalForm.ts::
    @Property({ type: Boolean })
    showSubmitButton = true;

elements/CodeMirror.ts::
    @Property({ type: Boolean })
    parseValue = true;

elements/LoadingOverlay.ts::
    @Property({ type: Boolean })
    loading = true;

admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts::
    @Property({ type: Boolean })
    showConfigurationStages = true;

elements/user/sources/SourceSettings.ts::
    @Property({ type: Boolean })
    canConnect = true;

admin/outposts/OutpostHealthSimple.ts::
    @Property({ attribute: false })
    showVersion = true;

elements/wizard/Wizard.ts::
    @Property({ type: Boolean })
    canCancel = true;

elements/wizard/Wizard.ts::
    @Property({ type: Boolean })
    canBack = true;
```
Copy link

netlify bot commented May 23, 2025

Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit 3fccf2b
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/682fc81df5a1f7000813a770
😎 Deploy Preview https://deploy-preview-14662--authentik-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

netlify bot commented May 23, 2025

Deploy Preview for authentik-docs canceled.

Name Link
🔨 Latest commit 3fccf2b
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/682fc81da3e024000807ec13

Copy link

codecov bot commented May 23, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
1806 1 1805 2
View the full list of 1 ❄️ flaky tests
tests.e2e.test_source_saml.TestSourceSAML::test_idp_post_auto_enroll_auth

Flake rate in main: 20.83% (Passed 19 times, Failed 5 times)

Stack Traces | 229s run time
self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:329: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-source-pre-authentication.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Source pre-authentication flow\nentries:\n- attrs:\n    designation: stage_c...    authentication: none\n  identifiers:\n    slug: default-source-pre-authentication\n  model: authentik_flows.flow\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint(
        "default/flow-default-source-authentication.yaml",
        "default/flow-default-source-enrollment.yaml",
        "default/flow-default-source-pre-authentication.yaml",
    )
    def test_idp_post_auto_enroll_auth(self):
        """test SAML Source With post binding (auto redirect)"""
        # Bootstrap all needed objects
        authentication_flow = Flow.objects.get(slug="default-source-authentication")
        enrollment_flow = Flow.objects.get(slug="default-source-enrollment")
        pre_authentication_flow = Flow.objects.get(slug="default-source-pre-authentication")
        keypair = CertificateKeyPair.objects.create(
            name=generate_id(),
            certificate_data=IDP_CERT,
            key_data=IDP_KEY,
        )
    
        source = SAMLSource.objects.create(
            name=generate_id(),
            slug=self.slug,
            authentication_flow=authentication_flow,
            enrollment_flow=enrollment_flow,
            pre_authentication_flow=pre_authentication_flow,
            issuer="entity-id",
            sso_url=f"http://{self.host}:.../saml2/idp/SSOService.php",
            binding_type=SAMLBindingTypes.POST_AUTO,
            signing_kp=keypair,
        )
        ident_stage = IdentificationStage.objects.first()
        ident_stage.sources.set([source])
        ident_stage.save()
    
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
        self.wait.until(ec.presence_of_element_located((By.ID, "username")))
        self.driver.find_element(By.ID, "username").send_keys("user1")
        self.driver.find_element(By.ID, "password").send_keys("user1pass")
        self.driver.find_element(By.ID, "password").send_keys(Keys.ENTER)
    
        # Wait until we're logged in
        self.wait_for_url(self.if_user_url())
    
        self.assert_user(
            User.objects.exclude(username="akadmin")
            .exclude(username__startswith="ak-outpost")
            .exclude_anonymous()
            .exclude(pk=self.user.pk)
            .first()
        )
    
        # Clear all cookies and log in again
        self.driver.delete_all_cookies()
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
>       self.wait.until(ec.presence_of_element_located((By.ID, "username")))

tests/e2e/test_source_saml.py:414: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.support.wait.WebDriverWait (session="93b97c93e4549f686159ef6c8cb8457e")>
method = <function presence_of_element_located.<locals>._predicate at 0x7ffa6f0b0180>
message = ''

    def until(self, method: Callable[[D], Union[Literal[False], T]], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Parameters:
        -----------
        method: callable(WebDriver)
            - A callable object that takes a WebDriver instance as an argument.
    
        message: str
            - Optional message for :exc:`TimeoutException`
    
        Return:
        -------
        object: T
            - The result of the last call to `method`
    
        Raises:
        -------
        TimeoutException
            - If 'method' does not return a truthy value within the WebDriverWait
            object's timeout
    
        Example:
        --------
        >>> from selenium.webdriver.common.by import By
        >>> from selenium.webdriver.support.ui import WebDriverWait
        >>> from selenium.webdriver.support import expected_conditions as EC
    
        # Wait until an element is visible on the page
        >>> wait = WebDriverWait(driver, 10)
        >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
        >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, "screen", None)
                stacktrace = getattr(exc, "stacktrace", None)
            if time.monotonic() > end_time:
                break
            time.sleep(self._poll)
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message: 
E       Stacktrace:
E       #0 0x557cdadcd75a <unknown>
E       #1 0x557cda8700a0 <unknown>
E       #2 0x557cda8c19b0 <unknown>
E       #3 0x557cda8c1ba1 <unknown>
E       #4 0x557cda90fea4 <unknown>
E       #5 0x557cda8e73cd <unknown>
E       #6 0x557cda90d2a0 <unknown>
E       #7 0x557cda8e7173 <unknown>
E       #8 0x557cda8b3d4b <unknown>
E       #9 0x557cda8b49b1 <unknown>
E       #10 0x557cdad9290b <unknown>
E       #11 0x557cdad9680a <unknown>
E       #12 0x557cdad7a662 <unknown>
E       #13 0x557cdad97394 <unknown>
E       #14 0x557cdad5f49f <unknown>
E       #15 0x557cdadbb538 <unknown>
E       #16 0x557cdadbb716 <unknown>
E       #17 0x557cdadcc5c6 <unknown>
E       #18 0x7f48973aaaa4 <unknown>
E       #19 0x7f4897437a34 __clone

.venv/lib/python3.13.../webdriver/support/wait.py:146: TimeoutException

During handling of the above exception, another exception occurred:

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:329: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-source-pre-authentication.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Source pre-authentication flow\nentries:\n- attrs:\n    designation: stage_c...    authentication: none\n  identifiers:\n    slug: default-source-pre-authentication\n  model: authentik_flows.flow\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint(
        "default/flow-default-source-authentication.yaml",
        "default/flow-default-source-enrollment.yaml",
        "default/flow-default-source-pre-authentication.yaml",
    )
    def test_idp_post_auto_enroll_auth(self):
        """test SAML Source With post binding (auto redirect)"""
        # Bootstrap all needed objects
        authentication_flow = Flow.objects.get(slug="default-source-authentication")
        enrollment_flow = Flow.objects.get(slug="default-source-enrollment")
        pre_authentication_flow = Flow.objects.get(slug="default-source-pre-authentication")
        keypair = CertificateKeyPair.objects.create(
            name=generate_id(),
            certificate_data=IDP_CERT,
            key_data=IDP_KEY,
        )
    
        source = SAMLSource.objects.create(
            name=generate_id(),
            slug=self.slug,
            authentication_flow=authentication_flow,
            enrollment_flow=enrollment_flow,
            pre_authentication_flow=pre_authentication_flow,
            issuer="entity-id",
            sso_url=f"http://{self.host}:.../saml2/idp/SSOService.php",
            binding_type=SAMLBindingTypes.POST_AUTO,
            signing_kp=keypair,
        )
        ident_stage = IdentificationStage.objects.first()
        ident_stage.sources.set([source])
        ident_stage.save()
    
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
        self.wait.until(ec.presence_of_element_located((By.ID, "username")))
        self.driver.find_element(By.ID, "username").send_keys("user1")
        self.driver.find_element(By.ID, "password").send_keys("user1pass")
        self.driver.find_element(By.ID, "password").send_keys(Keys.ENTER)
    
        # Wait until we're logged in
        self.wait_for_url(self.if_user_url())
    
        self.assert_user(
            User.objects.exclude(username="akadmin")
            .exclude(username__startswith="ak-outpost")
            .exclude_anonymous()
            .exclude(pk=self.user.pk)
            .first()
        )
    
        # Clear all cookies and log in again
        self.driver.delete_all_cookies()
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
>       self.wait.until(ec.presence_of_element_located((By.ID, "username")))

tests/e2e/test_source_saml.py:414: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.support.wait.WebDriverWait (session="0e54a6df4ca3af0ca0417ff70577efff")>
method = <function presence_of_element_located.<locals>._predicate at 0x7ffa6e766660>
message = ''

    def until(self, method: Callable[[D], Union[Literal[False], T]], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Parameters:
        -----------
        method: callable(WebDriver)
            - A callable object that takes a WebDriver instance as an argument.
    
        message: str
            - Optional message for :exc:`TimeoutException`
    
        Return:
        -------
        object: T
            - The result of the last call to `method`
    
        Raises:
        -------
        TimeoutException
            - If 'method' does not return a truthy value within the WebDriverWait
            object's timeout
    
        Example:
        --------
        >>> from selenium.webdriver.common.by import By
        >>> from selenium.webdriver.support.ui import WebDriverWait
        >>> from selenium.webdriver.support import expected_conditions as EC
    
        # Wait until an element is visible on the page
        >>> wait = WebDriverWait(driver, 10)
        >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
        >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, "screen", None)
                stacktrace = getattr(exc, "stacktrace", None)
            if time.monotonic() > end_time:
                break
            time.sleep(self._poll)
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message: 
E       Stacktrace:
E       #0 0x561a32a0f75a <unknown>
E       #1 0x561a324b20a0 <unknown>
E       #2 0x561a325039b0 <unknown>
E       #3 0x561a32503ba1 <unknown>
E       #4 0x561a32551ea4 <unknown>
E       #5 0x561a325293cd <unknown>
E       #6 0x561a3254f2a0 <unknown>
E       #7 0x561a32529173 <unknown>
E       #8 0x561a324f5d4b <unknown>
E       #9 0x561a324f69b1 <unknown>
E       #10 0x561a329d490b <unknown>
E       #11 0x561a329d880a <unknown>
E       #12 0x561a329bc662 <unknown>
E       #13 0x561a329d9394 <unknown>
E       #14 0x561a329a149f <unknown>
E       #15 0x561a329fd538 <unknown>
E       #16 0x561a329fd716 <unknown>
E       #17 0x561a32a0e5c6 <unknown>
E       #18 0x7f8596ef2aa4 <unknown>
E       #19 0x7f8596f7fa34 __clone

.venv/lib/python3.13.../webdriver/support/wait.py:146: TimeoutException

During handling of the above exception, another exception occurred:

self = <unittest.case._Outcome object at 0x7ffa6f2f0550>
test_case = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.13.3........./x64/lib/python3.13/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
result = <TestCaseFunction test_idp_post_auto_enroll_auth>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.13.3........./x64/lib/python3.13/unittest/case.py:651: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
method = <bound method TestSourceSAML.test_idp_post_auto_enroll_auth of <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.13.3........./x64/lib/python3.13/unittest/case.py:606: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
                raise exc
            logger.debug("Retrying on error", exc=exc, test=self)
            self.tearDown()
            self._post_teardown()
            self._pre_setup()
            self.setUp()
>           return wrapper(self, *args, **kwargs)

tests/e2e/utils.py:342: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
                raise exc
            logger.debug("Retrying on error", exc=exc, test=self)
            self.tearDown()
            self._post_teardown()
            self._pre_setup()
            self.setUp()
>           return wrapper(self, *args, **kwargs)

tests/e2e/utils.py:342: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
            return func(self, *args, **kwargs)
    
        except tuple(exceptions) as exc:
            count += 1
            if count > max_retires:
                logger.debug("Exceeded retry count", exc=exc, test=self)
    
>               raise exc

tests/e2e/utils.py:336: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>
args = (), kwargs = {}

    @wraps(func)
    def wrapper(self: TransactionTestCase, *args, **kwargs):
        """Run test again if we're below max_retries, including tearDown and
        setUp. Otherwise raise the error"""
        nonlocal count
        try:
>           return func(self, *args, **kwargs)

tests/e2e/utils.py:329: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-invalidation-flow.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Invalidation flow\nentries:\n- attrs:\n    designation: invalidation\n    na...0\n    stage: !KeyOf default-invalidation-logout\n    target: !KeyOf flow\n  model: authentik_flows.flowstagebinding\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (<tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>,)
kwargs = {}, file = 'default/flow-default-source-pre-authentication.yaml'
content = 'version: 1\nmetadata:\n  name: Default - Source pre-authentication flow\nentries:\n- attrs:\n    designation: stage_c...    authentication: none\n  identifiers:\n    slug: default-source-pre-authentication\n  model: authentik_flows.flow\n'

    @wraps(func)
    def wrapper(*args, **kwargs):
        for file in files:
            content = BlueprintInstance(path=file).retrieve()
            Importer.from_string(content).apply()
>       return func(*args, **kwargs)

.../blueprints/tests/__init__.py:25: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <tests.e2e.test_source_saml.TestSourceSAML testMethod=test_idp_post_auto_enroll_auth>

    @retry()
    @apply_blueprint(
        "default/flow-default-authentication-flow.yaml",
        "default/flow-default-invalidation-flow.yaml",
    )
    @apply_blueprint(
        "default/flow-default-source-authentication.yaml",
        "default/flow-default-source-enrollment.yaml",
        "default/flow-default-source-pre-authentication.yaml",
    )
    def test_idp_post_auto_enroll_auth(self):
        """test SAML Source With post binding (auto redirect)"""
        # Bootstrap all needed objects
        authentication_flow = Flow.objects.get(slug="default-source-authentication")
        enrollment_flow = Flow.objects.get(slug="default-source-enrollment")
        pre_authentication_flow = Flow.objects.get(slug="default-source-pre-authentication")
        keypair = CertificateKeyPair.objects.create(
            name=generate_id(),
            certificate_data=IDP_CERT,
            key_data=IDP_KEY,
        )
    
        source = SAMLSource.objects.create(
            name=generate_id(),
            slug=self.slug,
            authentication_flow=authentication_flow,
            enrollment_flow=enrollment_flow,
            pre_authentication_flow=pre_authentication_flow,
            issuer="entity-id",
            sso_url=f"http://{self.host}:.../saml2/idp/SSOService.php",
            binding_type=SAMLBindingTypes.POST_AUTO,
            signing_kp=keypair,
        )
        ident_stage = IdentificationStage.objects.first()
        ident_stage.sources.set([source])
        ident_stage.save()
    
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
        self.wait.until(ec.presence_of_element_located((By.ID, "username")))
        self.driver.find_element(By.ID, "username").send_keys("user1")
        self.driver.find_element(By.ID, "password").send_keys("user1pass")
        self.driver.find_element(By.ID, "password").send_keys(Keys.ENTER)
    
        # Wait until we're logged in
        self.wait_for_url(self.if_user_url())
    
        self.assert_user(
            User.objects.exclude(username="akadmin")
            .exclude(username__startswith="ak-outpost")
            .exclude_anonymous()
            .exclude(pk=self.user.pk)
            .first()
        )
    
        # Clear all cookies and log in again
        self.driver.delete_all_cookies()
        self.driver.get(self.live_server_url)
    
        flow_executor = self.get_shadow_root("ak-flow-executor")
        identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)
        wait = WebDriverWait(identification_stage, self.wait_timeout)
    
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button")
            )
        )
        identification_stage.find_element(
            By.CSS_SELECTOR, ".pf-c-login__main-footer-links-item > button"
        ).click()
    
        # Now we should be at the IDP, wait for the username field
>       self.wait.until(ec.presence_of_element_located((By.ID, "username")))

tests/e2e/test_source_saml.py:414: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <selenium.webdriver.support.wait.WebDriverWait (session="85d4997fdc67b864ebedd71ff30de4bf")>
method = <function presence_of_element_located.<locals>._predicate at 0x7ffa6eb60360>
message = ''

    def until(self, method: Callable[[D], Union[Literal[False], T]], message: str = "") -> T:
        """Wait until the method returns a value that is not False.
    
        Calls the method provided with the driver as an argument until the
        return value does not evaluate to ``False``.
    
        Parameters:
        -----------
        method: callable(WebDriver)
            - A callable object that takes a WebDriver instance as an argument.
    
        message: str
            - Optional message for :exc:`TimeoutException`
    
        Return:
        -------
        object: T
            - The result of the last call to `method`
    
        Raises:
        -------
        TimeoutException
            - If 'method' does not return a truthy value within the WebDriverWait
            object's timeout
    
        Example:
        --------
        >>> from selenium.webdriver.common.by import By
        >>> from selenium.webdriver.support.ui import WebDriverWait
        >>> from selenium.webdriver.support import expected_conditions as EC
    
        # Wait until an element is visible on the page
        >>> wait = WebDriverWait(driver, 10)
        >>> element = wait.until(EC.visibility_of_element_located((By.ID, "exampleId")))
        >>> print(element.text)
        """
        screen = None
        stacktrace = None
    
        end_time = time.monotonic() + self._timeout
        while True:
            try:
                value = method(self._driver)
                if value:
                    return value
            except self._ignored_exceptions as exc:
                screen = getattr(exc, "screen", None)
                stacktrace = getattr(exc, "stacktrace", None)
            if time.monotonic() > end_time:
                break
            time.sleep(self._poll)
>       raise TimeoutException(message, screen, stacktrace)
E       selenium.common.exceptions.TimeoutException: Message: 
E       Stacktrace:
E       #0 0x55911796275a <unknown>
E       #1 0x5591174050a0 <unknown>
E       #2 0x5591174569b0 <unknown>
E       #3 0x559117456ba1 <unknown>
E       #4 0x5591174a4ea4 <unknown>
E       #5 0x55911747c3cd <unknown>
E       #6 0x5591174a22a0 <unknown>
E       #7 0x55911747c173 <unknown>
E       #8 0x559117448d4b <unknown>
E       #9 0x5591174499b1 <unknown>
E       #10 0x55911792790b <unknown>
E       #11 0x55911792b80a <unknown>
E       #12 0x55911790f662 <unknown>
E       #13 0x55911792c394 <unknown>
E       #14 0x5591178f449f <unknown>
E       #15 0x559117950538 <unknown>
E       #16 0x559117950716 <unknown>
E       #17 0x5591179615c6 <unknown>
E       #18 0x7f92448c3aa4 <unknown>
E       #19 0x7f9244950a34 __clone

.venv/lib/python3.13.../webdriver/support/wait.py:146: TimeoutException

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@property({
type: Object,
attribute: false,
reflect: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot reflect an Object.

Amazingly, this is the only change that's more or less unrelated to the Booleans issue. Everything else is just... getting it right. 😉

@@ -20,7 +20,7 @@ export class ProviderSelectModal extends TableModal<Provider> {
}

@property({ type: Boolean })
backchannel?: boolean;
backchannel = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few places left Booleans as undefined. That's... not cool. :-). Boolean attributes should always have a default.

@kensternberg-authentik kensternberg-authentik marked this pull request as ready for review May 23, 2025 01:03
@kensternberg-authentik kensternberg-authentik requested a review from a team as a code owner May 23, 2025 01:03
Copy link
Contributor

authentik PR Installation instructions

Instructions for docker-compose

Add the following block to your .env file:

AUTHENTIK_IMAGE=ghcr.io/goauthentik/dev-server
AUTHENTIK_TAG=gh-469e8d88f69c018f1d42dd1d952630b95060ff70
AUTHENTIK_OUTPOSTS__CONTAINER_IMAGE_BASE=ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s

Afterwards, run the upgrade commands from the latest release notes.

Instructions for Kubernetes

Add the following block to your values.yml file:

authentik:
    outposts:
        container_image_base: ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s
global:
    image:
        repository: ghcr.io/goauthentik/dev-server
        tag: gh-469e8d88f69c018f1d42dd1d952630b95060ff70

Afterwards, run the upgrade commands from the latest release notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants