feat(secrets): migrate Penpot token from plaintext file to secret table #826
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!826
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/agent-tokens-to-secrets"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes one of three slices of #823. Branch name says
agent-tokensfor historical reasons (initial scope) — actual scope reduced to Penpot only after discovering TOK-1/TOK-2 already migrated per-agent Forgejo tokens to thesecrettable under theFORGEJO_TOKEN_<TYPE>name pattern.Summary
The Penpot API token moves from
~/.config/claude-hooks/penpot-token(plaintext, mode 0600) to the existing AES-256-GCM-encryptedsecrettable under namePENPOT_TOKEN. Idempotent migration014ports any existing file into the DB on first boot and renames the source to.penpot-token.migrated.bak(matching the TOK-1 pattern; notunlinkso a panicked operator can recover).The boot-time read in
main.tsnow resolves the secret viagetSecretRowByName("PENPOT_TOKEN") + decryptSyncand feedssetPenpotMcpConfig. The container / agent-env-sync render layer already substitutes${SECRET:PENPOT_TOKEN}placeholders, so the in-container designer / design-reviewer flows pick up the same value with no further code change.Plus dead-reference cleanup: comments and tests still pointing at the removed
~/.config/claude-hooks/tokens/<agent>files now match reality (TOK-1 migrated those long ago).Changes
apps/server/src/infrastructure/database/migrations/014-migrate-penpot-token-to-secret.ts(new).apps/server/src/infrastructure/database/migrations/014-migrate-penpot-token-to-secret.test.ts(new).apps/server/src/infrastructure/database/db.ts— wired migration 014 intoensureSchema().apps/server/src/main.ts— boot path swap (getSecretRowByName("PENPOT_TOKEN") + decryptSyncwithboot:penpotaccessor).apps/server/src/infrastructure/container/container.ts— comment cleanup; dropped deadhostTokenPathhelper.apps/server/src/infrastructure/container/container.test.ts— dropped thehostTokenPathdescribe.apps/server/src/domain/agent/agent-runner.test.ts— removed thetokens/bossdenied-list entry.justfile— added one-line "lifted into secret table" comments above the operator-fallback bash inlabels-bootstrapanddeps-backfill. Kept the actual fallback since it's still useful for fresh manual token drops by the operator (post TOK-1 the migratedtokens/.<agent>.migrated.bakfiles don't match thels -1glob so the fallback is silently dead but not wrong).docs/credentials.md— added a migrated-secrets table covering bothFORGEJO_TOKEN_<TYPE>(TOK-1) and the newPENPOT_TOKEN.Test plan
just qaclean from project root~/.config/claude-hooks/penpot-tokenand confirm row +.bakrename${SECRET:PENPOT_TOKEN}substitution still resolves (in-container path)🤖 Generated with Claude Code
1ceefd88e2579345154757934515473ecd2fb7273ecd2fb72776ba3ad0c6CI green. Migration 014 correctly guards on row-already-present, file-missing, file-empty, and encrypt-failed; renames to
.bakbest-effort.sessions.tsSQLite port is clean — LIKE escaping indropAllForIssueis the right fix. Test coverage is thorough across both migrations.76ba3ad0c676c25c6155PR has conflicts — please rebase on main before merging.