Supersedes #20. The original cmd/server/main.go redaction for BRAIN_PG_DSN was wrong — it sliced up to @, which is after the password in a Postgres URL, so the password landed in the structured log line of the ingestion pod under image 7a13c756... on 2026-05-18 → 2026-05-19. Fixed in 4af10364 via url.URL.Redacted(). Old log lines remain in kubectl logs --previous history and any sink container logs ship to until retention rolls off (typically 7–14 days; longer if shipped to a SIEM).
Since #20 was filed, External Secrets Operator + 1Password Connect went live (ClusterSecretStore/onepassword, HomeLab vault). BRAIN_PG_DSN is still on the old SOPS path (k3s/apps/supervisor/secrets.enc.yaml) and referenced as secretKeyRef: supervisor-secrets in ingestion-deployment.yaml. Rotate + migrate in the same change so future rotations are 1P-only with no git commit needed.
New brain_app password generated, full DSN stored only in 1Password HomeLab vault
BRAIN_PG_DSN removed from secrets.enc.yaml
kubectl get externalsecret -n supervisor brain-pg-dsn shows SecretSynced=True
Pod restart picks up the new DSN cleanly (brain hybrid retrieval enabled log line, no auth errors)
/tmp/brain_app_pg.pwd deleted
Optional: extra kubectl delete pod after retention concern eases to flush leaked log lines sooner
Follow-up (out of scope)
Migrate CLAUDE_INGEST_CLIENT_BLOCK to 1Password, retire secrets.enc.yaml entirely.
Severity
Low — the leak was internal-only (kubectl logs require cluster admin), and the affected DB sits behind Tailscale. Worth doing as hygiene, not urgent. Migration win is the real value: future rotations become a 1P field edit, no commit.
## Context
Supersedes #20. The original `cmd/server/main.go` redaction for `BRAIN_PG_DSN` was wrong — it sliced up to `@`, which is *after* the password in a Postgres URL, so the password landed in the structured log line of the ingestion pod under image `7a13c756...` on 2026-05-18 → 2026-05-19. Fixed in `4af10364` via `url.URL.Redacted()`. Old log lines remain in `kubectl logs --previous` history and any sink container logs ship to until retention rolls off (typically 7–14 days; longer if shipped to a SIEM).
Since #20 was filed, External Secrets Operator + 1Password Connect went live (`ClusterSecretStore/onepassword`, HomeLab vault). `BRAIN_PG_DSN` is still on the old SOPS path (`k3s/apps/supervisor/secrets.enc.yaml`) and referenced as `secretKeyRef: supervisor-secrets` in `ingestion-deployment.yaml`. Rotate + migrate in the same change so future rotations are 1P-only with no git commit needed.
## Action
1. Generate new password:
```bash
umask 077 && openssl rand -hex 24 > /tmp/brain_app_pg.pwd
```
2. Apply via init SQL (idempotent `ALTER ROLE`):
```bash
kubectl exec -i -n databases postgres18-0 -- \
psql -U postgres -v password="$(cat /tmp/brain_app_pg.pwd)" \
< scripts/brain-embeddings-init.sql
```
(Bare value, no surrounding single quotes — `:'password'` does its own quoting.)
3. Store the full DSN in 1Password — vault `HomeLab`, item `BRAIN_PG_DSN`, field `password`:
```
postgres://brain_app:<new-pwd>@postgres18.databases.svc.cluster.local:5432/brain?sslmode=disable
```
4. Create `k3s/apps/supervisor/brain-pg-dsn-externalsecret.yaml` mirroring `brain-mcp-token-externalsecret.yaml`:
```yaml
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: brain-pg-dsn
namespace: supervisor
spec:
refreshInterval: 1h
secretStoreRef:
name: onepassword
kind: ClusterSecretStore
target:
name: brain-pg-dsn
creationPolicy: Owner
data:
- secretKey: BRAIN_PG_DSN
remoteRef:
key: BRAIN_PG_DSN
property: password
```
5. Update `ingestion-deployment.yaml` BRAIN_PG_DSN env block: `secretKeyRef.name: supervisor-secrets` → `brain-pg-dsn`.
6. Remove `BRAIN_PG_DSN` from `k3s/apps/supervisor/secrets.enc.yaml` (re-sops without the key; `CLAUDE_INGEST_CLIENT_BLOCK` stays — separate migration).
7. Add the new ExternalSecret to `k3s/apps/supervisor/kustomization.yaml`.
8. Bump `secrets-revision` annotation on `ingestion-deployment.yaml` to roll the pod.
9. Commit (one logical change), watch Flux reconcile (`flux get kustomization apps --watch`).
10. `rm /tmp/brain_app_pg.pwd`.
## Acceptance criteria
- [ ] New `brain_app` password generated, full DSN stored only in 1Password HomeLab vault
- [ ] `BRAIN_PG_DSN` removed from `secrets.enc.yaml`
- [ ] `kubectl get externalsecret -n supervisor brain-pg-dsn` shows `SecretSynced=True`
- [ ] Pod restart picks up the new DSN cleanly (`brain hybrid retrieval enabled` log line, no auth errors)
- [ ] `/tmp/brain_app_pg.pwd` deleted
- [ ] Optional: extra `kubectl delete pod` after retention concern eases to flush leaked log lines sooner
## Follow-up (out of scope)
- Migrate `CLAUDE_INGEST_CLIENT_BLOCK` to 1Password, retire `secrets.enc.yaml` entirely.
## Severity
Low — the leak was internal-only (kubectl logs require cluster admin), and the affected DB sits behind Tailscale. Worth doing as hygiene, not urgent. Migration win is the real value: future rotations become a 1P field edit, no commit.
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.
Context
Supersedes #20. The original
cmd/server/main.goredaction forBRAIN_PG_DSNwas wrong — it sliced up to@, which is after the password in a Postgres URL, so the password landed in the structured log line of the ingestion pod under image7a13c756...on 2026-05-18 → 2026-05-19. Fixed in4af10364viaurl.URL.Redacted(). Old log lines remain inkubectl logs --previoushistory and any sink container logs ship to until retention rolls off (typically 7–14 days; longer if shipped to a SIEM).Since #20 was filed, External Secrets Operator + 1Password Connect went live (
ClusterSecretStore/onepassword, HomeLab vault).BRAIN_PG_DSNis still on the old SOPS path (k3s/apps/supervisor/secrets.enc.yaml) and referenced assecretKeyRef: supervisor-secretsiningestion-deployment.yaml. Rotate + migrate in the same change so future rotations are 1P-only with no git commit needed.Action
ALTER ROLE)::'password'does its own quoting.)HomeLab, itemBRAIN_PG_DSN, fieldpassword:k3s/apps/supervisor/brain-pg-dsn-externalsecret.yamlmirroringbrain-mcp-token-externalsecret.yaml:ingestion-deployment.yamlBRAIN_PG_DSN env block:secretKeyRef.name: supervisor-secrets→brain-pg-dsn.BRAIN_PG_DSNfromk3s/apps/supervisor/secrets.enc.yaml(re-sops without the key;CLAUDE_INGEST_CLIENT_BLOCKstays — separate migration).k3s/apps/supervisor/kustomization.yaml.secrets-revisionannotation oningestion-deployment.yamlto roll the pod.flux get kustomization apps --watch).rm /tmp/brain_app_pg.pwd.Acceptance criteria
brain_apppassword generated, full DSN stored only in 1Password HomeLab vaultBRAIN_PG_DSNremoved fromsecrets.enc.yamlkubectl get externalsecret -n supervisor brain-pg-dsnshowsSecretSynced=Truebrain hybrid retrieval enabledlog line, no auth errors)/tmp/brain_app_pg.pwddeletedkubectl delete podafter retention concern eases to flush leaked log lines soonerFollow-up (out of scope)
CLAUDE_INGEST_CLIENT_BLOCKto 1Password, retiresecrets.enc.yamlentirely.Severity
Low — the leak was internal-only (kubectl logs require cluster admin), and the affected DB sits behind Tailscale. Worth doing as hygiene, not urgent. Migration win is the real value: future rotations become a 1P field edit, no commit.
Done — commit
b048594on infra/main.ALTER ROLE brain_appinpostgres18-0, verified withpsql -U brain_app -d brain(1 row)BRAIN_PG_DSN, fieldpasswordbrain-pg-dsnExternalSecret reconciledSecretSynced=TrueBRAIN_PG_DSNremoved fromsecrets.enc.yaml,CLAUDE_INGEST_CLIENT_BLOCKretainedbrain hybrid retrieval enabledwith redacted DSN (xxxxx)embed sync added=14 deleted=0 errors=0— DB writes workingappsKustomizationReady=Trueat revisionb0485949/tmp/brain_app_pg.pwdshreddedAcceptance criteria met. Closing.
Follow-up: migrate
CLAUDE_INGEST_CLIENT_BLOCKto 1P and retiresecrets.enc.yaml(separate issue).