Skip to content

feat(v2): records — schema-version-pinned rows, validated bulk-upsert, references view (Phase 2)#226

Closed
JonnyTran wants to merge 14 commits into
developfrom
feat/v2-schema-registry
Closed

feat(v2): records — schema-version-pinned rows, validated bulk-upsert, references view (Phase 2)#226
JonnyTran wants to merge 14 commits into
developfrom
feat/v2-schema-registry

Conversation

@JonnyTran

Copy link
Copy Markdown
Member

Stacked on #219 (Phase 1: schema registry). Implements Phase 2 of the schema-centric data model — spec §5 (record row), §6 (validated write flow), §7 (records/references endpoints): docs/superpowers/specs/2026-06-27-schema-centric-data-model-design.md. Plan: docs/superpowers/plans/2026-07-03-v2-records.md.

What's included

  • v2_records table + V2Record ORM model (class named V2Record because a second Record breaks v1's string-based relationship lookups in the shared declarative registry) + Alembic migration 8136bc88ee3a (upgrade/downgrade round-trip verified)
  • V2RecordStatus enum (pending|completed|discarded) with its own PG type; v1 untouched
  • Validated bulk-upsert POST /api/v2/schemas/{id}/records:bulk-upsert: resolves each item's pinned or current schema version, fetches each distinct version's Pandera body from the object store once per request, validates all items via Phase 1's validate_record_fields before any write (all-or-nothing 422 with per-item detail), then merges v1-style on (schema_id, external_id); metadata/status are patch-like on update (documented)
  • GET /schemas/{id}/records (offset/limit 50/1000, status/reference filters, exact total) and DELETE /schemas/{id}/records?ids= (cap 100, 204)
  • GET /api/v2/references/{reference:path} — cross-schema document view grouped per schema; :path converter so DOI references (containing slashes) resolve; workspace-scoped + authorized; unknown reference returns an empty 200 view
  • SchemaPolicy.{upsert_records,list_records,delete_records}: reads = workspace member, writes = owner/admin member; member/non-member negative tests
  • 55 v2 tests green; roborev findings from jobs 64/68/70/71 addressed in-branch (see plan doc)

Out of scope (later phases)

LanceDB search/sync (Phase 3); questions/suggestions/responses (Phase 4).

Accepted caveat

Concurrent bulk-upserts racing on (schema_id, external_id) can surface an IntegrityError (500) — same class as v1's bulk behavior and Phase 1's accepted publish race; to be hardened when record writes move to the job queue.

JonnyTran and others added 14 commits June 27, 2026 07:20
Pandera 0.32/pandas 3.0 drops Column.metadata through to_json, so the review
widget is carried via a review_widgets side map (spec §13). validate_record_fields
separates nulls so a None in a nullable numpy-int column no longer fails coercion.
Adds review_widgets JSONB overlay on SchemaVersion per spec §13 (Pandera to_json
drops Column.metadata, so review widgets are carried out-of-band).
Includes review_widgets column; the circular schemas.current_version_id FK is added
only on non-SQLite dialects (SQLite can't ALTER-add constraints; tests run on SQLite).
Adds a one-directional Schema.workspace relationship so the SubFactory pattern
(and FK population) works as in DatasetFactory.
SchemaVersionCreate/Read carry review_widgets (spec §13).
publish_version flushes the new version before pointing schema.current_version_id at
it (avoids the schemas<->schema_versions FK cycle and an unset version id). Threads
review_widgets into the stored version and derived columns_cache (spec §13).
…r-workspace authz

SchemaPolicy mirrors DatasetPolicy (owner always; admin+member for writes). Mounts a
separate api_v2 sub-app at /api/v2. Adds an isolated tests/integration conftest with a
v2-aware async_client (overrides get_async_db + get_s3_client on api_v2) and no
OpenSearch fixture.
…VersionId)

- validate_record_fields: convert numpy->native via .item()/ISO instead of lossy
  to_json (preserves high-precision floats + datetimes); reject omitted required cols.
- put_object: propagate S3 VersionId so schema_versions.object_version_id is populated.
- Add model default/uniqueness + float/datetime/missing-required tests.
- Document accepted/deferred findings (publish race, 404-vs-403, commit granularity).
frame.iloc[0] collapses the validated row into a single Series whose dtype is
the columns' common type; an int64 cell alongside a float64 column upcasts to
float, silently degrading integer fidelity for record.fields. Extract each cell
per-column (frame[col].iloc[0]) instead. Adds an Int+Float (no string column)
regression test. Addresses roborev job 62.
…, references view (Phase 2) (#225)

* feat(v2): add V2RecordStatus enum (pending/completed/discarded)

* feat(v2): V2Record ORM model (v2_records) pinned to schema versions

* feat(v2): alembic migration for v2_records table

* test(v2): V2RecordFactory

* feat(v2): pydantic request/response schemas for v2 records and references

* feat(v2): records context with validated bulk-upsert, list, delete, reference query

* feat(v2): record-scoped policy actions on SchemaPolicy

* feat(v2): /api/v2 records endpoints (bulk-upsert, list, delete) with authz

* feat(v2): GET /api/v2/references/{reference} cross-schema document view

Also surfaces the specific 'No record IDs provided' 422 on empty delete ids
(roborev job 70: the post-parse length check was unreachable).

* fix(v2): match slash-containing references (DOIs) via :path converter; lint cleanups

* docs: add Phase 2 (v2 records) implementation plan

* docs: update schema-centric data model design with new v2 table definitions and record write process

- Clarified table names and purposes for `schemas`, `schema_versions`, and `v2_records`.
- Enhanced the description of the record write process, emphasizing validation and error handling.
- Updated API endpoint descriptions for schemas, schema versions, and records to reflect recent changes.
@JonnyTran JonnyTran requested a review from a team as a code owner July 7, 2026 06:12
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
extralit-frontend Ignored Ignored Preview Jul 7, 2026 6:12am

@JonnyTran JonnyTran closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant