Thin SpikerSoft.Secrets provider in EventHandlerHostBuilder.WithConfiguration (+ API host): Secrets:UseBao flag, AppRole login, pull Storage__SecretKey-class values + RabbitMQ/Mongo/Redis creds into IConfiguration at startup with env-var fallback (the #493 dual-run pattern — flag off = today's behavior byte-for-byte). Kills the appsettings dockerUser/dockerPassword defaults. VaultSharp or raw HTTP (mirror the #533 seam sizing discussion).
Thin SpikerSoft.Secrets provider in EventHandlerHostBuilder.WithConfiguration (+ API host): Secrets:UseBao flag, AppRole login, pull Storage__SecretKey-class values + RabbitMQ/Mongo/Redis creds into IConfiguration at startup with env-var fallback (the #493 dual-run pattern — flag off = today's behavior byte-for-byte). Kills the appsettings dockerUser/dockerPassword defaults. VaultSharp or raw HTTP (mirror the #533 seam sizing discussion).
Phase 2 seam is up for review: spikersoft-backend PR #270. New SpikerSoft.Secrets project (ISecretSource + VaultSecretSource: AppRole login + KV v2 over plain HttpClient, zero new NuGet deps) with an AddBaoSecrets() configuration overlay — Secrets:UseBao=false by default, so it is completely inert and safe to merge while the vault is uninitialized; flag-on with the vault down/sealed logs loudly and falls back to env (Strict opt-in for fail-fast). Piloted on EventHandlers.Scheduler only via the existing ConfigureConfiguration hook to avoid the #256 fleet Dockerfile sweep; 17 new unit tests pass locally plus a clean full-solution build. Follow-ups noted in the PR: provision a svc-scheduler AppRole + populate secret/services/*, then fleet rollout + killing the committed dockerUser/dockerPassword defaults. — macbook-claude-session
Phase 2 seam is up for review: spikersoft-backend PR [#270](https://git.spikersoft.com/spikerj/spikersoft-backend/pulls/270). New `SpikerSoft.Secrets` project (ISecretSource + VaultSecretSource: AppRole login + KV v2 over plain HttpClient, zero new NuGet deps) with an `AddBaoSecrets()` configuration overlay — `Secrets:UseBao=false` by default, so it is completely inert and safe to merge while the vault is uninitialized; flag-on with the vault down/sealed logs loudly and falls back to env (Strict opt-in for fail-fast). Piloted on EventHandlers.Scheduler only via the existing ConfigureConfiguration hook to avoid the #256 fleet Dockerfile sweep; 17 new unit tests pass locally plus a clean full-solution build. Follow-ups noted in the PR: provision a svc-scheduler AppRole + populate secret/services/*, then fleet rollout + killing the committed dockerUser/dockerPassword defaults. — macbook-claude-session
Phase 2 kicked off — Stage 0 up (spikersoft-backend PR #309). With Phase 0/1 closed the vault is live, so the SpikerSoft.Secrets overlay (built 2026-07-14) can finally be adopted.
Plan (agreed): one shared runtime services AppRole (per-service least-privilege deferred); role_id/secret_id delivered as Docker swarm secrets → /run/secrets/; hide-in-Bao first, rotate the burned values as a separate follow-up (each is a coordinated fleet restart).
Stage 0 (PR #309) — inert host wiring:AddBaoSecrets() now registered centrally in EventHandlerHostBuilder.WithConfiguration() (all ~30 workers) + SpikerSoft.Api/Program.cs, replacing the hand-wired Scheduler pilot. Secrets:UseBao off everywhere → config byte-identical to today (#493), safe no-op merge. slnf builds clean, 17/17 Secrets tests pass.
Remaining stages: 1) infra — services policy+AppRole, docker-secret cred delivery, populate secret/services/shared (RabbitMQ pw + Seq key); 2) flip the Scheduler pilot to the live vault; 3) fleet rollout per service; 4) delete committed appsettings plaintext (+ the notifications docker-stack.yml plaintext) once Bao-served everywhere.
Inventory note: most creds are committed plaintext DEFAULTS in appsettings (not env-injected) incl. real Keycloak/Stripe/Twilio/Encryption/InfluxDB values — the overlay is the first mechanism to hide them. Rotation follow-up will be filed when Stage 4 lands.
**Phase 2 kicked off — Stage 0 up (spikersoft-backend PR #309).** With Phase 0/1 closed the vault is live, so the SpikerSoft.Secrets overlay (built 2026-07-14) can finally be adopted.
**Plan (agreed):** one shared runtime `services` AppRole (per-service least-privilege deferred); role_id/secret_id delivered as Docker swarm secrets → `/run/secrets/`; hide-in-Bao first, **rotate the burned values as a separate follow-up** (each is a coordinated fleet restart).
**Stage 0 (PR #309) — inert host wiring:** `AddBaoSecrets()` now registered centrally in `EventHandlerHostBuilder.WithConfiguration()` (all ~30 workers) + `SpikerSoft.Api/Program.cs`, replacing the hand-wired Scheduler pilot. `Secrets:UseBao` off everywhere → config byte-identical to today (#493), safe no-op merge. slnf builds clean, 17/17 Secrets tests pass.
**Remaining stages:** 1) infra — `services` policy+AppRole, docker-secret cred delivery, populate `secret/services/shared` (RabbitMQ pw + Seq key); 2) flip the Scheduler pilot to the live vault; 3) fleet rollout per service; 4) delete committed appsettings plaintext (+ the notifications docker-stack.yml plaintext) once Bao-served everywhere.
Inventory note: most creds are committed plaintext DEFAULTS in appsettings (not env-injected) incl. real Keycloak/Stripe/Twilio/Encryption/InfluxDB values — the overlay is the first mechanism to hide them. Rotation follow-up will be filed when Stage 4 lands.
Audited against origin/master — the seam itself is adopted fleet-wide, but 6 stacks were left behind and Stage 4 is unswept. Staying open.
Adopted centrally rather than per-service, which is the right shape:
EventHandlers.Infrastructure/Builders/EventHandlerHostBuilder.cs:76 — _builder.Configuration.AddBaoSecrets();, inherited by all ~30 workers.
The three hosts that don't use that builder call it directly: SpikerSoft.Api/Program.cs:53, GpuCoordinator/Program.cs:26, NxCacheServer/Program.cs:27.
Infra: 27 stack files set Secrets__UseBao=true and 26 mount the AppRole creds (e.g. spikersoft-backend/docker-stack.yml:44-45 → Secrets__RoleIdFile=/run/secrets/bao_services_role_id).
Provisioning is scripted: openbao/provision-services-approle.sh creates the shared services policy/AppRole and both swarm secrets.
Gap 1 — six stacks deploy .NET services with no Bao env at all. Comparing the 32 stacks running spikerj/spikersoft images against the 27 carrying Secrets__UseBao: spikersoft-bootstrap, spikersoft-gameserver, spikersoft-gameserver-init, spikersoft-image-description, and — the ones that actually worry me — spikersoft-embeddings/docker-stack-gpu.yml and spikersoft-quiz-generation/docker-stack-gpu.yml.
Those last two are GPU variants of services whose main stack does have the seam. Grepping Secrets__ in either returns nothing. So the base stack is migrated and the GPU variant isn't — which means once Stage 4 blanks the committed plaintext, deploying the GPU variant boots the service with empty credentials, and it'll look like a config bug rather than a missed migration. That's a live trap sitting behind whoever does Stage 4.
Gap 2 — Stage 4 (delete committed plaintext) is not confirmed. It's verified only for SpikerSoft.Api/appsettings.json:8-9 (comment records the 12 API values blanked, UseBao: false for dev). The ~30 worker appsettings.json files have not been swept for residual Keycloak/Stripe/Twilio/Encryption/InfluxDB values. My separate audit on #633 confirms four committed credentials still live in backend appsettings, plus five more I just found in mailserver/docker-stack.yml — so plaintext retirement is demonstrably incomplete.
Gap 3 — comment 7241 promised a rotation follow-up ticket "when Stage 4 lands"; I found no such ticket.
Suggested order: close gap 1 first (two-line change per GPU stack, and it's cheap insurance), then sweep gap 2, then rotate.
Audited against `origin/master` — **the seam itself is adopted fleet-wide, but 6 stacks were left behind and Stage 4 is unswept.** Staying open.
**Adopted centrally rather than per-service, which is the right shape:**
- `EventHandlers.Infrastructure/Builders/EventHandlerHostBuilder.cs:76` — `_builder.Configuration.AddBaoSecrets();`, inherited by all ~30 workers.
- The three hosts that don't use that builder call it directly: `SpikerSoft.Api/Program.cs:53`, `GpuCoordinator/Program.cs:26`, `NxCacheServer/Program.cs:27`.
- Infra: 27 stack files set `Secrets__UseBao=true` and 26 mount the AppRole creds (e.g. `spikersoft-backend/docker-stack.yml:44-45` → `Secrets__RoleIdFile=/run/secrets/bao_services_role_id`).
- Provisioning is scripted: `openbao/provision-services-approle.sh` creates the shared `services` policy/AppRole and both swarm secrets.
**Gap 1 — six stacks deploy .NET services with no Bao env at all.** Comparing the 32 stacks running `spikerj/spikersoft` images against the 27 carrying `Secrets__UseBao`: `spikersoft-bootstrap`, `spikersoft-gameserver`, `spikersoft-gameserver-init`, `spikersoft-image-description`, and — the ones that actually worry me — **`spikersoft-embeddings/docker-stack-gpu.yml` and `spikersoft-quiz-generation/docker-stack-gpu.yml`**.
Those last two are **GPU variants of services whose main stack does have the seam**. Grepping `Secrets__` in either returns nothing. So the base stack is migrated and the GPU variant isn't — which means once Stage 4 blanks the committed plaintext, deploying the GPU variant boots the service with **empty credentials**, and it'll look like a config bug rather than a missed migration. That's a live trap sitting behind whoever does Stage 4.
**Gap 2 — Stage 4 (delete committed plaintext) is not confirmed.** It's verified only for `SpikerSoft.Api/appsettings.json:8-9` (comment records the 12 API values blanked, `UseBao: false` for dev). The ~30 worker `appsettings.json` files have not been swept for residual Keycloak/Stripe/Twilio/Encryption/InfluxDB values. My separate audit on #633 confirms four committed credentials still live in backend appsettings, plus five more I just found in `mailserver/docker-stack.yml` — so plaintext retirement is demonstrably incomplete.
**Gap 3** — comment 7241 promised a rotation follow-up ticket "when Stage 4 lands"; I found no such ticket.
Suggested order: close gap 1 first (two-line change per GPU stack, and it's cheap insurance), then sweep gap 2, then rotate.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Thin SpikerSoft.Secrets provider in EventHandlerHostBuilder.WithConfiguration (+ API host): Secrets:UseBao flag, AppRole login, pull Storage__SecretKey-class values + RabbitMQ/Mongo/Redis creds into IConfiguration at startup with env-var fallback (the #493 dual-run pattern — flag off = today's behavior byte-for-byte). Kills the appsettings dockerUser/dockerPassword defaults. VaultSharp or raw HTTP (mirror the #533 seam sizing discussion).
Phase 2 seam is up for review: spikersoft-backend PR #270. New
SpikerSoft.Secretsproject (ISecretSource + VaultSecretSource: AppRole login + KV v2 over plain HttpClient, zero new NuGet deps) with anAddBaoSecrets()configuration overlay —Secrets:UseBao=falseby default, so it is completely inert and safe to merge while the vault is uninitialized; flag-on with the vault down/sealed logs loudly and falls back to env (Strict opt-in for fail-fast). Piloted on EventHandlers.Scheduler only via the existing ConfigureConfiguration hook to avoid the #256 fleet Dockerfile sweep; 17 new unit tests pass locally plus a clean full-solution build. Follow-ups noted in the PR: provision a svc-scheduler AppRole + populate secret/services/*, then fleet rollout + killing the committed dockerUser/dockerPassword defaults. — macbook-claude-sessionPhase 2 kicked off — Stage 0 up (spikersoft-backend PR #309). With Phase 0/1 closed the vault is live, so the SpikerSoft.Secrets overlay (built 2026-07-14) can finally be adopted.
Plan (agreed): one shared runtime
servicesAppRole (per-service least-privilege deferred); role_id/secret_id delivered as Docker swarm secrets →/run/secrets/; hide-in-Bao first, rotate the burned values as a separate follow-up (each is a coordinated fleet restart).Stage 0 (PR #309) — inert host wiring:
AddBaoSecrets()now registered centrally inEventHandlerHostBuilder.WithConfiguration()(all ~30 workers) +SpikerSoft.Api/Program.cs, replacing the hand-wired Scheduler pilot.Secrets:UseBaooff everywhere → config byte-identical to today (#493), safe no-op merge. slnf builds clean, 17/17 Secrets tests pass.Remaining stages: 1) infra —
servicespolicy+AppRole, docker-secret cred delivery, populatesecret/services/shared(RabbitMQ pw + Seq key); 2) flip the Scheduler pilot to the live vault; 3) fleet rollout per service; 4) delete committed appsettings plaintext (+ the notifications docker-stack.yml plaintext) once Bao-served everywhere.Inventory note: most creds are committed plaintext DEFAULTS in appsettings (not env-injected) incl. real Keycloak/Stripe/Twilio/Encryption/InfluxDB values — the overlay is the first mechanism to hide them. Rotation follow-up will be filed when Stage 4 lands.
Audited against
origin/master— the seam itself is adopted fleet-wide, but 6 stacks were left behind and Stage 4 is unswept. Staying open.Adopted centrally rather than per-service, which is the right shape:
EventHandlers.Infrastructure/Builders/EventHandlerHostBuilder.cs:76—_builder.Configuration.AddBaoSecrets();, inherited by all ~30 workers.SpikerSoft.Api/Program.cs:53,GpuCoordinator/Program.cs:26,NxCacheServer/Program.cs:27.Secrets__UseBao=trueand 26 mount the AppRole creds (e.g.spikersoft-backend/docker-stack.yml:44-45→Secrets__RoleIdFile=/run/secrets/bao_services_role_id).openbao/provision-services-approle.shcreates the sharedservicespolicy/AppRole and both swarm secrets.Gap 1 — six stacks deploy .NET services with no Bao env at all. Comparing the 32 stacks running
spikerj/spikersoftimages against the 27 carryingSecrets__UseBao:spikersoft-bootstrap,spikersoft-gameserver,spikersoft-gameserver-init,spikersoft-image-description, and — the ones that actually worry me —spikersoft-embeddings/docker-stack-gpu.ymlandspikersoft-quiz-generation/docker-stack-gpu.yml.Those last two are GPU variants of services whose main stack does have the seam. Grepping
Secrets__in either returns nothing. So the base stack is migrated and the GPU variant isn't — which means once Stage 4 blanks the committed plaintext, deploying the GPU variant boots the service with empty credentials, and it'll look like a config bug rather than a missed migration. That's a live trap sitting behind whoever does Stage 4.Gap 2 — Stage 4 (delete committed plaintext) is not confirmed. It's verified only for
SpikerSoft.Api/appsettings.json:8-9(comment records the 12 API values blanked,UseBao: falsefor dev). The ~30 workerappsettings.jsonfiles have not been swept for residual Keycloak/Stripe/Twilio/Encryption/InfluxDB values. My separate audit on #633 confirms four committed credentials still live in backend appsettings, plus five more I just found inmailserver/docker-stack.yml— so plaintext retirement is demonstrably incomplete.Gap 3 — comment 7241 promised a rotation follow-up ticket "when Stage 4 lands"; I found no such ticket.
Suggested order: close gap 1 first (two-line change per GPU stack, and it's cheap insurance), then sweep gap 2, then rotate.