chore(label-catalog): extract factory presets to code constants #936

Closed
opened 2026-05-08 08:55:33 +00:00 by claude-desktop · 0 comments
Collaborator

As an operator, I want the factory label set to live in TypeScript constants, so that the runtime no longer depends on scope='builtin' rows in the label_catalog table.

Today the label_catalog table seeds a 'builtin' row per factory label and the dashboard merges builtin + global + repo at read time. Builtin rows are read-only at runtime (apps/server/src/http/handlers/label-catalog.ts:236 returns 403 on PUT/DELETE). Pulling the set into code makes the factory list reviewable, removes the read-time scope merge, and unblocks the migration that drops the 'builtin' enum value (tracker #934).

Acceptance criteria

Constants

  • New module apps/server/src/setup/label-presets.ts exports LABEL_PRESETS: ReadonlyArray<{ name; color; description }> covering every label currently inserted at scope='builtin' (audit existing rows on the dev DB to seed the list).
  • One frozen entry per area / type label currently shipping. Colours match the global preferences in ~/.claude/CLAUDE.md (e.g. area:agents #0ea5e9, type:user-story #ec4899).

Reads

  • apps/server/src/http/handlers/label-catalog.ts GET handlers read the factory layer from LABEL_PRESETS and merge with global + repo rows in memory; SQL no longer touches scope='builtin'.
  • apps/server/src/infrastructure/forge/labels.ts (the bridge that pushes labels to a Forgejo repo) sources its factory list from LABEL_PRESETS.

Tests

  • Unit test: LABEL_PRESETS is non-empty and every entry has a 6-digit hex colour.
  • Existing label-catalog handler tests still pass with the in-memory merge.

Out of scope

  • Seeding LABEL_PRESETS into scope='global' rows on first install — that's the wizard story.
  • Dropping the builtin rows + tightening the CHECK constraint — that's the migration story.

References

  • Meta tracker: #934
  • Current builtin readers: apps/server/src/http/handlers/label-catalog.ts, apps/server/src/infrastructure/forge/labels.ts
As an operator, I want the factory label set to live in TypeScript constants, so that the runtime no longer depends on `scope='builtin'` rows in the `label_catalog` table. Today the `label_catalog` table seeds a `'builtin'` row per factory label and the dashboard merges builtin + global + repo at read time. Builtin rows are read-only at runtime (`apps/server/src/http/handlers/label-catalog.ts:236` returns 403 on PUT/DELETE). Pulling the set into code makes the factory list reviewable, removes the read-time scope merge, and unblocks the migration that drops the `'builtin'` enum value (tracker #934). ## Acceptance criteria ### Constants - [ ] New module `apps/server/src/setup/label-presets.ts` exports `LABEL_PRESETS: ReadonlyArray<{ name; color; description }>` covering every label currently inserted at `scope='builtin'` (audit existing rows on the dev DB to seed the list). - [ ] One frozen entry per area / type label currently shipping. Colours match the global preferences in `~/.claude/CLAUDE.md` (e.g. `area:agents` `#0ea5e9`, `type:user-story` `#ec4899`). ### Reads - [ ] `apps/server/src/http/handlers/label-catalog.ts` GET handlers read the factory layer from `LABEL_PRESETS` and merge with `global` + `repo` rows in memory; SQL no longer touches `scope='builtin'`. - [ ] `apps/server/src/infrastructure/forge/labels.ts` (the bridge that pushes labels to a Forgejo repo) sources its factory list from `LABEL_PRESETS`. ### Tests - [ ] Unit test: `LABEL_PRESETS` is non-empty and every entry has a 6-digit hex colour. - [ ] Existing label-catalog handler tests still pass with the in-memory merge. ## Out of scope - Seeding `LABEL_PRESETS` into `scope='global'` rows on first install — that's the wizard story. - Dropping the builtin rows + tightening the CHECK constraint — that's the migration story. ## References - Meta tracker: #934 - Current builtin readers: `apps/server/src/http/handlers/label-catalog.ts`, `apps/server/src/infrastructure/forge/labels.ts`
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#936
No description provided.