The seeded local admin is now the shared-model user
web-app-semaphore-breakglass (login breakglass-administrator, password =
ansible_become_password, accounts: [] so it is never provisioned to
LDAP/Keycloak, forward: administrator so its mail lands in the administrator
mailbox). SEMAPHORE_ADMIN_* read that user via lookup('users'); README and
variant table updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implements requirement 028: web-app-semaphore deploying semaphoreui/semaphore
v2.18.13 behind sys-svc-proxy with central PostgreSQL, native Keycloak OIDC
SSO, and LDAP login, plus guest/biber/administrator Playwright personas.
Auth/admin model verified against the upstream v2.18.13 source (config.go,
api/login.go, api/router.go, web/src/views/Auth.vue, config.schema.yaml,
cli/cmd/user_add.go): the OIDC callback matches by email and rejects local
users, the login form is LDAP-only when ldap_enable=true, and OIDC users are
never admin from a claim. The role therefore seeds a distinct break-glass
local admin and creates the Keycloak administrator as an external admin at
deploy time (semaphore user add --admin --external). Correct v2.x env names
(SEMAPHORE_LDAP_ENABLE/_SERVER/_BIND_DN/_BIND_PASSWORD/_SEARCH_DN, OIDC
provider JSON) confirmed against the source.
Validation: make autoformat clean; make test green (lint, test-lint,
test-unit, test-integration 190, test-external). Live full-matrix deploy +
Playwright still pending (host container runtime fault, environment-only).
Refs: docs/requirements/028-web-app-semaphore.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>