TOK-1: Tokens migrate into the secret table #757

Closed
opened 2026-05-02 17:27:50 +00:00 by claude-desktop · 0 comments
Collaborator

As a platform engineer, I want every per-agent forge token currently living at ~/.config/claude-hooks/tokens/<agent> to get a row in the SC-6 secret table referenced from agent_type.token_secret_id, so that token bytes never sit in plaintext on disk and rotation runs through the same encrypted-secret + access-log surface as every other secret.

Acceptance criteria

Migration

  • On first boot post-deploy, a one-shot migration sweep reads every existing tokens/<agent> file, writes the bytes to secret, sets agent_type.token_secret_id (or per-instance override row if present), and renames the file to tokens/.<agent>.migrated.bak (operator inspectable, not auto-deleted).
  • The migration is idempotent: a re-run after the rename is a no-op.

Resolver

  • getAgentToken(typeName) reads through the SC-6 secret resolver with access logging.
  • The plaintext token_file path on agents.json is deprecated; the builtin-sync writes the contents into the secret table on first boot then ignores the path on subsequent boots.

Tests

  • Unit: migration is idempotent.
  • Integration: a token rotated at scope='agent_type' via the dashboard is picked up by the next dispatch's Forgejo client without a restart.

Out of scope

  • Per-instance token override — covered by TOK-3.
  • Filesystem-read removal from the runtime — covered by TOK-2.

References

  • Spec: specs/config-to-db.md § Story TOK-1.
  • Precedent: SC-6 — encrypted secrets + access log.
  • Blocked by: AT-1.
As a platform engineer, I want every per-agent forge token currently living at `~/.config/claude-hooks/tokens/<agent>` to get a row in the SC-6 `secret` table referenced from `agent_type.token_secret_id`, so that token bytes never sit in plaintext on disk and rotation runs through the same encrypted-secret + access-log surface as every other secret. ## Acceptance criteria ### Migration - [ ] On first boot post-deploy, a one-shot migration sweep reads every existing `tokens/<agent>` file, writes the bytes to `secret`, sets `agent_type.token_secret_id` (or per-instance override row if present), and renames the file to `tokens/.<agent>.migrated.bak` (operator inspectable, not auto-deleted). - [ ] The migration is idempotent: a re-run after the rename is a no-op. ### Resolver - [ ] `getAgentToken(typeName)` reads through the SC-6 secret resolver with access logging. - [ ] The plaintext `token_file` path on agents.json is deprecated; the builtin-sync writes the contents into the `secret` table on first boot then ignores the path on subsequent boots. ### Tests - [ ] Unit: migration is idempotent. - [ ] Integration: a token rotated at `scope='agent_type'` via the dashboard is picked up by the next dispatch's Forgejo client without a restart. ## Out of scope - Per-instance token override — covered by TOK-3. - Filesystem-read removal from the runtime — covered by TOK-2. ## References - Spec: `specs/config-to-db.md` § Story TOK-1. - Precedent: SC-6 — encrypted secrets + access log. - Blocked by: AT-1.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#757
No description provided.