Release v0.4.1#4
Conversation
Entries marked as the test_images type could not be saved: autosave stalled and the manual "Save now" button could not recover the entry, even though the type was selectable in the outline. The root cause was controlled vocabularies duplicated as hand-copied literal arrays across the database schema, validators, and type definitions, with the save validator's allowlist omitting test_images. Hoist the controlled vocabularies (entry types, resource types, project roles, descriptive standards, quality-control flag types and resolution actions, GeoNames feature classes, and volume statuses) to a single source of truth in validation/enums.ts. The schema, Zod validators, role allow-lists, and derived types now all reference these constants, so save validation derives from the canonical entry-type set. Add a drift guard (tests/db/enum-drift.test.ts) that pins each schema enum column to its canonical constant so a future divergence fails in CI rather than silently breaking a save, plus a round-trip regression test for entry-type save validation.
A workflow_dispatch CI job that runs the Vitest suite and the TypeScript type-check on demand, on an Ubicloud runner sized for the Cloudflare Workers vitest pool. Manual trigger is deliberate: the suite is too heavy to run on every push, and concurrency is keyed by branch ref so a second dispatch cancels the in-flight run.
There was a problem hiding this comment.
Pull request overview
Maintenance release v0.4.1 focused on fixing a save-path regression for test_images entries by consolidating controlled vocabularies into a single canonical source and adding guards to prevent enum drift across schema/validators/types.
Changes:
- Fixed entry-save validation to accept every schema-allowed
EntryType(includingtest_images) and added a regression test for it. - Centralized workflow-side enums (entry types, project roles, QC vocabularies, volume statuses, etc.) in
app/lib/validation/enums.ts, and updated schema/routes/types to consume them. - Added an enum-drift test suite and a manually dispatched CI workflow for running tests + typecheck.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/entries/save.test.ts | Adds regression coverage ensuring schema-allowed entry types (incl. test_images) round-trip through save/load. |
| tests/db/enum-drift.test.ts | Adds a drift-guard suite pinning Drizzle enum columns to canonical enum constants + explicit checkpoints. |
| CHANGELOG.md | Documents the v0.4.1 fix and enum consolidation. |
| app/routes/api.workflow.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/api.resegmentation.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/api.qc-flags.tsx | Replaces local QC enum literals + role allowlists with canonical enums. |
| app/routes/api.entries.save.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/api.comments.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/_auth.viewer.$projectId.$volumeId.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/_auth.projects.$id.volumes.$volumeId.manage.tsx | Aligns userRole typing with exported workflow role type. |
| app/routes/_auth.projects.$id.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/_auth.projects.$id.overview.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/_auth.projects.$id.members.tsx | Reuses canonical project roles for validation and adopts ProjectRole type. |
| app/routes/_auth.description.$projectId.$entryId.tsx | Replaces hand-copied project-role allowlist with canonical PROJECT_ROLES. |
| app/routes/_auth.admin.users.$id.tsx | Reuses canonical project roles for validation and adopts ProjectRole type. |
| app/routes/_auth.admin.cataloguing.team.tsx | Uses canonical PROJECT_ROLES in Zod validation. |
| app/lib/workflow.ts | Re-exports VolumeStatus and aliases WorkflowRole to canonical ProjectRole. |
| app/lib/validation/place.ts | Replaces inline GeoNames fclass enum literal with GEONAMES_FCLASSES. |
| app/lib/validation/enums.ts | Introduces canonical workflow-side enums (entry types, roles, QC vocabularies, etc.). |
| app/lib/permissions.server.ts | Replaces repeated role allowlists with canonical PROJECT_ROLES. |
| app/lib/operator-actions.server.ts | Uses canonical DESCRIPTIVE_STANDARDS for tenant creation validation. |
| app/lib/invites.server.ts | Replaces hard-coded role union casts with canonical ProjectRole type. |
| app/lib/entries.server.ts | Fixes save validation to accept all canonical ENTRY_TYPES (incl. test_images). |
| app/lib/description.server.ts | Uses canonical Spanish resource-type enum and ResourceTypeEs type. |
| app/lib/description-types.ts | Uses canonical types for resourceType and authorRole. |
| app/lib/boundary-types.ts | Re-exports EntryType from canonical enums to keep consumers consistent. |
| app/db/schema.ts | Updates Drizzle enum hints to use canonical enum constants. |
| app/components/qc-flags/resolve-qc-flag-dialog.tsx | Types userRole with canonical ProjectRole. |
| app/components/qc-flags/qc-flag-card-expandable.tsx | Types userRole with canonical ProjectRole. |
| app/components/layout/footer.tsx | Updates displayed version to 0.4.1. |
| .github/workflows/tests.yml | Adds manually triggered CI workflow to run Vitest + typecheck. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| */ | ||
|
|
||
| const VERSION = "0.4.0"; | ||
| const VERSION = "0.4.1"; |
There was a problem hiding this comment.
Good catch — bumped package.json to 0.4.1 in 4f3f791.
| on: | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: tests-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubicloud-standard-4 | ||
| timeout-minutes: 15 |
There was a problem hiding this comment.
Deliberate, and documented in the workflow header. It's manual-dispatch only, so it never blocks fork PR checks. We picked ubicloud-standard-4 (16 GB) for headroom on the full Workers vitest pool, which is heavier than a standard runner is sized for. If fork-friendliness comes up, we'd add a dispatch input defaulting to Ubicloud with ubuntu-latest as an override.
The site footer reads "Fisqua v0.4.1" and links to the v0.4.1 release tag, and package.json metadata matches the release.
A maintenance release: one save-path bug fix plus the structural cleanup behind it.
Highlights
Full details in the changelog.