mirror of
https://github.com/goauthentik/authentik
synced 2026-05-05 14:42:22 +02:00
Compare commits
7 Commits
api--set-A
...
web/docs/u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13e79b4793 | ||
|
|
4f16bed6a5 | ||
|
|
8fb3569333 | ||
|
|
471493a118 | ||
|
|
8c27b7db26 | ||
|
|
cea8f1624a | ||
|
|
d48c3382dd |
367
web/README.md
367
web/README.md
@@ -1,112 +1,303 @@
|
||||
# authentik WebUI
|
||||
# The authentik WebUI
|
||||
|
||||
This is the default UI for the authentik server. The documentation is going to be a little sparse
|
||||
for awhile, but at least let's get started.
|
||||
The authetik WebUI is the default UI for the authentik Single Sign-on (SSO) server. It consists of
|
||||
three primary applications:
|
||||
|
||||
# The Theory of the authentik UI
|
||||
- Flow: The transaction-driven, customizable interface for logging in and all other workflow
|
||||
activities
|
||||
- User: The user's library of applications to which they have access, and user settings such as
|
||||
configuring their MFA and email address, viewing their current sessions, and more
|
||||
- Admin: The system administration tool for defining applications, providers, policies, and
|
||||
everything else
|
||||
|
||||
In Peter Naur's 1985 essay [Programming as Theory
|
||||
Building](https://pages.cs.wisc.edu/~remzi/Naur.pdf), programming is described as creating a mental
|
||||
model of how a program _should_ run, then writing the code to test if the program _can_ run that
|
||||
way.
|
||||
Each of these is a [thin client] application around data objects provided by and transactions
|
||||
available with the authentik SSO server. Business logic and validation is provided by the server.
|
||||
|
||||
The mental model for the authentik UI is straightforward. There are five "applications" within the
|
||||
UI, each with its own base URL, router, and responsibilities, and each application needs as many as
|
||||
three contexts in which to run.
|
||||
The authentik SSO server is written in Python and Django.
|
||||
|
||||
The three contexts corresponds to objects in the API's `model` section, so let's use those names.
|
||||
> - [thin client](https://en.wikipedia.org/wiki/Thin_client): In this case, we mean "a front end to
|
||||
> show the data where the server does all the heavy lifting."
|
||||
|
||||
- The root `Config`. The root configuration object of the server, containing mostly caching and
|
||||
error reporting information. This is misleading, however; the `Config` object contains some user
|
||||
information, specifically a list of permissions the current user (or "no user") has.
|
||||
- The root `CurrentTenant`. This describes the `Brand` information UIs should use, such as themes,
|
||||
logos, favicon, and specific default flows for logging in, logging out, and recovering a user
|
||||
password.
|
||||
- The current `SessionUser`, the person logged in: username, display name, and various states.
|
||||
(Note: the authentik server permits administrators to "impersonate" any other user in order to
|
||||
debug their authentication experience. If impersonation is active, the `user` field reflects that
|
||||
user, but it also includes a field, `original`, with the administrator's information.)
|
||||
## Project setup
|
||||
|
||||
(There is a fourth context object, Version, but its use is limited to displaying version information
|
||||
and checking for upgrades. Just be aware that you will see it, but you will probably never interact
|
||||
with it.)
|
||||
If you have cloned the authentik repository, the [developer docs] are where you go to perform the
|
||||
initial set-up and install. This sequence will get you up and running in the usual course of events.
|
||||
|
||||
There are five applications. Two (`loading` and `api-browser`) are trivial applications whose
|
||||
insides are provided by third-party libraries (Patternfly and Rapidoc, respectively). The other
|
||||
three are actual applications. The descriptions below are wholly from the view of the user's
|
||||
experience:
|
||||
```
|
||||
$ make install
|
||||
$ make gen-dev-config
|
||||
$ make migrate
|
||||
$ make run-server
|
||||
$ make run-worker
|
||||
```
|
||||
|
||||
- `Flow`: From a given URL, displays a form that requests information from the user to accomplish a
|
||||
task. Some tasks require the user to be logged in, but many (such as logging in itself!)
|
||||
obviously do not.
|
||||
- `User`: Provides the user with access to the applications they can access, plus a few user
|
||||
settings.
|
||||
- `Admin`: Provides someone with super-user permissions access to the administrative functions of
|
||||
the authentik server.
|
||||
We recommend that you run `run-server` and `run-worker` in different terminals or different sessions
|
||||
under tmux or screen or a similar terminal multiplexer.
|
||||
|
||||
**Mental Model**
|
||||
The WebUI runs in this folder (`./web` under the project root). You can put the WebUI into hot
|
||||
reload by running, from this folder,
|
||||
|
||||
- Upon initialization, _every_ authentik UI application fetches `Config` and `CurrentTenant`. `User`
|
||||
and `Admin` will also attempt to load the `SessionUser`; if there is none, the user is kicked out
|
||||
to the `Flow` for logging into authentik itself.
|
||||
- `Config`, `CurrentTenant`, and `SessionUser`, are provided by the `@goauthentik/api` application,
|
||||
not by the codebase under `./web`. (Where you are now).
|
||||
- `Flow`, `User`, and `Admin` are all called `Interfaces` and are found in
|
||||
`./web/src/flow/FlowInterface`, `./web/src/user/UserInterface`, `./web/src/admin/AdminInterface`,
|
||||
respectively.
|
||||
```
|
||||
$ npm run watch
|
||||
```
|
||||
|
||||
Inside each of these you will find, in a hierarchal order:
|
||||
## Front-End Architecture
|
||||
|
||||
- The context layer described above
|
||||
- A theme managing layer
|
||||
- The orchestration layer:
|
||||
- web socket handler for server-generated events
|
||||
- The router
|
||||
- Individual routes for each vertical slice and its relationship to other objects:
|
||||
### The Django side
|
||||
|
||||
Each slice corresponds to an object table on the server, and each slice _usually_ consists of the
|
||||
following:
|
||||
The authentik web-based applications are delivered via a Django server. The server delivers an HTML
|
||||
template that executes a sequence of startup operations:
|
||||
|
||||
- A paginated collection display, usually using the `Table` foundation (found in
|
||||
`./web/src/elements/Table`)
|
||||
- The ability to view an individual object from the collection, which you may be able to:
|
||||
- Edit
|
||||
- Delete
|
||||
- A form for creating a new object
|
||||
- Tabs showing that object's relationship to other objects
|
||||
- Interactive elements for changing or deleting those relationships, or creating new ones.
|
||||
- The ability to create new objects with which to have that relationship, if they're not part of
|
||||
the core objects (such as User->MFA authenticator apps, since the latter is not a "core" object
|
||||
and has no tab of its own).
|
||||
- Assigns the language code and `data-theme="light|dark"` settings to the `html` tag. Assigns the
|
||||
favicon links. Creates a `window.authentik` object and assigns a variety of site-wide
|
||||
configuration details to it. Probes the a priority decision list of sources of the user's
|
||||
light/dark preferences and assigns that to the `Document.dataset`
|
||||
- Begins loading the interface root bundle. The script is of `type="module"`; it will not be
|
||||
executed until the initial HTML has been completely parsed.
|
||||
- Loads the site-wide standard CSS.
|
||||
- Injects any CSS overrides specified in the customer's `brand` settings
|
||||
- Loads any necessary JavaScript polyfills
|
||||
- Dispatches any initial messages to the notification handler
|
||||
- Sets any custom `<meta>` settings specified by the server
|
||||
- Provides the initial HTML scaffolding to launch an interface.
|
||||
|
||||
We are still a bit "all over the place" with respect to sub-units and common units; there are
|
||||
folders `common`, `elements`, and `components`, and ideally they would be:
|
||||
The interface code is mostly the core web component and its responsibilities. This code will be
|
||||
hydrated when the interface root bundle in the second step above is executed and the components are
|
||||
registered with the browser.
|
||||
|
||||
- `common`: non-UI related libraries all of our applications need
|
||||
- `elements`: UI elements shared among multiple applications that do not need context
|
||||
- `components`: UI elements shared among multiple that use one or more context
|
||||
### The Flow interface
|
||||
|
||||
... but at the moment there are some context-sensitive elements, and some UI-related stuff in
|
||||
`common`.
|
||||
The Flow interface has three subsystems:
|
||||
|
||||
# Comments
|
||||
- The Locale Selector: `<ak-locale-select>`
|
||||
- The Flow Inspector: `<ak-flow-inspector>`
|
||||
- The Flow Executor: `<ak-flow-executor>`
|
||||
|
||||
**NOTE:** The comments in this section are for specific changes to this repository that cannot be
|
||||
reliably documented any other way. For the most part, they contain comments related to custom
|
||||
settings in JSON files, which do not support comments.
|
||||
The Flow interface is a single-page application. The Locale Selector and the Inspector are
|
||||
independent buttons that persist on the web page for the duration of a Flow. Either can be disabled
|
||||
and hidden by admin preference. The Locale Selector allows the user to select an alternative locale
|
||||
in which to display text and labels. The [Flow
|
||||
Inspector](https://docs.goauthentik.io/add-secure-apps/flows-stages/flow/inspector/), when enabled,
|
||||
can query the server and then display details about the state of a flow: the accumulated context of
|
||||
the current flow, existing error messages, and expected next steps; it is present to assist with
|
||||
debugging.
|
||||
|
||||
- `tsconfig.json`:
|
||||
- `compilerOptions.useDefineForClassFields: false` is required to make TSC use the "classic" form
|
||||
of field definition when compiling class definitions. Storybook does not handle the ESNext
|
||||
proposed definition mechanism (yet).
|
||||
- `compilerOptions.plugins.ts-lit-plugin.rules.no-unknown-tag-name: "off"`: required to support
|
||||
rapidoc, which exports its tag late.
|
||||
- `compilerOptions.plugins.ts-lit-plugin.rules.no-missing-import: "off"`: lit-analyzer currently
|
||||
does not support path aliases very well, and cannot find the definition files associated with
|
||||
imports using them.
|
||||
- `compilerOptions.plugins.ts-lit-plugin.rules.no-incompatible-type-binding: "warn"`: lit-analyzer
|
||||
does not support generics well when parsing a subtype of `HTMLElement`. As a result, this threw
|
||||
too many errors to be supportable.
|
||||
The Executor is the heart of the system. It executes Flows.
|
||||
|
||||
A _Flow_ in authentik is the workflow that accomplishes a specific SSO-oriented task such as logging
|
||||
in, logging out, or enrolling as a new user, among others.
|
||||
|
||||
The Executor starts by examining the current URL for the `flowSlug`, and sends a request for a
|
||||
_Challenge_ to the server. Upon the response, the Executor loads the corresponding _Stage_: the UI
|
||||
component responsible for showing the challenge to the user. When the user performs the requested
|
||||
action the input is sent to the server, which issues a new Challenge. This Challenge may be the same
|
||||
one with error messages, or the next one in the workflow. This process repeats until the user
|
||||
reaches the end of the Flow, at which point the task is complete or failed.
|
||||
|
||||
The architecture for the Executor is straightforward:
|
||||
|
||||
- The HTML Document
|
||||
- The Locale Selector
|
||||
- The Inspector
|
||||
- The Executor
|
||||
- The current Stage
|
||||
|
||||
A Stage may have interior stages or components. The Identification Stage is the most complex of our
|
||||
stages. It usually shows the Username field, and in some configurations it _can_ show the Password
|
||||
field; in that case, the password component exists to allow the user to "show password". It may also
|
||||
host the Captcha and Passkey stages within, to complete the initial task of determining and
|
||||
validating a user's identity.
|
||||
|
||||
### User and Admin Interfaces
|
||||
|
||||
The architecture of these interfaces is more complex. In both cases, the user is assumed to have
|
||||
logged in and so is said to have a _Session_. The architecture is structured:
|
||||
|
||||
- The HTML Document
|
||||
- The Interface
|
||||
- License: a context handler for the site's enterprise license status
|
||||
- Session: a context handler for the user's current session. This mostly the `user` identity
|
||||
- Version: a context handler for the current version of authentik
|
||||
- Notifications: a context handler for outstanding messages sent from the server to the user
|
||||
- Capabilities: a list of features that the current user may use. List includes "can save
|
||||
reports," "can use debugging feature," "can use enterprise features."
|
||||
- The Application:
|
||||
- Header
|
||||
- Sidebar
|
||||
- Router
|
||||
- CRUD interfaces to features of the system:
|
||||
- Dashboard
|
||||
- Logs
|
||||
- Configurations
|
||||
- Flows, Stages & Policies
|
||||
- Users & Group
|
||||
- IDP Sources
|
||||
- Everything else!
|
||||
|
||||
### Miscellaneous interfaces
|
||||
|
||||
There are three miscellaneous interfaces:
|
||||
|
||||
#### API browser
|
||||
|
||||
A single page application that loads our schema and allows the user to experiment with it. Uses the
|
||||
[RapiDoc](https://rapidocweb.com/) app.
|
||||
|
||||
#### Loading
|
||||
|
||||
The Django application is wrapped in a proxy server for caching and performance; while it is in
|
||||
start-up mode, the proxy serves this page, which just says "The application is loading" with a
|
||||
pretty animation.
|
||||
|
||||
#### SFE: Simplified Flow Executor
|
||||
|
||||
The SFE is a limited version of the Flow Executor written to use [jQuery](https://jquery.com/). It
|
||||
supports only login operations, and is meant for places where the login is embedded in an Office365
|
||||
or MicrosoftTeams settings, as those use Trident (Internet Explorer) for their web-based login.
|
||||
|
||||
## Front-end foundations
|
||||
|
||||
### CSS
|
||||
|
||||
Our current CSS is provided by [Patternfly 4](https://v4-archive.patternfly.org/v4/). There are two
|
||||
different layers of CSS.
|
||||
|
||||
The first is the Global CSS that appears in the `<head>`. This defines the basic look: theme,
|
||||
start-up, reset, and fonts. It also provides the [CSS Custom
|
||||
Properties](https://docs.goauthentik.io/brands/custom-css/) that control the look and feel of the
|
||||
rest of an Interface.
|
||||
|
||||
The second is per-component CSS. This is linked into each component using [Adopted
|
||||
Stylesheets](https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets).
|
||||
|
||||
> This recipe has led to some significant awkwardness. Information from the outside does not pierce
|
||||
> the shadowDOM, so Patternfly-Base is linked into every component just to provide the box model,
|
||||
> reset, basic functionality, and behavioral modifiers. The interior of our components is cluttered
|
||||
> with lots of patternfly classes.
|
||||
|
||||
### Elements
|
||||
|
||||
Elements are custom web components that authentik has written that supply advanced behaviors to
|
||||
common operations, as well as API-independent complex components such as rich drop-downs, dual-pane
|
||||
selectors, toggles, switches, and wizards. At least, that's the idea. We are still untangling.
|
||||
|
||||
### Components
|
||||
|
||||
Components are custom web components that authentik has written that are API-aware and that supply
|
||||
business logic to perform validation, permissioning, and selective display.
|
||||
|
||||
## Adding a new feature (developer's guide)
|
||||
|
||||
As a thin client, the primary task will either be adding a new CRUD vertical or extending and
|
||||
enhancing an existing one. (If the elements, components, API, and so on represent the horizontal
|
||||
layers of an application, a single CRUD task is the "vertical slice" through these.) Our Django
|
||||
application presents collections of objects from which the user may pick one to view, update, or
|
||||
delete.
|
||||
|
||||
The web component in `./elements/table` is used to display, well, tables of components. A new
|
||||
feature begins by inheriting the `Table` class and providing two things: the API call to retrieve
|
||||
the objects, and a method describing a row for the table. This is the retrieval for our Role-Based
|
||||
Access Controls (RBAC).
|
||||
|
||||
```
|
||||
async apiEndpoint(): Promise<PaginatedResponse<Role>> {
|
||||
return new RbacApi(DEFAULT_CONFIG).rbacRolesList({
|
||||
...(await this.defaultEndpointConfig()),
|
||||
managedIsnull: this.hideManaged ? true : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The complete list of APIs available can be found in `node_modules/@goauthentik/api/src/apis`.
|
||||
|
||||
A row returns an array of cells:
|
||||
|
||||
```
|
||||
row(item: Role): SlottedTemplateResult[] {
|
||||
return [
|
||||
html`<a href="#/identity/roles/${item.pk}">${item.name}</a>`,
|
||||
html`<div>
|
||||
<ak-forms-modal>
|
||||
<span slot="submit">${msg("Update")}</span>
|
||||
<span slot="header">${msg("Update Role")}</span>
|
||||
<ak-role-form slot="form" .instancePk=${item.pk}> </ak-role-form>
|
||||
<button slot="trigger" class="pf-c-button pf-m-plain">
|
||||
<pf-tooltip position="top" content=${msg("Edit")}>
|
||||
<i class="fas fa-edit" aria-hidden="true"></i>
|
||||
</pf-tooltip>
|
||||
</button>
|
||||
</ak-forms-modal>
|
||||
</div>`,
|
||||
];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This example shows the use of the `modal` dialogue to show the "update role" form. Deciding to use
|
||||
a modal or to move to a different page is a matter of taste, but mostly rests on how large the form
|
||||
is. If it's likely to have internal scrolling, opt for a separate page.
|
||||
|
||||
For complex objects that have a lot of detail or subsidiary lists of features (such as Flows),
|
||||
provide a separate View page for each one. We have a specified display standard encapsulated in our
|
||||
`DictionaryList` component.
|
||||
|
||||
Creation and Updating are handled using the web component parent in `./elements/forms`. Like
|
||||
tables, a child component inherits and extends the Form class, providing three features: how to
|
||||
_retrieve_ the object, how to _send_ the object, and what to ask for. (RBAC is small enough, it's
|
||||
useful as an example):
|
||||
|
||||
```
|
||||
loadInstance(pk: string): Promise<Role> {
|
||||
return new RbacApi(DEFAULT_CONFIG).rbacRolesRetrieve({
|
||||
uuid: pk,
|
||||
});
|
||||
}
|
||||
|
||||
async send(data: Role): Promise<Role> {
|
||||
if (this.instance?.pk) {
|
||||
return new RbacApi(DEFAULT_CONFIG).rbacRolesPartialUpdate({
|
||||
uuid: this.instance.pk,
|
||||
patchedRoleRequest: data,
|
||||
});
|
||||
}
|
||||
return new RbacApi(DEFAULT_CONFIG).rbacRolesCreate({
|
||||
roleRequest: data,
|
||||
});
|
||||
}
|
||||
|
||||
protected override renderForm(): TemplateResult {
|
||||
return html`<ak-form-element-horizontal label=${msg("Name")} required name="name">
|
||||
<input
|
||||
type="text"
|
||||
value="${ifDefined(this.instance?.name)}"
|
||||
class="pf-c-form-control"
|
||||
required
|
||||
/>
|
||||
</ak-form-element-horizontal>`;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The `send` shows two different modes: If the existing instance has an identity, this is an update;
|
||||
otherwise it's a creation request.
|
||||
|
||||
These are _simple_ examples, naturally, and our application can get much more complicated. The
|
||||
`./admin/flows` vertical is one of the most complex, including:
|
||||
|
||||
- A per-flow view page with a [Mermaid](https://mermaid.js.org/) diagram to show a Flow's Stages
|
||||
- A sub-table of the Flow's Policies, with the ability to edit each Policy or its Bindings
|
||||
- A sub-table of the Flow's Stages with the ability to edit each Stage or a Stage's Binding directly
|
||||
- A sub-table of the Flow's Permissions
|
||||
|
||||
## Choosing To Use A Custom Component (developer's guide)
|
||||
|
||||
Some of our server-side objects come with lists. When editing a list, we suggest:
|
||||
|
||||
- If it's a simple list and there's only one choice, use `<select>`
|
||||
- If it's from the server and it's possible there are more than 100 items, use SearchSelect. It
|
||||
has features for showing complex list objects and narrowing down search items.
|
||||
- If the user can select multiple choices, use DualSelect
|
||||
|
||||
### License
|
||||
|
||||
|
||||
30
web/docs/2026-05-01-01-Foundations-Language.md
Normal file
30
web/docs/2026-05-01-01-Foundations-Language.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# 01 Foundations: Language
|
||||
|
||||
Date: 2026-05-01 (May 1st, 2026)
|
||||
|
||||
## The web application
|
||||
|
||||
The authentik web-based front-end is written in Typescript. We are currently targeting Typescript
|
||||
7.0, aka "TSGO," for its speed and compatibility. We chose Typescript because our experience has
|
||||
been that the type system, when used reliably, can prevent a wide class of errors, especially when
|
||||
negotiating with the authentik API as generated by OpenAPI.
|
||||
|
||||
- `mode: strict` is non-negotiable.
|
||||
- `useDefineForClassFields` is required for Lit decorator compatibility. See the Lit documentation
|
||||
[Typescript class fields for reactive
|
||||
properties](https://lit.dev/docs/components/properties/#:~:text=Set%20the%20useDefineForClassFields%20compiler%20option%20to%20false)
|
||||
for details.
|
||||
|
||||
## Tooling
|
||||
|
||||
Most of our internal tooling in the `./web/scripts` folder is written in JavaScript, not Typescript,
|
||||
to avoid the chicken-and-egg problem of needing build scripts to build build scripts. To facilitate
|
||||
checking, we enable `checkJs` and [jsdoc supported
|
||||
types](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#param-and-returns) in
|
||||
our tooling and script files, and we check them rigorously.
|
||||
|
||||
## Guidance:
|
||||
|
||||
Whenever tempted to use `any`, use `unknown` and a [type
|
||||
predicate](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)
|
||||
(sometimes called a "type guard") instead.
|
||||
27
web/docs/2026-05-01-02-Foundations-Build-Tools.md
Normal file
27
web/docs/2026-05-01-02-Foundations-Build-Tools.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# 02 Foundations: Build Tools
|
||||
|
||||
Date: 2026-05-01 (May 1st, 2026)
|
||||
|
||||
## Esbuild and TSGo
|
||||
|
||||
In 2024, the web UI used Rollup and TSC as its primary build tools. Building the entire UI for
|
||||
release took as many as three minutes.
|
||||
|
||||
ESBuild can both produce running Javascript from Typescript, and perform all of the bundling
|
||||
required to support the authentik WebUI. Switching to ESBuild reduced build time to 5 _seconds_. TSC
|
||||
has been relegated to the `no-emit` strategy of type-checking but not code-producing.
|
||||
|
||||
One complication in our code is that our web component foundation, Lit, has an awkward
|
||||
CSS-in-Javascript format incompatible with the build tools intended to support React, and the
|
||||
ESBuild plug-in to handle it is custom.
|
||||
|
||||
As of this writing, Typescript 7.0, aka "TSGo," is currently in beta. When it is released, we expect
|
||||
to both reassess this strategy and examine alternative build strategies. We prefer to hew as close
|
||||
to the Typescript standard as possible, and the standard is set by the Typescript team.
|
||||
|
||||
## Wireit
|
||||
|
||||
We have chosen to use Wireit because it provides a finer degree of control over build order and
|
||||
provides a caching strategy. This significantly speeds up rebuilding during development versus using
|
||||
NPM's own builds. Use Wireit _only_ when you need the cache or dependency order to be strict; for
|
||||
baseline builds, prefer writing directly into the `scripts` section of `package.json`.
|
||||
20
web/docs/2026-05-01-03-Foundations-Workspaces.md
Normal file
20
web/docs/2026-05-01-03-Foundations-Workspaces.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# 01 Foundations: Workspaces
|
||||
|
||||
Date: 2026-05-02 (May 2st, 2026)
|
||||
|
||||
## Workspaces
|
||||
|
||||
In order to promote the use and development of a product by the widest community possible, we
|
||||
default to using NPM workspaces, since it is the most common too possible.
|
||||
|
||||
Provide a separate workspace when:
|
||||
|
||||
1. The project is support that applies across multiple other workspaces, rather than being a part of
|
||||
an application directly. `./packages/core` is the example.
|
||||
2. The project is a polyfill or library that is needed across all the applications supported by the
|
||||
front-end. `./packages/formdata-polyfill` is the example.
|
||||
|
||||
3. The project is an application that has radically different requirements from the standard set of
|
||||
applications. `./packages/sfe` exists to support only the Login Flow with the Internet Explorer
|
||||
11-based rendering engine, which is still embedded in some older Microsoft products we cannot
|
||||
afford to ignore.
|
||||
12
web/docs/2026-05-02-04-Foundation-Import-Strategies.md
Normal file
12
web/docs/2026-05-02-04-Foundation-Import-Strategies.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# 01 Foundations: Import Strategies
|
||||
|
||||
Date: 2026-05-02 (May 2st, 2026)
|
||||
|
||||
## Import Strategies
|
||||
|
||||
`package.json` defines a large number of import paths that reach into the `src` folder. We use
|
||||
NodeJS subpaths prefixed with `#`, such as `#fonts`, `#elements`, or `#flow` to isolate subsections
|
||||
of the frontend. This strategy is intended to facilitate directory restructuring without having to
|
||||
do mass search-and-replace ops, and as a precursor to further mono-repo-ifying the codebase.
|
||||
|
||||
We recommend using barrel files only to export the intended API of a defined subsection.
|
||||
69
web/docs/2026-05-02-05-Foundation-Code-Quality.md
Normal file
69
web/docs/2026-05-02-05-Foundation-Code-Quality.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# 01 Foundations: Code Quality
|
||||
|
||||
Date: 2026-05-02 (May 2st, 2026)
|
||||
|
||||
## Code Linting
|
||||
|
||||
We _like_ our guardrails. We use ESLint with as many plug-ins as we can reasonably stuff into it for
|
||||
our checks, such as `eslint-plugin-lit` and `eslint-plugin-wc`, plus `lit-analyzer`.
|
||||
|
||||
## Code Formatting
|
||||
|
||||
We use `prettier` to enforce a coding style and to catch some fundamental syntax errors. The current
|
||||
`prettier` configuration correctly formats Lit's HTML-in-JS and CSS-it-JS use cases, as well as all
|
||||
the Typescript we can throw at it.
|
||||
|
||||
## Lockfile
|
||||
|
||||
We have a custom script in `./scripts/lint-lockfile.sh` that checks to ensure that every packages as
|
||||
a resolved hash.
|
||||
|
||||
## Type Checking
|
||||
|
||||
Although we use ESBuild to convert and bundle our Typescript into JavaScript, we use the stock
|
||||
Typescript compiler, `tsc`, to check our types. We maintain a default configuration with `use
|
||||
strict`.
|
||||
|
||||
## Testing
|
||||
|
||||
We do have tests, but they are primitive. We are very much in a move-fast and try hard not to break
|
||||
things. We strongly recommend that every PR include a description of how a peer would test the
|
||||
product manually to validate that it does what the PR claims it does.
|
||||
|
||||
Adding to the library of end-to-end tests is a critical mission.
|
||||
|
||||
## Your eyes, and the eyes of your peers
|
||||
|
||||
For all that we do like our guardrails, nothing surpasses peer review.
|
||||
|
||||
## AI Review
|
||||
|
||||
We have had mixed results using AI tools such as Claude and Copilot to vet our code. Claude,
|
||||
especially, can be very good at pointing out shortcomings and missed opportunities in a pull
|
||||
request, but it can also generate a lot of false positives or trivial issues. We recommend reading
|
||||
AI reviews with caution.
|
||||
|
||||
## AI Review Strategy
|
||||
|
||||
That said, this is the current template for a code review prompt. Start with the _target_ branch,
|
||||
then download the patch file into the project root. You can easily download the patch file by
|
||||
navigating to the Github PR and appending `.patch` to it, for example:
|
||||
`https://github.com/goauthentik/authentik/pull/21868.patch`
|
||||
|
||||
We use this template:
|
||||
|
||||
> Keep the tone neutral-professional-skeptical, the voice of an expert. Avoid excessive enthusiasm.
|
||||
> This is the root folder for the authentik single sign-on server.
|
||||
>
|
||||
> Read the patch file `./21868.patch`. This [community-provided] patch [describe the patch here in
|
||||
> your own words, using only one or two sentences].
|
||||
>
|
||||
> Task 1: Provide a high-level summary of the effect of applying `./21868.patch` Point out any
|
||||
> shortcomings or security considerations.
|
||||
>
|
||||
> Task2: If no tests are provided in the patch, describe how these changes could be tested.
|
||||
|
||||
Edit the patch number, add or remove "community-provided" as needed, and include your best
|
||||
understanding of what the patch claims to do in the second paragraph. Having a strong template that
|
||||
you hand-edit before running seems to work much better than using a generic template in a Claude
|
||||
skill.
|
||||
@@ -10,7 +10,11 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"experimentalDecorators": true,
|
||||
// See https://lit.dev/docs/components/properties/
|
||||
|
||||
// `useDefineForClassFields` is required for Lit decorator compatibility.
|
||||
// See the Lit documentation
|
||||
// [Typescript class fields for reactive properties](https://lit.dev/docs/components/properties/#:~:text=Set%20the%20useDefineForClassFields%20compiler%20option%20to%20false)
|
||||
// for details.
|
||||
"useDefineForClassFields": false,
|
||||
"target": "esnext",
|
||||
"module": "preserve",
|
||||
|
||||
Reference in New Issue
Block a user