Make the LLDAP export report its own completeness
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 31s

The exporter discovered groups by walking each user's memberships, so a group
nobody belongs to never reached the snapshot, and a failed lookup was skipped by
a `continue` under a comment claiming it was recorded in the incompatibility
report. The run then emitted `result: "success"`.

Add an optional `domain.GroupLister` capability and implement `ListGroups` on
the LLDAP adapter as a direct group-subtree search, kept off `UserRepository`
because the OIDC layer never enumerates the directory. Record `groupEnumeration`
on every result and a `Complete()` predicate over it; abort rather than write a
smaller snapshot when the enumeration fails; report a failed per-user lookup on
the fallback path; emit `partial` telemetry and name the mode from the CLI.

Reading the adapter to write this surfaced a defect the assessment had not
listed: `LookupGroups` never populated `Group.Members`, and the exporter built
every membership from that field, so against a real directory the `memberships`
block was always empty while the fixture-backed tests passed. Memberships on the
fallback path now come from the user/group pair actually observed.

Sort users, groups and memberships so an unchanged directory exports
identically. Closes G05 of the scope/intent assessment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012WAsfsfQmDu4vcBhiMcmQp

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 867844@bnt-lap001
Assistant-Session: 3d45905e-0016-4b49-b828-231406881f7b
This commit is contained in:
tegwick 2026-09-07 08:45:50 +02:00
parent 7fe5bccc7c
commit f7dd51b8d2
9 changed files with 538 additions and 43 deletions

View file

@ -25,7 +25,7 @@ Keycloak interchangeability are not established.
| Service authentication | Static confidential `client_credentials` clients authenticated with form-encoded `client_secret_basic`; configured subject, tenant, roles, scopes and per-client token lifetime. Secrets are resolved from environment references at startup. |
| Tokens and identity | Locally signed RS256 JWTs; configurable access-token resource audience while ID tokens retain the client audience; human/service principal types, tenant, groups, roles, scope and assurance claims. UserInfo resolves canonical directory subjects and filters profile/email/groups by scope. |
| Caller commands | `keycape login` for public-client browser PKCE login and `keycape service-token` for service exchange. HTTPS discovery/JWKS verification and private JSON token-file delivery outside Git; no token output on stdout. |
| Validation and migration | Canonical snapshot checks; LLDAP user/group/membership export; basic Keycloak realm JSON; LDIF generation for OpenLDAP, 389 Directory Server and AD targets. These generate artifacts rather than execute a complete migration. |
| Validation and migration | Canonical snapshot checks; deterministic LLDAP user/group/membership export that records whether it enumerated the whole directory; basic Keycloak realm JSON; LDIF generation for OpenLDAP, 389 Directory Server and AD targets. These generate artifacts rather than execute a complete migration. |
| Diagnostics and packaging | Structured authentication/enforcement/migration events, a process health response, Go build/test/vet targets, a container containing the KeyCape binary, and development/CI scaffolding. |
## Material limits
@ -38,6 +38,14 @@ Keycloak interchangeability are not established.
- The optional tenant-engine `tenant_roles` adapter and handler support exist,
but the server entry point does not configure them. That claim is not an
enabled capability of the stock executable.
- The LLDAP export enumerates the group subtree directly, so groups with no
members are present, and every snapshot carries a `groupEnumeration` field
saying whether that enumeration ran or the membership-derived fallback did
(KEY-WP-0018). A failed enumeration aborts the export rather than writing a
smaller snapshot, and read failures are reported rather than skipped. Users,
groups and memberships are sorted, so an unchanged directory exports
identically. Completeness beyond users, groups and memberships — passwords and
MFA credentials in particular — is still not covered.
- The Keycloak CLI exports users/groups through the basic transformer and has
no client-list input. Library-level client mapping does not preserve the full
current service-identity, audience, tenant/role, MFA and lifetime contract.