coulomb-social/docs/adr/ADR-0001-netkingdom-identity.md
tegwick 01da195c13 Implement NetKingdom identity shell for coulomb.social (CSOC-WP-0002)
Django scaffold aligned with the business delivery lane: tenant-keyed
Member model without passwords, identity app as sole OIDC/session
boundary, dev-claims login, authenticated /app/ shell, ADR-0001, and
tests. T01/T02/T05/T06 done; OIDC registration, real user-engine HTTP,
flex-auth, and packaging remain open.
2026-08-09 01:45:05 +02:00

85 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: ADR-0001
title: NetKingdom identity for coulomb.social
status: accepted
date: 2026-08-09
workplan: CSOC-WP-0002
task: CSOC-WP-0002-T01
---
# ADR-0001 — NetKingdom identity for coulomb.social
## Status
Accepted (2026-08-09).
## Context
coulomb.social is being reestablished as a standalone business application
(DR-2 B) on the Railiance delivery lane. The business-app service contract
v0.1 defaults to **app-local accounts** (DR-3 A) with a bounded auth module
for a later OIDC switch.
A social product with many members is a poor fit for a private password
database inside the app: credential lifecycle, MFA, and user-domain profiles
already exist (or are governed) in the NetKingdom landscape.
## Decision
1. **Authentication** uses only the **NetKingdom IAM Profile** (OIDC + PKCE).
The app depends on the profile contract, not on KeyCape vs Keycloak
implementation details.
2. **User-domain facts** (account, profile, memberships, identity links) are
owned by **user-engine**. This app maps `(issuer, sub)` to a local
`Member` row for session convenience and never stores passwords.
3. **Authorization** for protected actions is decided by **flex-auth** (PDP).
The app is a PEP only (fail-closed when the PDP is unavailable for
sensitive actions). Dev may use a local deny-by-default stub until the
protected system is registered.
4. **Browser session** after successful OIDC is an application session
(Django session / signed cookie). Tokens are not treated as long-lived
API credentials in the browser.
5. **Tenant model**: all client-owned data is keyed by `tenant_id` from the
first migration (Binky Hedgehog = client #1 / reference tenant).
6. **Relationship to DR-3 A**: the contracts “app-local baseline” remains
valid for simple single-tenant tools (e.g. vergabe-teilnahme v1). This ADR
**specializes** coulomb.social onto NetKingdom identity as a product
decision; the auth code still lives in one module (§2.3) so issuer mode
can change without rewriting the product.
### Issuer modes
| Mode | When |
|------|------|
| Dev mock claims (`DEBUG` + `OIDC_ENABLED=false`) | Local unit/integration tests and offline shell work |
| local-identity / KeyCape | Bootstrap and lightweight platform environments |
| Keycloak expanded | Production / enterprise MFA & federation when platform provides it |
### Non-goals
- App-local password / MFA store
- Bubble as identity provider
- Content migration from Bubble in this identity track
- Owning KeyCape, Keycloak, user-engine, or flex-auth codebases
## Consequences
- Scaffold uses Django aligned with the business delivery lane, with a
dedicated `identity` app as the sole OIDC/session boundary.
- OpenBao (or local 0600 files) holds OIDC client secrets; nothing secret
in Git.
- Content re-claim is a separate workplan after the authenticated shell
works.
## References
- `workplans/CSOC-WP-0002-netkingdom-user-management-reestablish.md`
- `net-kingdom/canon/standards/iam-profile_v0.2.md` (and v0.3)
- `net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`
- `the-custodian/canon/standards/business-app-service-contract_v0.1.md`
- `the-custodian/docs/business-platform-decision-records.md` (DR-2, DR-3)