Skip to content

feat(kernel): a schema version records a description and when it was created #230

Description

@JArmandoAnaya

Problem

AnnotationSchema is (project_id, version, classes) — nothing records why a version exists or when it was created. A version history UI (follow-up issue) has nothing to show but class lists, and users asked for a details/comments field on schema versions.

Decision (founder, 2026-08-02)

The description is immutable, written once at publish — the commit-message model. It fits the never-update-a-version doctrine (immutability is in the frozen type); no update route is added. Ongoing editable discussion would be a separate future feature, deliberately out of scope here.

Scope

  • Domain: AnnotationSchema.description: str | None (frozen, like everything else on the model) and created_at: datetime (UTC, tz-aware — a version history without dates is half a history; kernel: nothing records when an asset was ingested, so "recently" is unanswerable #216 established the pattern and the cost).
  • SchemaService.create_version gains an optional description parameter, stored verbatim (normalize/strip per domain/names.py temperament, but blank → None rather than a refusal — an empty commit message is legal).
  • Migration 14: two nullable columns on annotation_schema (description TEXT, created_at TEXT ISO-8601 with offset, per the timestamps rule in _tables.py). Alter-only table → columns declared last on the row class, explicit drops in _downgrade_to_version_one (the kernel: nothing records when an asset was ingested, so "recently" is unanswerable #216 pattern — the undo is what exercises the migration). Pre-existing versions keep NULLs; nothing backfills a moment nobody recorded.
  • Mapper: check whether SCHEMAS is a flat mapping — a timestamp costs an entity its flat persistence mapping (kernel: nothing records when an asset was ingested, so "recently" is unanswerable #216 finding), so this likely means a hand-written mapper pair if it doesn't already have one (the classes JSON column suggests it does).
  • Wire: SchemaVersionOut gains both fields; SchemaVersionCreate gains optional description. openapi.json + pnpm generate:client regenerate (drift gates).
  • MCP: create_schema_version / get_schema tool schemas pick the fields up through the domain models per the M3 convention.
  • Docs: docs/schemas.md.

Acceptance criteria

  1. Publishing a version with a description stores and returns it; without one, description is null.
  2. created_at is stamped by the service at publish, UTC, and survives a round-trip byte-identically.
  3. Fresh-vs-migrated schema equality holds (migration 14 + its undo in the downgrade walk).
  4. Existing versions read back with null description/created_at — no backfill, no refusal.
  5. The generated TS client and checks.ts reflect both fields (drift gates green).

Metadata

Metadata

Assignees

No one assigned

    Labels

    apivisionset.server — REST API and OpenAPI contractenhancementNew feature or requestkernelvisionset.kernel — domain, ports, adapters, servicesmcpvisionset.mcp — MCP server and tools

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions