refactor(config): split agents.json into agents / service / auth files (+ env for secrets) #540
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#540
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
User story
As an operator, I want
config/agents.jsonto hold only agent-fleet configuration (types + per-instance overrides), so that operator-editable fields can't be mistakenly mixed with deploy-time infra and secrets, and the dashboard's/config/agentsPUT surface has a single, narrow blast radius.Why
Audit on 2026-04-28 showed
config/agents.jsonis doing four unrelated jobs:types, per-instance overrides (operator-editable, dashboard surface)forge_mcp_command,container_image,container_image_default,forgejo_url,webhook_secret_file,node_flows,watchdogs,penpot,ui_versionauth.operator_user,auth.trust_proxy,auth.authelia_logout_url,forgejo_oauth_client_id/_secret,github_oauth_client_id/_secret,public_base_urlrepos(already partly migrated to thewatched_reposSQLite table, F4)A single editable file mixing all four creates real risk: an operator hand-editing a type definition can fat-finger an oauth secret, accidentally widen
trust_proxy, or break the gate. The dashboard's PUT handler already has guards but the file shape itself is the problem.Acceptance criteria
Loader
config/service.jsoncarries the service-infra group (item 2 above). Same JSON schema for those fields as today's agents.jsonFORGEJO_OAUTH_CLIENT_ID/FORGEJO_OAUTH_CLIENT_SECRET(env override already exists, make it the only path)GITHUB_OAUTH_CLIENT_ID/GITHUB_OAUTH_CLIENT_SECRETGITLAB_OAUTH_CLIENT_ID/GITLAB_OAUTH_CLIENT_SECRETPUBLIC_BASE_URLWEBHOOK_SECRET(or keepWEBHOOK_SECRET_FILEenv pointing at a file, like the rest of the secret-file pattern)config/agents.jsonretains only:types+ their per-instance overridesauthblock contents — keepoperator_user+trust_proxyonly if a follow-up audit confirms either is still doing useful work post-Authelia rip; otherwise drop the block entirely.authelia_logout_urlalready dead (today's logout rewiring), drop unconditionallyreposfield — assess whether thewatched_reposSQLite table fully replaces it; if yes, drop. If migration incomplete, leave for a follow-up issueMigration mode
agents.jsonstill contains service / auth / repo fields, loader copies them into the resolved config (legacy fallback) AND prints a deprecation warning per field at bootjust config-splitreads the legacyagents.jsonand writesconfig/service.json+ a.env.split.examplefor the secret env vars; backs up the original toagents.json.pre-split.bakTests
webhook-config.test.ts: load a fresh-style split set (agents.jsontypes-only +service.json+ env vars) and assert resolved config matches the legacy single-file equivalentagents.jsonwith service fields → warning printed, config still resolvesOAUTH_ENCRYPTION_KEYand missing OAuth client env vars → service still boots, OAuth init routes return 503 (current behaviour preserved)Dashboard
PUT /config/agentsschema validation rejects any non-types field, returns 400 with a pointer to the new home (env var orservice.json)Docs
docs/configuration.md(new or existing) lists every field, its file/env home, and the operator vs ops ownershipOut of scope
authblock entirely (depends on the post-Authelia audit, separate issue)reposfield out ofagents.json(depends on F4 watched_repos rollout)service.json— these are deploy-time, file-edit-only by designReferences
/api/*boundary refactor) — same spirit, different layerrepos:for new bindings)apps/server/src/shared/config/webhook-config.ts— the single loader that needs the surgeryapps/server/src/shared/config/agents-config-schema.ts— Zod schema split target