refactor(cms): single TS source of truth for document_type and stage enums#72
Open
RickCogley wants to merge 1 commit intomainfrom
Open
refactor(cms): single TS source of truth for document_type and stage enums#72RickCogley wants to merge 1 commit intomainfrom
RickCogley wants to merge 1 commit intomainfrom
Conversation
…source
The document_type enum previously lived in 7 places (SQL CHECK, Zod enum,
4 UI dropdown arrays, 1 inline TS union). stage lived in 5. That drift
surface is exactly how the pre-0036 'runbook' gap happened: present in
SQL CHECK + UI + TS union, missing from Zod.
This refactor makes the Zod enum the single source of values. UI pickers
import DOCUMENT_TYPES / LIFECYCLE_STAGES constants derived from the Zod
enum + a labels Record, so adding a type in one place propagates.
- schemas.ts: DOCUMENT_TYPES, DOCUMENT_TYPE_LABELS, LIFECYCLE_STAGES,
LIFECYCLE_STAGE_LABELS exports. Labels Records are typed exhaustively
(Record<DocumentTypeValue, string>) so TS errors if a new enum value
doesn't get a label. DocumentTypeValue and StageValue types exported.
- 4 Svelte files: local arrays / inline <option> lists replaced with
imported constants + {#each} loops.
- templates/[id]/+page.server.ts: 15-arm inline TS union replaced with
DocumentTypeValue / StageValue.
- Minor UX change: the template-list filter in documents/new uses the
canonical singular labels (Proposal) rather than the previous plural
(Proposals). One less drift surface.
Drift guard test (schemas.test.ts): reads all migration files via
Vite's import.meta.glob, extracts the most recent templates.document_type
CHECK list, asserts it matches DOCUMENT_TYPES. Fails CI if a future
migration forgets a type. No @types/node dependency needed.
Closes #71
InfoSec: no security impact — pure TS restructuring of values that
already existed. Parameterized D1 binds unchanged (OWASP A03 preserved).
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
esolia-hanawa | f791d64 | Commit Preview URL Branch Preview URL |
Apr 17 2026, 11:00 PM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Collapses document type and lifecycle stage from 7 / 5 hand-synced locations down to a single TS source of truth. Each UI picker now imports derived constants; the Zod enum drives value set; a unit test guards against SQL CHECK drift.
Addresses exactly the failure mode that the pre-0036 `runbook` gap exhibited: something present in SQL CHECK + UI dropdowns + TS union but silently missing from the Zod enum.
Changes
`src/lib/schemas.ts` — new single source
4 Svelte files — import + loop
`templates/[id]/+page.server.ts`
Drift guard — `src/lib/schemas.test.ts` (new)
Minor UX change
The template-list type filter on `/documents/new` previously used plural labels ("Proposals", "Reports"). It now uses the canonical singular labels from `DOCUMENT_TYPES` ("Proposal", "Report"). Deliberate — keeping them separate would preserve one of the drift surfaces this PR is meant to eliminate. The "All Types" default option is prepended in place.
Test Plan
Out of scope
InfoSec
No security impact — pure TS restructuring of existing values. Parameterized D1 binds unchanged (OWASP A03 preserved). Drift guard strengthens defense-in-depth against schema/code divergence.
Closes #71