Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
e2a5a6b
Add account-derived LineageWeave RP profile
seonghobae Aug 13, 2026
694f406
Harden account-derived mapper reconciliation
seonghobae Aug 13, 2026
eb7271b
Fix Keycloak realm import and account profile bootstrap
seonghobae Aug 13, 2026
6e96ff0
Run Keycloak image as non-root
seonghobae Aug 13, 2026
cf4dbb9
Harden LineageWeave account claim deployment
seonghobae Aug 13, 2026
7d71024
Merge branch 'main' into codex/per-account-rp-claims
opencode-agent[bot] Aug 14, 2026
4ea8fbc
build: refresh account-unification lockfile
seonghobae Aug 14, 2026
43e7607
docs: separate downstream RP evidence
seonghobae Aug 14, 2026
eed91c9
docs: record product technical gap baseline
seonghobae Aug 20, 2026
eafa344
docs: refresh exact head gap evidence
seonghobae Aug 20, 2026
f9d0159
docs: define lineageweave tenant mapping
seonghobae Aug 20, 2026
65c6290
docs: refresh exact-head PR inventory
seonghobae Aug 20, 2026
826e774
docs: keep live PR evidence non-self-referential
seonghobae Aug 20, 2026
fb5e875
docs: track current SCIM lock PR evidence
seonghobae Aug 20, 2026
b52e0c0
docs: refresh SCIM PR head evidence
seonghobae Aug 20, 2026
cf34b81
docs: refresh SCIM PR head evidence
seonghobae Aug 20, 2026
815332d
docs: correct SCIM PR head hash
seonghobae Aug 20, 2026
271541f
docs: record exact Strix failure evidence
seonghobae Aug 20, 2026
1acf3a5
test(clients): cover malformed observed mapper drift
seonghobae Aug 20, 2026
506c7a1
docs: record workflow registry lifecycle evidence
seonghobae Aug 20, 2026
f785db2
docs: record workflow inventory pagination evidence
seonghobae Aug 20, 2026
d548df1
docs: record uv lock failure evidence
seonghobae Aug 20, 2026
1bd15d0
docs: refresh SCIM PR baseline evidence
seonghobae Aug 20, 2026
9b0069e
docs: record current SCIM review head
seonghobae Aug 20, 2026
c483bd5
docs: refresh live product gap baseline
seonghobae Aug 20, 2026
14193ad
docs: refresh gap baseline doctoring
seonghobae Aug 20, 2026
02baa31
docs: record live oidc acceptance boundary
seonghobae Aug 20, 2026
3777f54
test(realm): cover default validator artifacts
seonghobae Aug 20, 2026
193ea3a
docs: refresh current PR gap evidence
seonghobae Aug 20, 2026
49d8899
docs: record cross-repo cadence dependency
seonghobae Aug 20, 2026
32b69cd
docs: refresh live check failure baseline
seonghobae Aug 20, 2026
fb75994
docs: record stacked lockfile rerun
seonghobae Aug 20, 2026
0cf06bf
docs: record recovered lockfile checks
seonghobae Aug 20, 2026
89a1415
docs: bound storage evidence gap
seonghobae Aug 20, 2026
2b8c59f
docs: reconcile ecosystem dependency evidence
seonghobae Aug 20, 2026
a997826
docs: update current documentation head
seonghobae Aug 20, 2026
8a5ba11
docs: record exact local CI evidence
seonghobae Aug 20, 2026
0d4d1b9
docs: pin latest baseline head
seonghobae Aug 20, 2026
9f6e9b6
docs: reconcile scheduler and check baseline
seonghobae Aug 20, 2026
972ed50
docs: record local PostgreSQL evidence
seonghobae Aug 20, 2026
8e74c4e
docs: record stacked CodeQL checks
seonghobae Aug 20, 2026
b35def4
docs: record dependency stack state
seonghobae Aug 20, 2026
b0748bc
docs: refresh current authorization and cadence checks
seonghobae Aug 20, 2026
1937a6f
docs: record rebased dependency heads
seonghobae Aug 20, 2026
35a0bbd
docs: record encoded start-login remediation
seonghobae Aug 21, 2026
cae142c
docs: refresh current check evidence
seonghobae Aug 21, 2026
99fdd86
docs: record token rotation remediation
seonghobae Aug 21, 2026
e23af12
docs: refresh open PR evidence
seonghobae Aug 21, 2026
6acb064
docs: record current authorization PR head
seonghobae Aug 21, 2026
1604d8e
docs: align baseline with final token fix
seonghobae Aug 21, 2026
dbfea14
docs: refresh exact-head gap evidence
seonghobae Aug 21, 2026
899fb20
docs: correct live gap snapshot
seonghobae Aug 21, 2026
f2c4a15
docs: record stacked dependency updates
seonghobae Aug 21, 2026
58c6bb5
docs: record central coverage dependency
seonghobae Aug 21, 2026
bcd4b15
docs: refresh exact-head gap evidence
seonghobae Aug 21, 2026
6e0c92f
docs: refresh current queue evidence
seonghobae Aug 21, 2026
2c065e9
docs: update latest review evidence
seonghobae Aug 21, 2026
6244402
docs: track open MCP authorization gap
seonghobae Aug 21, 2026
096c12c
docs: record MCP cross-repo boundary
seonghobae Aug 21, 2026
920bed6
docs: record central automation failure evidence
seonghobae Aug 21, 2026
660e02e
docs: track central docstring repair
seonghobae Aug 21, 2026
d2b765f
docs: record scheduler dispatch evidence
seonghobae Aug 21, 2026
fbfbabd
docs: refresh live PR baseline
seonghobae Aug 21, 2026
daf2030
docs: refresh central check rollups
seonghobae Aug 21, 2026
6f3c861
docs: track scheduler hardening PRs
seonghobae Aug 21, 2026
3b35084
docs: record workflow registry lifecycle evidence
seonghobae Aug 21, 2026
cde3910
docs: refresh exact-head gap inventory
seonghobae Aug 21, 2026
f331938
docs: distinguish neutral security evidence
seonghobae Aug 21, 2026
d37d627
docs: refresh live product gap evidence
seonghobae Aug 21, 2026
ee6c13f
docs: correct MCP standards references
seonghobae Aug 21, 2026
7be7b48
docs: record post-snapshot PR heads
seonghobae Aug 21, 2026
630cd32
docs: refresh live PR evidence
seonghobae Aug 21, 2026
cdd0d74
docs: align baseline with current PR head
seonghobae Aug 21, 2026
35db1d2
docs: refresh live PR baseline
seonghobae Aug 21, 2026
0ba998f
docs: record latest MCP PR head
seonghobae Aug 21, 2026
3109b33
docs: refresh MCP PR head evidence
seonghobae Aug 21, 2026
ea74477
docs: clarify realm profile validator contract
seonghobae Aug 21, 2026
1a69a72
docs: refresh exact PR evidence
seonghobae Aug 21, 2026
a8cbafe
fix: preserve realm validation diagnostics
seonghobae Aug 21, 2026
ee96f6d
docs: record validator diagnostics fix
seonghobae Aug 21, 2026
ec78f92
docs: record SCIM coverage refresh
seonghobae Aug 21, 2026
ca075b3
docs: refresh live product gap baseline
seonghobae Aug 21, 2026
0735c81
fix(rp): reserve LineageWeave for account claims
seonghobae Aug 21, 2026
2887258
docs: refresh live PR gap baseline
seonghobae Aug 21, 2026
ac29331
docs: refresh authorization PR evidence
seonghobae Aug 21, 2026
28b69f6
docs: refresh live PR head inventory
seonghobae Aug 21, 2026
57f0cba
docs: refresh exact-head PR baseline
seonghobae Aug 21, 2026
babdb4f
docs: record stacked lockfile remediation state
seonghobae Aug 21, 2026
44f0f74
fix: reconcile Keycloak account profile read-back
seonghobae Aug 21, 2026
4092307
docs: record Keycloak registration remediation
seonghobae Aug 21, 2026
7b0a0c5
docs: refresh live PR queue evidence
seonghobae Aug 21, 2026
641ebe9
docs: record stacked OAuth merge evidence
seonghobae Aug 21, 2026
9a2d806
fix: diagnose missing LineageWeave profile attributes
seonghobae Aug 21, 2026
a92fdcb
docs: record profile bootstrap diagnostics
seonghobae Aug 21, 2026
ede8075
docs: refresh live PR and gap baseline
seonghobae Aug 21, 2026
a360fda
docs: refresh live PR gap evidence
seonghobae Aug 21, 2026
d89d4a6
docs: record fleet lifecycle dependency
seonghobae Aug 21, 2026
d039209
feat: bind hourly gap selection to live queue
seonghobae Aug 21, 2026
50276ff
docs: refresh live queue evidence and OSV RCA
seonghobae Aug 21, 2026
a44370f
docs: synchronize live PR gap baseline
seonghobae Aug 21, 2026
2fd5a77
docs: mark baseline head transition
seonghobae Aug 21, 2026
98c3305
docs: refresh live queue baseline
seonghobae Aug 21, 2026
35b0db0
docs: refresh current control-plane queue
seonghobae Aug 21, 2026
607b120
docs: align queue doctoring head
seonghobae Aug 21, 2026
4ee8689
docs: refresh live PR queue evidence
seonghobae Aug 21, 2026
a2875bc
docs: record current scheduler head
seonghobae Aug 21, 2026
e630eac
docs: bind queue snapshot to current keyverse head
seonghobae Aug 21, 2026
cede667
docs: refresh live hosted queue evidence
seonghobae Aug 21, 2026
c492245
docs: include current central repair stack
seonghobae Aug 21, 2026
2453296
docs: refresh live queue evidence
seonghobae Aug 21, 2026
9c75942
docs: refresh live queue evidence
seonghobae Aug 21, 2026
eb496ba
docs: refresh stacked control-plane evidence
seonghobae Aug 21, 2026
2fbe82a
docs: refresh live PR evidence snapshot
seonghobae Aug 21, 2026
f6a560a
docs: record current central control-plane queue
seonghobae Aug 21, 2026
c70f2cb
docs: bind snapshot to preceding keyverse head
seonghobae Aug 21, 2026
4d0d867
docs: refresh exact control-plane heads
seonghobae Aug 21, 2026
f4f85e9
docs: refresh queued check observations
seonghobae Aug 21, 2026
19ebd86
docs: refresh live control-plane queue
seonghobae Aug 21, 2026
f809c91
docs: refresh exact-head queue evidence
seonghobae Aug 21, 2026
25cf0e6
docs: refresh 2026-08-23 exact-head queue evidence
seonghobae Aug 23, 2026
84e0c75
docs: bind gap baseline to #100 head 25cf0e6
seonghobae Aug 23, 2026
655aaad
docs: bind gap baseline to live #100 head 84e0c75
seonghobae Aug 23, 2026
a1a65b2
docs: bind gap baseline to live #100 head 655aaad
seonghobae Aug 23, 2026
d978e9a
docs: record #100 observation SHA a1a65b2 vs later inventory commit
seonghobae Aug 23, 2026
7ad812b
Merge origin/main into pr-100
seonghobae Aug 31, 2026
e21a8bf
fix(docs): restore RFC 9068 and RFC 9207 after main merge
seonghobae Aug 31, 2026
6de6b65
test(realm): reject malformed user-profile shapes
seonghobae Aug 31, 2026
a473819
fix(realm): fail closed on malformed user profiles
seonghobae Aug 31, 2026
6a2af55
test(docs): require explicit current queue snapshot
seonghobae Aug 31, 2026
29a78ed
test(docs): stop treating dated snapshot as current
seonghobae Aug 31, 2026
8a61373
fix(clients): require complete LineageWeave account claims
seonghobae Sep 7, 2026
a782f8a
docs(adr): mark unmerged account claims proposal as proposed
seonghobae Sep 7, 2026
16e903d
Merge remote-tracking branch 'origin/main' into codex/pr100-claims-re…
seonghobae Sep 7, 2026
fe0b39a
fix(ci): retire contracts for removed duplicate PR steward
seonghobae Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
run: |
uv run coverage run --branch --source=app -m pytest -q
uv run coverage report --show-missing --fail-under=100
uv run coverage erase
uv run coverage run --branch -m pytest -q tests/test_validate_realm.py
uv run coverage report --include='*/scripts/validate_realm.py' --show-missing --fail-under=100
Comment thread
seonghobae marked this conversation as resolved.
- name: Build distribution
run: uv build --out-dir dist

Expand All @@ -53,7 +56,7 @@ jobs:
with:
python-version: "3.12"
- name: Validate Keycloak realm config-as-code
run: python scripts/validate_realm.py deploy/keycloak/realm-cwl.json
run: python scripts/validate_realm.py deploy/keycloak/cwl-realm.json
- name: Validate deployment template JSON
run: |
python - <<'PY'
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/hourly-product-development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,9 @@ jobs:
install -d -m 0750 "$agent_workspace" "$agent_home" "$agent_home/tmp"
git archive HEAD | tar -x -C "$agent_workspace"

cat >"${agent_workspace}/opencode.json" <<'CONFIG'
cat >"${agent_workspace}/opencode.json" <<CONFIG
{
"$schema": "https://opencode.ai/config.json",
"\$schema": "https://opencode.ai/config.json",
"enabled_providers": ["nvidia-nim"],
"lsp": false,
"mcp": {},
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -562,7 +562,7 @@ jobs:
NVIDIA_API_KEY=keyverse-local-broker \
OPENCODE_DISABLE_AUTOUPDATE=1 \
/bin/bash -c \
'ulimit -u 256; ulimit -n 1024; cd "$1"; exec opencode run "$2" --model "$3"' \
"ulimit -u 256; ulimit -n 1024; cd \"\$1\"; exec opencode run \"\$2\" --model \"\$3\"" \
bash "$agent_workspace" "$prompt" "$model"; then
sudo pkill -KILL -u 65532 >/dev/null 2>&1 || true
successful_workspace="$agent_workspace"
Expand Down Expand Up @@ -739,9 +739,12 @@ jobs:
uv run coverage erase
uv run coverage run --branch --source=app -m pytest -q
uv run coverage report --show-missing --fail-under=100
uv run coverage erase
uv run coverage run --branch -m pytest -q tests/test_validate_realm.py
uv run coverage report --include='*/scripts/validate_realm.py' --show-missing --fail-under=100
uv build --out-dir dist
)
python scripts/validate_realm.py deploy/keycloak/realm-cwl.json
python scripts/validate_realm.py deploy/keycloak/cwl-realm.json
docker compose -f docker-compose.yml config >/dev/null
while IFS= read -r -d '' template; do
python -m json.tool "$template" >/dev/null
Expand Down
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ queue owner.
- SAML/OIDC preflight performs no metadata/discovery fetch. LDAP preflight
performs no DNS, socket, bind, search, storage, or Keycloak call.
- OIDC relying-party mapper support stays closed: one self-pinned audience plus
only canonical `role`, `org`, and `workspace` hardcoded claims. Do not add
scripts, user attributes, groups, regex, arbitrary claims, new audiences, or
only canonical `role`, `org`, and `workspace` hardcoded claims, except the
ADR-0009 `lineageweave-web` profile which maps only a same-client account role
and the exact `org`/`workspace` account attributes. Do not add scripts,
other user attributes, groups, regex, arbitrary claims, new audiences, or
extra token destinations without a separately reviewed profile and RED test.
- Treat generated Keycloak mapper IDs and vendor ordering as normalization-only
metadata. Unknown, malformed, duplicate, or semantically changed live mappers
Expand Down
22 changes: 13 additions & 9 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,18 @@ redirect/origin/logout policy, public/confidential client consistency, bounded
token metadata, and an exact portable scope set.

An optional closed `protocolMappers` profile carries exactly one self-pinned
`oidc-audience-mapper` plus zero to three canonical hardcoded claims named
`role`, `org`, and `workspace`. Mapper count, names, classes, destinations,
claim values, and ordering are bounded; scripts, user attributes, groups, regex,
arbitrary claims, unknown fields, and credential material are rejected.
`deploy/templates/oidc-rp-naruon.json` is the reviewed public-client instance of
that profile. Its routing claim values are deployment data and must not contain
credentials or personal secrets.
`oidc-audience-mapper` plus either zero to three canonical hardcoded claims or
the ADR-0009 LineageWeave account-derived trio. The latter is limited to a
same-client `oidc-usermodel-client-role-mapper` for multivalued `role` and two
scalar `oidc-usermodel-attribute-mapper` entries from exact `org` and
`workspace` account attributes. The three dynamic claims must appear together
and cannot mix with hardcoded claims. Mapper count, names, classes,
destinations, claim values, and ordering are bounded; scripts, other user
attributes, groups, regex, arbitrary claims, unknown fields, and credential
material are rejected. `deploy/templates/oidc-rp-naruon.json` is the reviewed
public-client instance of the static profile; `deploy/templates/oidc-rp-lineageweave.json`
is the confidential account-derived contract. Neither template contains a
credential or proves a live account login.

Stateful reconciliation keys intent by validated `clientId`, classifies zero,
one, or multiple exact Keycloak clients, and never mutates duplicates. Create or
Expand All @@ -172,8 +177,7 @@ The accepted representation has no client-secret field; credential provisioning
remains an independent secret-management responsibility.

Native loopback/private-use redirects, different resource audiences, and claim
expansion beyond `role`, `org`, and `workspace` remain separate reviewed
profiles.
expansion beyond the two closed profiles remain separate reviewed profiles.

Each downstream RP is a separate trust boundary. The RP must validate the
Keyverse issuer, signature/algorithm, expiry, subject, and audience, map the
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Keep a Changelog, and releases use semantic versioning.
access-token audience, bounded `role`, `org`, and `workspace` hardcoded claims,
canonical mapper ordering, Keycloak-generated-ID/order normalization, and a
secret-free `naruon-web` runtime desired-state template.
- ADR-0009's confidential `lineageweave-web` account-derived mapper profile:
same-client roles plus exact scalar `org` and `workspace` account attributes,
with no static/dynamic mixing, a secret-free deployment template, and
reconciliation regression coverage.
- Durable, secret-free OIDC relying-party desired-state CRUD and reconciliation
with exact `clientId` matching, duplicate fail-closed behavior, post-mutation
re-observation, canonical apply receipts, realm-rebuild recovery, per-client
Expand Down Expand Up @@ -55,6 +59,13 @@ Keep a Changelog, and releases use semantic versioning.

### Changed

- The Helm realm-import operator runbook now migrates the legacy
`realm-cwl.json` ConfigMap key to `cwl-realm.json` before rollout, preserving
a rollback copy and requiring post-rollout realm discovery verification.
- Account-derived OIDC claim mappers are now limited to the ADR-0009
`lineageweave-web` profile, and a non-string observed mapper type is treated
as reconciliation drift rather than causing an exception. Operator guides now
consistently name issued `org` (company) and `workspace` (PU) claims.
- Relying-party deployment controllers now send validated, secret-free metadata
to Keyverse desired-state PUT instead of applying client representations
directly to Keycloak; confidential credential placement remains a separate
Expand Down Expand Up @@ -89,6 +100,9 @@ Keep a Changelog, and releases use semantic versioning.

### Fixed

- Packaged the portable Keycloak realm under the required `cwl-realm.json`
directory-import name in Compose and mapped it in Helm, with a deployment
contract that prevents a healthy-but-empty identity realm.
- Prevented relying-party inventory from silently accepting a KV key/body
identity mismatch, rejected unsafe live or `Location`-derived client UUIDs,
and aligned exact client discovery with Keycloak's documented
Expand Down
18 changes: 10 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ make ready # poll readiness (deploy/scripts/healthz.sh)
make install # install the admin service development environment
make test # run account-unification unit tests
make lint # run Ruff + interrogate docstring coverage
make validate-realm # validate deploy/keycloak/realm-cwl.json
make validate-realm # validate deploy/keycloak/cwl-realm.json
make seed-bootstrap # create a local SQLite KV bootstrap store
```

Expand Down Expand Up @@ -110,10 +110,11 @@ is required by the normal suite.
`kcadm-bootstrap.sh`. The realm contains no employer-specific federation.
- `deploy/templates/` — explicit private deployment contracts. SAML/OIDC use
Keyverse desired-state endpoints. `oidc-rp-naruon.json` is the reviewed public
Naruon runtime RP profile with one audience mapper and bounded routing claims.
LDAP is preflighted through Keyverse and then applied through private Keycloak
Admin REST in this release. All `{{placeholders}}` are resolved from KV before
use.
Naruon runtime profile; `oidc-rp-lineageweave.json` is the ADR-0009
confidential profile that projects an account's same-client role and exact
`org`/`workspace` attributes. LDAP is preflighted through Keyverse and then
applied through private Keycloak Admin REST in this release. All
`{{placeholders}}` are resolved from KV before use.
- `deploy/bootstrap/` — the bootstrap pointer locating the KV/DB config store.
- `helm/cwl-idp/` — the same three components; Keycloak and Postgres may be
disabled in favor of externally managed services. Secrets come from
Expand Down Expand Up @@ -142,9 +143,10 @@ is required by the normal suite.
- **OIDC relying-party metadata is secret-free desired state.** Validate with
`POST /clients/relying-parties:validate`, persist with `PUT`, and require exact
post-mutation observation before accepting a receipt. The optional mapper
profile permits exactly one audience mapper plus only canonical `role`, `org`,
and `workspace` hardcoded claims. Never expand mapper classes, claim names,
resource audiences, or token destinations by configuration alone.
profile permits static canonical claims, plus the separately reviewed
ADR-0009 `lineageweave-web` account-derived profile. Never expand mapper
classes, claim names, resource audiences, or token destinations by
configuration alone.
- **Treat mapper normalization narrowly.** Ignore only a valid generated mapper
`id` and canonicalize known mapper order. Unknown, malformed, duplicate, or
semantically changed live mapper state is drift. Mapper configuration does not
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ seed-bootstrap: ## Create a local sqlite KV bootstrap store for dev
python $(SERVICE_DIR)/tools/seed_config_store.py

validate-realm: ## Validate the Keycloak realm config-as-code
python scripts/validate_realm.py deploy/keycloak/realm-cwl.json
python scripts/validate_realm.py deploy/keycloak/cwl-realm.json

install: ## Install the admin service with dev extras
cd $(SERVICE_DIR) && python -m pip install -e '.[dev]'
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,15 @@ docker compose up -d # or: podman compose up -d
- Admin service health: `http://localhost:8099/healthz`

The stack imports the **passwordless-first** realm at first start
(`deploy/keycloak/realm-cwl.json`): a `browser-passwordless` flow with a
(`deploy/keycloak/cwl-realm.json`): a `browser-passwordless` flow with a
WebAuthn passwordless authenticator and **no password authenticator**, plus
`registrationAllowed:false` / `resetPasswordAllowed:false`.

For Helm installations created with the former `realm-cwl.json` ConfigMap key,
perform the zero-gap key migration in
[`deploy/keycloak/README.md`](deploy/keycloak/README.md#helm-configmap-key-migration)
before upgrading the chart.

### Register external federation

The portable realm contains no employer ADFS, LDAP/AD source, or other
Expand All @@ -96,6 +101,10 @@ See [`docs/federation-onboarding.md`](docs/federation-onboarding.md),
### Onboard a relying party

See [`docs/rp-onboarding.md`](docs/rp-onboarding.md).
The ADR-0009 LineageWeave profile uses real account-derived `role`, `org`
(company), and `workspace` (PU) claims; it is not enabled until private Keyverse
apply and controlled
downstream authorization evidence are recorded.

## Account unification & merge

Expand Down
7 changes: 7 additions & 0 deletions deploy/keycloak/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM quay.io/keycloak/keycloak:26.3.2@sha256:98fab020a3a490aba0978f237e2a06cd0ea42bf149c6cf10f11c0aaf27728ff2
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed

# Keycloak directory import recognizes <realm>-realm.json at container start.
COPY cwl-realm.json /opt/keycloak/data/import/cwl-realm.json
COPY lineageweave-user-profile.json /opt/keycloak/lineageweave-user-profile.json
COPY --chmod=755 reconcile-lineageweave-user-profile.sh /opt/keycloak/reconcile-lineageweave-user-profile.sh
USER 1000
41 changes: 40 additions & 1 deletion deploy/keycloak/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ providers are converged afterwards from the KV/DB source of truth.

| File | Responsibility |
| --- | --- |
| `realm-cwl.json` | Portable passwordless realm, shared client scopes, RP template, concrete `naruon-web` PKCE client, and account-unification service client |
| `cwl-realm.json` | Portable passwordless realm, shared client scopes, RP template, concrete `naruon-web` PKCE client, and account-unification service client |
| `kcadm-bootstrap.sh` | Idempotently inject the service-client secret, grant least-privilege realm-management roles, and reconcile the role mapper |
| `../templates/` | Reference payloads for runtime federation and additional relying-party registrations |

Expand Down Expand Up @@ -58,6 +58,45 @@ URLs or invalid placeholder LDAP distinguished names.
than 900 seconds;
- committed client secrets are placeholders only.

## Helm ConfigMap key migration

Older Helm installations used the ConfigMap data key `realm-cwl.json`. The
current chart requires the source key `cwl-realm.json` and mounts it at the
Keycloak-required target filename of the same name. Add the new key **before**
upgrading the StatefulSet so an existing Pod never references a missing
ConfigMap item.

```bash
NAMESPACE=identity
RELEASE=cwl-idp
CONFIG_MAP=cwl-idp-realm

# Keep a rollback copy of the dedicated realm-import ConfigMap.
kubectl -n "$NAMESPACE" get configmap "$CONFIG_MAP" -o yaml \
> "${CONFIG_MAP}.before-cwl-realm.yaml"

# Server-side apply adds the new data key without deleting the legacy key first.
kubectl -n "$NAMESPACE" create configmap "$CONFIG_MAP" \
--from-file=cwl-realm.json=deploy/keycloak/cwl-realm.json \
--dry-run=client -o yaml \
| kubectl -n "$NAMESPACE" apply --server-side \
--field-manager=cwl-idp-realm-migration -f -

helm upgrade "$RELEASE" helm/cwl-idp -n "$NAMESPACE" \
--set keycloak.realmImport.configMapName="$CONFIG_MAP" \
--set keycloak.realmImport.fileName=cwl-realm.json
kubectl -n "$NAMESPACE" rollout status statefulset/"${RELEASE}-keycloak"

# Only after the new StatefulSet is healthy may the obsolete source key go.
kubectl -n "$NAMESPACE" patch configmap "$CONFIG_MAP" --type=json \
--patch='[{"op":"remove","path":"/data/realm-cwl.json"}]'
```

This ConfigMap is dedicated to realm import. If a deployment added unrelated
keys, preserve or relocate them under its own ownership before the migration.
Verify the `cwl` realm discovery endpoint after rollout; container health alone
does not prove import succeeded.

## RP clients

`ecosystem-rp-template` is a confidential PKCE S256 blueprint. It uses the
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion deploy/keycloak/kcadm-bootstrap.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# cwl-idp — Keycloak post-import bootstrap (config-as-code, secrets from KV).
#
# The realm SHAPE lives in realm-cwl.json and is imported at container start.
# The realm SHAPE lives in cwl-realm.json and is imported at container start.
# This script patches the pieces that must NOT be committed (secrets, env URLs)
# by reading them from the KV store and applying them with Keycloak's admin CLI
# (`kcadm.sh`, shipped in the Keycloak image, Apache-2.0). Run it after the realm
Expand Down
Loading
Loading