Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P Assistant: claude-code Assistant-Model: opus Assistant-Process: 713576@bnt-lap001 Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
123 lines
4.5 KiB
Markdown
123 lines
4.5 KiB
Markdown
---
|
|
id: KEY-WP-0026
|
|
type: workplan
|
|
title: "Reconcile packaging, bootstrap and migration credential handling"
|
|
domain: infotech
|
|
repo: key-cape
|
|
status: finished
|
|
owner: claude
|
|
topic_slug: packaging-bootstrap-and-credential-handling
|
|
created: "2026-09-08"
|
|
updated: "2026-09-08"
|
|
state_hub_workstream_id: "d2b04d59-41b1-531b-8cab-a980328611b4"
|
|
---
|
|
|
|
Closes gap G09. Five separate defects, only loosely related: the dev stack could
|
|
not start from a clean checkout, the image shipped one binary of five, the
|
|
publish workflow named a different registry than the one the cluster pulls from,
|
|
the exporter took a password on argv, and every migration artifact was written
|
|
world-readable.
|
|
|
|
## Take the bind password off argv
|
|
|
|
```task
|
|
id: KEY-WP-0026-T01
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "510a4603-337f-5ceb-b6b7-b9126d8605f0"
|
|
```
|
|
|
|
`lldap-export` took `--bind-pw`, so the service account password was visible to
|
|
any local user through `ps`, and captured by shell history and process
|
|
accounting. It now prefers `KEYCAPE_LLDAP_BIND_PW`, accepts `--bind-pw-file`, and
|
|
keeps `--bind-pw` working with a warning — deprecated rather than removed,
|
|
because existing runbooks use it and silently breaking them would be worse than
|
|
the exposure for one more cycle.
|
|
|
|
Conflicting sources are rejected rather than silently ranked: with two supplied,
|
|
an operator cannot tell which bind was attempted. A password file has its
|
|
trailing newline trimmed, since editors and heredocs add one and binding with it
|
|
fails confusingly. Both migration scripts now pass the password by environment.
|
|
|
|
## Stop writing migration artifacts world-readable
|
|
|
|
```task
|
|
id: KEY-WP-0026-T02
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "679e21a1-e37b-574b-bc25-b9fd46bdfd16"
|
|
```
|
|
|
|
The canonical export, the generated LDIF and the Keycloak realm were all written
|
|
`0644`. None carries credential material, but the snapshot is a directory dump —
|
|
every username, display name, email and group membership in the estate — and it
|
|
tended to land in `/tmp`. All three are `0600` now.
|
|
|
|
## Ship every binary in the image
|
|
|
|
```task
|
|
id: KEY-WP-0026-T03
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "5252a13c-cd5d-5686-a7f5-04587d7d9b1d"
|
|
```
|
|
|
|
The image packaged `keycape` alone, so the validator and the three migration
|
|
binaries needed a Go toolchain on the host — which defeats shipping an image for
|
|
the cutover work they exist to support. All five are built and copied; the issuer
|
|
remains the entrypoint and the rest are reachable by overriding it. Verified by
|
|
building the image and running each binary inside it.
|
|
|
|
## Reconcile the publish target
|
|
|
|
```task
|
|
id: KEY-WP-0026-T04
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "45b8c386-41bd-514c-9247-5eba9663d8fb"
|
|
```
|
|
|
|
The workflow published to `92.205.130.254:32166/coulomb/key-cape` while the
|
|
cluster runs `forgejo.coulomb.social/coulomb/key-cape` (KEY-WP-0013). Whether
|
|
those are one registry behind two names or two registries is not determinable
|
|
from this repository, which is exactly the problem: a push could not be assumed
|
|
to have deployed the current source. Now defaults to the recorded Forgejo name
|
|
and stays overridable through a repository variable.
|
|
|
|
**Unverified, and needs an operator's eye:** this repository cannot test that the
|
|
runner resolves that hostname or that `REGISTRY_USER`/`REGISTRY_TOKEN` are valid
|
|
for it. If the next publish fails, set the `REGISTRY` repository variable back to
|
|
the address.
|
|
|
|
## Make the dev stack bootstrappable
|
|
|
|
```task
|
|
id: KEY-WP-0026-T05
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "a750ac2f-cad2-5e7f-a505-2ca6b94f1a5a"
|
|
```
|
|
|
|
`docker-compose.dev.yml` mounts `config/dev-key.pem` and `config/authelia/`,
|
|
neither in the checkout — correctly, since one is a private key and the other
|
|
carries a password hash. `scripts/bootstrap-dev.sh` generates both locally: an
|
|
RSA key created under `umask 077` rather than chmodded afterwards, so it is never
|
|
briefly world-readable, plus an Authelia configuration, its OIDC signing key and
|
|
a user fixture. Everything it writes is git-ignored, and re-running it leaves
|
|
existing material alone.
|
|
|
|
The fixture password is published in the script deliberately: a reader can see
|
|
exactly what it unlocks, which is nothing deployed.
|
|
|
|
## Reconcile the records
|
|
|
|
```task
|
|
id: KEY-WP-0026-T06
|
|
status: done
|
|
priority: medium
|
|
state_hub_task_id: "cc7c86ae-9c78-5422-8f3c-19441ceeb513"
|
|
```
|
|
|
|
`SCOPE.md` and G09's status record what is fixed and what is not: the registry
|
|
change is unverified from here, and a documented external bootstrap remains the
|
|
route for anything beyond development.
|