From 39a3f1379c749e7b5da3a361bd7bf09917c1c284 Mon Sep 17 00:00:00 2001 From: Wanja Krah Date: Thu, 12 Nov 2026 10:24:10 +0100 Subject: [PATCH] ADR3 refinement --- ...-identity-and-application-authorization.md | 222 ++++++++++++++++++ skills/adr-brainstorm/SKILL.md | 47 ++-- systems.md | 18 ++ 3 files changed, 266 insertions(+), 21 deletions(-) create mode 100644 adr/refined/ADR3_shared-identity-and-application-authorization.md diff --git a/adr/refined/ADR3_shared-identity-and-application-authorization.md b/adr/refined/ADR3_shared-identity-and-application-authorization.md new file mode 100644 index 0000000..794f7a6 --- /dev/null +++ b/adr/refined/ADR3_shared-identity-and-application-authorization.md @@ -0,0 +1,222 @@ +**ID:** ADR3 \ +**Title:** Shared identity and application authorization \ +**Supersedes:** - \ +**Status:** REFINED \ +**Expiration Date:** Six months after approval; record the calendar date upon manual approval. + +## Context + +Agile Dancers needs authenticated access so that private school data is available +only to authorized people. Initially, users are school owners and invited staff. +The design must accommodate teachers, students, and parents later without +requiring their permissions to be designed now. + +A person may belong to multiple schools, with different permissions in each. +Future tools must be able to use the same identity, although shared login across +multiple deployed applications is not an immediate requirement. Authentication, +application admission, and access to school data are separate responsibilities. + +This decision applies across the application landscape when systems introduce +protected user access. Agile Dancers is the first consumer. Waterpolo Coaching +does not require immediate integration. + +There is no budget for paid identity services. Authentication must be self-hosted +and must allow accounts provided by the landscape without requiring an external +Google, Microsoft, or similar account. + +The intended host is the existing Synology DS224+, with a four-core Intel Celeron +J4125 and 18 GB RAM, including a 16 GB expansion recognized and verified by the +maintainer. This exceeds Synology's published supported memory maximum. Actual +spare capacity alongside existing workloads has not been measured for identity +hosting. Product sizing guidance is a starting point rather than evidence of +performance on this NAS. + +## Decisions + +### Shared identity and ownership + +Use self-hosted Keycloak as the shared identity provider. Keycloak owns identities, +credentials, authentication factors, and application admission. Applications must +not implement their own password storage or credential verification. Users need +not have an external identity provider account. External sign-in may be considered +later; it is not required initially. + +Manage Keycloak deployment configuration, upgrades, and recovery instructions in +a dedicated identity infrastructure repository. Its name remains follow-up work. +Keep secrets outside version control. Applications own their integrations and +runtime configuration. Landscape owns this ADR and the system map; reusable build +resources belong to engineering, consistent with ADR1. + +Target the Synology for the initial deployment. Validate startup, normal operation, +and login bursts alongside existing NAS workloads before putting Keycloak into +use. Start capacity planning with Keycloak's documented 2 GB container memory +limit for small production deployments, allowing additional database resources. +This is an initial planning allocation, not a measured consumption guarantee. + +### Protocol and browser integration + +Use OpenID Connect as the default identity integration protocol. For interactive +browser login, use Authorization Code with PKCE. Redirect users to Keycloak for +authentication. Do not use the implicit or resource owner password credentials +flows. + +For browser applications, use a Backend for Frontend pattern: the application +backend completes the protocol exchange and keeps OAuth tokens on the server. +The browser receives a Secure, HttpOnly session cookie. Protect cookie-based +requests against CSRF. This functionality may reside in an application's existing +backend; it does not require a separate deployment. + +Validate tokens with established framework support, including signature, issuer, +audience, and lifetime. APIs accept appropriate access tokens, not ID tokens as +API credentials. Local JWT validation using the provider's public keys does not +require a Keycloak request for every API call. + +Backend-held tokens reduce credential extraction through malicious browser +scripts. They do not prevent malicious scripts from making requests through an +active browser session; applications still need browser security protections. + +### Authentication and recovery + +Require MFA for all protected application users. Support password plus an +authenticator code (TOTP), or a passkey configured to require user verification. +Configure Keycloak to enforce these authentication requirements. + +Provide recovery codes as the normal fallback. If all authenticators and recovery +codes are lost, the maintainer performs exceptional manual recovery after identity +verification. Email password reset alone must not remove MFA. Define the detailed +identity-verification and recovery procedure before use. + +### Application admission and domain authorization + +An identity in Keycloak does not automatically grant access to every application. +Require an explicit Agile Dancers admission entitlement in Keycloak. Enforce +admission in the backend, including protected API access; hiding frontend routes +or application links is insufficient. + +Agile Dancers owns school memberships, school roles, and school-specific +permissions. One identity may have multiple school memberships with different +permissions. Enforce authorization on the backend for every protected operation +and its school context. An authenticated identity or application admission alone +does not grant school data access. + +Other applications own their own domain permissions. If several tools later need +shared school membership semantics, define an explicit contract or separately +owned capability. Shared identity does not imply shared membership storage. + +### Provisioning and revocation + +The maintainer provisions each school and its first owner. Owners may invite +staff. A controlled provisioning workflow coordinates application admission in +Keycloak and membership in Agile Dancers for an existing or new identity. School +owners receive no Keycloak administration access. + +Design provisioning and removal for partial failures, safe retries, and recovery. +An incomplete workflow must not grant school access without the required +admission and membership. Detailed workflow contracts and mechanics are follow-up +implementation work. + +Removing a school membership must deny access to that school's data on subsequent +requests, even if updating Keycloak fails. Preserve other school memberships. +When the last Agile Dancers school membership is removed, revoke Agile Dancers +admission as well. Preserve the shared identity and access to other tools. + +Allow a maximum five-minute delay before application admission revocation affects +existing access credentials. Token lifetime, clock tolerance, refresh behavior, +and backend session handling together must enforce that bound. A longer-lived +browser session must not bypass it. School membership revocation retains the +immediate behavior described above. + +### Adoption and review + +Implement first in Agile Dancers. Other tools adopt this approach when they +introduce protected user access; no immediate Waterpolo Coaching integration is +required. Preserve the ability to add broader user audiences later. + +Review six months after approval. The review date triggers reevaluation rather +than automatic expiry. REFINED records the agreed proposal; approval is a +separate manual action. + +## Options considered + +### Identity architecture + +| Option | Pros | Cons | Outcome | +| --- | --- | --- | --- | +| Existing shared identity product | Shared identity across tools; established authentication and account-management capabilities; avoids building a login product. | Adds an operational dependency, database, configuration, updates, and recovery work. | Chosen. | +| Authentication within each application using established libraries | Fewer services initially; direct application control over the experience. | Duplicates account lifecycle work; separate accounts by default; shared identity requires later migration or federation. | Not chosen because shared identity across future tools is desired. | +| Custom shared identity service using established libraries | Shared identity with full control over behavior. | Makes protocol integration, account recovery, sessions, and security maintenance a custom product responsibility. | Not chosen because the development and maintenance burden is unjustified. | + +### Self-hosted product + +| Option | Pros | Cons | Outcome | +| --- | --- | --- | --- | +| Keycloak | Supports OIDC with PKCE, local accounts, passkeys, MFA, shared login, and future external identity integration. | Requires service and database maintenance; resource suitability on the NAS still needs measurement. | Chosen for capability fit; validate NAS capacity before use. | +| authentik | Supports OIDC with PKCE, passkeys, and TOTP; flexible application integration. | Requires server, worker, and PostgreSQL operation; open-source and paid feature boundaries need attention. Its documented host minimum does not establish a lower footprint than Keycloak. | Credible alternative, but no demonstrated resource advantage justifies preferring it here. | + +Keycloak documents a 2 GB container limit recommendation for small production +installations. authentik documents a host minimum of two CPU cores and 2 GB RAM. +These figures describe different scopes and are not a comparative benchmark. + +### Authorization ownership + +| Option | Pros | Cons | Outcome | +| --- | --- | --- | --- | +| Keycloak admission plus application-owned domain permissions | Central admission control; school rules stay with school data; applications can evolve independently. | Requires coordinated admission and membership workflows, including failure recovery. | Chosen. | +| Centralize school memberships and permissions in Keycloak | Central administration and potential reuse across tools. | Couples domain changes to identity configuration; applications still need data-access enforcement. | Not chosen for domain authorization. | + +### Browser integration + +| Option | Pros | Cons | Outcome | +| --- | --- | --- | --- | +| Backend-held tokens with a browser session cookie | Keeps OAuth tokens unavailable to browser scripts; uses the existing backend. | Adds session lifecycle management and CSRF protection; malicious scripts can still act through the browser. | Chosen. | +| Frontend-held tokens with Authorization Code and PKCE | Direct frontend-to-API integration; avoids backend login sessions. | Malicious application scripts can steal valid tokens for reuse elsewhere; PKCE does not prevent that theft. | Not chosen for browser applications. | + +OIDC provides the required identity integration. SAML is not required by current +consumers; this ADR does not declare SAML obsolete. + +## Consequences + +- Create the dedicated identity infrastructure repository and specify deployment, + upgrade, backup, restore, and manual recovery procedures. Creating documentation + does not authorize production deployment. +- Validate NAS resource usage before use, including database overhead and competing + workloads. Implementation configuration and measured validation evidence belong + in the owning repositories. +- Integrate Agile Dancers with backend-managed OIDC login, protected sessions, + application admission enforcement, and school authorization. +- Specify membership storage and school permission rules for owners and invited + staff. Broader audiences are future work within the agreed identity boundaries. +- Implement controlled invitations and coordinated admission removal. Define + failure recovery, retries, and reconciliation without weakening school isolation. +- Validate mandatory MFA, passkey user verification, recovery protection, immediate + school membership revocation, and the five-minute admission revocation bound. +- Define session renewal, logout, and identity-provider outage behavior in the + consuming application specification. Failure behavior must preserve the agreed + authorization and revocation bounds. +- Shared identity introduces a common dependency: Keycloak outages can affect login + and session renewal across integrated tools. NAS and database colocation retain + shared infrastructure failure points. +- Maintain systems.md as the planned service becomes an implemented system and + repositories and responsibilities become concrete. +- Record the absolute review date upon manual approval. This ADR does not itself + create repositories, provision accounts, or deploy services. + +## References + +Consulted on 2026-11-10: + +- [OIDC Core](https://openid.net/specs/openid-connect-core-1_0.html) +- [RFC 9700: OAuth 2.0 Security Best Current Practice](https://www.rfc-editor.org/info/rfc9700/) +- [RFC 10017: OAuth 2.0 for Browser-Based Applications](https://www.ietf.org/ietf-ftp/rfc/rfc10017.html) +- [Keycloak overview](https://www.keycloak.org/) +- [Keycloak administration guide](https://www.keycloak.org/docs/latest/server_admin/) +- [Keycloak OIDC integration](https://www.keycloak.org/securing-apps/oidc-layers) +- [Keycloak container memory configuration](https://www.keycloak.org/server/containers) +- [Keycloak resource sizing](https://www.keycloak.org/high-availability/single-cluster/concepts-memory-and-cpu-sizing) +- [Keycloak production configuration](https://www.keycloak.org/server/configuration-production) +- [authentik installation requirements](https://docs.goauthentik.io/install-config/install/docker-compose/) +- [authentik components](https://docs.goauthentik.io/install-config/first-steps/) +- [authentik OIDC and PKCE](https://docs.goauthentik.io/add-secure-apps/providers/oauth2/) +- [authentik authenticators](https://docs.goauthentik.io/users-sources/user/user-interface/) +- [authentik enterprise distinction](https://docs.goauthentik.io/enterprise/) +- [Synology DS224+ specifications](https://www.synology.com/en-us/products/DS224%2B) diff --git a/skills/adr-brainstorm/SKILL.md b/skills/adr-brainstorm/SKILL.md index 6ef44da..5887249 100644 --- a/skills/adr-brainstorm/SKILL.md +++ b/skills/adr-brainstorm/SKILL.md @@ -4,14 +4,16 @@ description: "Brainstorm with the user about a new ADR. Use when the user wants --- An ADR is an Architecture Decision Record. Such a record contains a decision on the architecture or design for the application landscape the user is maintaining. -If an ADR-folder exists, read the README.md of that folder to get a full understanding of any specific rules and properties of how the user works with ADR's that might not be listed in this Skill. +If an ADR-folder exists, read the `README.md` of that folder to get a full understanding of any specific rules and properties of how the user works with ADRs that might not be listed in this Skill. -The goal of the ADR is to provide an architectural solution or a design solution for a given context. Therefor, two to four different approaches must be worked out with their pro's and con's, from which the user should select one as their preferred solution. +The goal of the ADR is to provide an architectural solution or a design solution for a given context. Therefore, two to four different approaches must be worked out with their pros and cons, from which the user should select one as their preferred solution. -Below, the brainstorm session is mapped out in multiple steps. Each step must be completed succesfully, before continuing to the next step. Success means reaching a shared understanding and whatever the step entitles as its success criteria. +Below, the brainstorm session is mapped out in multiple steps. Each step must be completed successfully before continuing to the next step. Success means reaching a shared understanding and meeting the success criteria defined for that step. If the user, or the relevant ADR, indicates that an ADR is to supersede another ADR, read that ADR first. +Consider each ADR in the context of the application landscape, including active and future projects. State the decision's scope explicitly and consider its implications for other projects within that scope. Include project-specific context when it explains the problem that prompted the ADR or illustrates relevant constraints and tradeoffs. Keep those details focused so the ADR remains relevant and understandable to readers applying it to other projects. + ## Explore decisions with the user ### Follow a design tree @@ -24,12 +26,15 @@ Ask dependent questions only after their prerequisites are settled. Revisit earlier decisions when new evidence changes their assumptions, and explain which dependent decisions need reconsideration. +Number questions sequentially throughout the session using ❓ **Q1**, ❓ **Q2**, etc. as prefixes. +Number proposed answers within each question using ➡️ **P1**, ➡️ **P2**, etc. as prefixes. Restart proposal numbering for each question. + Keep the tree within the ADR's agreed scope. Suggest follow-up work for independent topics rather than continually expanding the ADR. A deferred topic must have a clear boundary and must not leave the main decision ambiguous. -Finish when the user has agreed on the architectural decision and its material tradeoffs. Identify remaining implementation questions as follow-up work. Do not leave questions open that could materially change the chosen approach. +Finish exploring decisions when the user has agreed on the architectural decision and its material tradeoffs. Identify remaining implementation questions as follow-up work. Do not leave questions open that could materially change the chosen approach. ### Establish facts before asking for decisions @@ -50,7 +55,7 @@ implementation uses something else. ### Keep the conversation collaborative Use short rounds, usually one main question or a few closely related -questions. Number questions when asking more than one. Do not ask every +questions. Number every question. Do not ask every available question at once if that would hinder discussion. For decision questions, normally provide a recommended answer and its @@ -79,25 +84,25 @@ the Decisions section until the user accepts them. ### Guide the process through steps -Coöperate with the user via the following steps. Communicate each step in which step you are, and what the step entails. Use the template adr-template.md as a template for the final ADR. +Work with the user through the following steps. At the start of each step, state which step you are on and what it entails. Use the template `adr-template.md` for the final ADR. -The _first step_ is to get to a shared understanding of the probived context and the problem area the user is in need for a decision. Success for step one means you can describe the context in one to fifty sentences. +The _first step_ is to get to a shared understanding of the provided context and the problem that requires an architectural decision. Success for step one means you can describe the context in one to fifty sentences. -The _second step_ is to get to two to four different architectural solutions or design solutions for the described context. Every solution needs a short description of one to fifty sentences and a list of one to ten pro's and one to ten con's. allow discussion of consequences when they affect the choice. Record them formally in _step four_, but don’t postpone discovering migration costs or operational burdens until after selecting an option. -Success for step two means there are more than one credible solutions with a set of relevant pro's and con's by which a user is able to choose, or not choose that solution for the next step. +The _second step_ is to get to two to four different architectural solutions or design solutions for the described context. Every solution needs a concise description, using no more than fifty sentences. Number each solution and include one to ten pros and one to ten cons. Allow discussion of consequences when they affect the choice. Record them formally in _step four_, but don’t postpone discovering migration costs or operational burdens until after selecting an option. +Step two succeeds when the user can compare at least two credible solutions using their relevant pros and cons. -The _third step_ is to pick the best solution. Ths user must decide what solution he prefers. The choosen solution will be presented as the ADR decision. A decision may branch into a small tree of related decisions, small meaning one to five levels deep. Make the architectural decision, its scope, and its material tradeoffs unambiguous; record remaining implementation questions as follow-up work. Success of step three means there is a shared understanding of the choosen solution and what it entails. +The _third step_ is to pick the best solution. The user must decide which solution they prefer. The chosen solution will be presented as the ADR decision. A decision may branch into a small tree of related decisions, with a maximum of five levels. Make the architectural decision, its scope, and its material tradeoffs unambiguous; record remaining implementation questions as follow-up work. Success of step three means there is a shared understanding of the chosen solution and what it entails. -The _fourth step_ is to make clear what the consequences will be for the application landscape. Success of step four means there is a clear understanding of the changes that should be made to software landscape and the way futurue work should be implemented. +The _fourth step_ is to make clear what the consequences will be for the application landscape. Success of step four means there is a clear understanding of the changes that should be made to the software landscape and the way future work should be implemented. -The _fifth step_ is fill out the other properties of the ADR that is required by the template. Succes of step five means the ID of the ADR is unique, the title is short and comprehandible, and gives the user an overall idea of what the ADR is about. If the ADR supersedes another ADR, that is listed as well. -Set the Expiration Date of when the ADR should be reviewd. This should be a relative date, to be made absolute by the user as soon as the user moves the ADR to APPROVED. -Finally, set the status to REFINED. It's up to the user to set the Status to either APPROVED - meaning the ADR is accepted and to be applied for all future work - or REJECTED - meaning the ADR is not accepted and should not be taken in consideration. +The _fifth step_ is to fill out the other properties of the ADR that are required by the template. Success of step five means the ID of the ADR is unique, the title is short and comprehensible and gives the user an overall idea of what the ADR is about. If the ADR supersedes another ADR, that is listed as well. +Set a review interval, such as six months after approval. The user converts this interval to an absolute expiration date when approving the ADR. +Finally, set the status to REFINED. It's up to the user to set the status to either APPROVED - meaning the ADR is accepted and to be applied to future work within its scope - or REJECTED - meaning the ADR is not accepted and should not be taken into consideration. -When updating the ADR with the result of the brainstorm, make it both easy to glanse through, as to read in full, meaning: -- stick to the template -- keep to the formatting as is custom for markdown-files -- high use of headers and sub-headers -- high use of bullit points, lists, and tables where applicable -- keep sentences short and precise where possible -- create images with ASCII-art where possible \ No newline at end of file +When updating the ADR with the result of the brainstorm, make it easy to scan and to read in full, by following these guidelines: + +- Stick to the template +- Follow standard Markdown formatting +- Use headings, lists, and tables where they improve readability +- Keep sentences short and precise where possible +- Use ASCII diagrams where they clarify the design \ No newline at end of file diff --git a/systems.md b/systems.md index 3209b20..9a2d93f 100644 --- a/systems.md +++ b/systems.md @@ -6,6 +6,7 @@ | [Waterpolo Coaching](http://192.168.2.28:3000/wanjakrah/waterpolo-coaching) | Interactive visualization of waterpolo training and player positions | Owns its application state; no production data store documented yet | Local frontend/backend development; no production deployment configured | | landscape | ADRs, specifications, capability/system map, onboarding and shared agent skills | Owns landscape documentation and agent workflows | Documentation repository; no application runtime | | [engineering](http://192.168.2.28:3000/wanjakrah/engineering) | Shared build mechanisms, standards, templates and generator; shared runner setup | Owns versioned engineering source | Immutable versioned releases consumed by applications | +| Shared identity / dedicated repository planned (ADR3 REFINED) | Planned Keycloak service for shared authentication and application admission; repository owns deployment configuration, upgrades, and recovery instructions | Planned ownership of identities, credentials, authentication factors, and application admission; applications retain their domain permissions and memberships | Planned self-hosted deployment on the Synology; resource validation required before use | S19 separates engineering and governance repositories. It does not extract a business capability or change runtime/data boundaries. Scheduling and school @@ -21,3 +22,20 @@ The physical mini-pc provides the shared host runner labelled `mini-pc`, registe at Gitea user scope for `wanjakrah`. Existing and new repositories of that owner use the same runner. Builds share one execution slot; deployment settings and registry credentials remain project-owned. + +The NAS is a Synology DS224+ with an Intel Celeron J4125 (four cores, +`linux/amd64`). Its original 2 GB RAM is supplemented by a 16 GB module, for +18 GB total. The maintainer confirmed that DSM recognizes the expansion and +verified that it works. This installed capacity exceeds Synology's published +supported maximum of 6 GB; it is an observed configuration rather than a vendor +support claim. See the [Synology specifications](https://www.synology.com/en-us/products/DS224%2B). + +The refined ADR3 proposal selects self-hosted Keycloak as the shared identity +provider, targeting the Synology. Keycloak is planned, not deployed; ADR3 is +REFINED and does not yet establish an approved landscape standard. Validate resource +usage alongside existing NAS workloads before putting it into use. +Agile Dancers is the first planned consumer and retains ownership of school +memberships and school-specific permissions. Other tools integrate when they +introduce protected user access. Each application owns its identity integration; +the dedicated identity repository's name remains to be chosen. Secrets remain +outside version control. -- 2.49.1