feat(maven): maven_virtual_repositories schema (S30 plan: 1/25)

Summary

Step 1 of the S30 plan (Depends on: —): the maven_virtual_repositories schema — the parent table, its unique index, the jet output, and the S20-A collateral the new cascading child forces.

  • Migration 20260916100000_create_maven_virtual_repositories.sql: parent plus 64 HASH(namespace_id) partitions under -- +goose NO TRANSACTION, the inline uuid-v7 CHECK, ON DELETE CASCADE on the (repository_id, namespace_id) composite foreign key and NO ACTION on the namespace key as trailing ALTER TABLE ... ADD CONSTRAINT statements, and the (namespace_id, repository_id) unique index.
  • Regenerated structure.sql and jet output.
  • Schema and rowshapes integration suites in the migrations package, mirrored against npm's npm_virtual_repositories suites — zero dropped subtests, every enumerated column value covered positively.
  • The FK schema guard's wantCascadeTargets grows by the new child; the S20-A inbound-FK count sentence is corrected to "ten of the twelve ... cascade".

Targets main directly: the step declares no dependencies, and no open MR touches these files.

Diff size

3,219 added lines across 11 files, past the 500-reviewable-LOC line:

File group Added Reviewable
structure.sql + jet output 1,338 no — machine-checked (db:structure-check, jet:generate-check)
The migration 685 yes
New integration suites 1,190 tests
Guard, checksum, mirror-collateral, S20-A prose 6 yes

Reviewable source is ~1,880. The plan prices Step 1 as one step (~1,900 total); splitting it would separate the migration from the only suites that pin it, and Steps 2–3 serialize on this table landing first.

Plan divergences, booked for the docs(plans) amendment

  • Lock posture. The plan pins the container junction's in-file Up-side SET lock_timeout = '1s' / SET statement_timeout = '5s'; the migration follows #548's schema-wide decision instead: the provider owns the Up-side bound as a connection startup option — a SQL SET would override it for this file's statements forever, and Steps 2–3 copy this file's shape — the require-timeout-settings waiver carries the posture, and only the Down brackets. Main's newest migration (20260915130000) already embodies this reading.
  • npm mirror collateral. The two npm mirror suites gain //nolint:dupl twin directives and one tense fix — unbooked in the plan, measured firing when stripped.

A step MR cannot edit the plan file, so both ride the planned docs(plans) amendment MR.

Governing ADRs

ADR-007 governs the schema, and the migration conforms to it as written: the ON DELETE CASCADE general rule for format child tables "and their virtual and remote variants" (ADR-007 :174), the uuid-v7 CHECK mandate (:30), HASH(namespace_id) partitioning (:1125), and the (namespace_id, repository_id) unique index (:1131); the namespace foreign key's NO ACTION equals ADR-007's unstated-action default, and the repositories-facing pair is declared in the maven_virtual_repositories ERD block. Verified against the canonical handbook text at HEAD on 2026-09-15 — the local mirror is fresh for this file. The amendment #943 tracks (the range/length CHECK constraints and the junction ON DELETE pair) covers subjects that materialize in Steps 2–3, not in this diff. ADR-001, 004, 005, 008, 009, and 012 were checked against the diff: no surface of theirs appears here.

Testing

  • New schema and rowshapes integration suites (//go:build integration, migrations package), mirrored against npm's with zero dropped subtests; the unique-constraint rejection asserts SQLSTATE 23505; the catalog-derived TestIDUUIDVersionCheck_CoversEveryApplicationGeneratedIDTable picks the new table up automatically.
  • The FK schema guard (TestRepositoryStore_DeleteFKAssumption_SchemaGuard) derives the live topology from the catalog and now requires the new cascade.
  • go test ./internal/datastore/migrations/ green locally; CI runs the full suite. Integration-tagged files linted with golangci-lint run --build-tags=integration — 0 issues on diff lines.
  • e2e scenarios: none added or affected — this step ships schema only, with no client-facing route; the plan books the e2e.maven.virtual.* catalog group at Step 20.
  • Conformance: no Maven protocol behavior is implemented (schema only), so no conformance run is due.
  • /validate-step ran pre-push: the sequence-number blocker it found is fixed at the tip (69d094d88, renumber above main's head); the plan-vs-code lock-posture contradiction was ruled keep-code by the operator (#548, above); the remaining WARNs are the two amendment items above.

Related to #289 (step 1 of 25; the issue tracks the whole S30 implementation)

Database Review Evidence

Migrations

Note

Timings are from CI (db:migrate matrix, goose verbose) against an empty database, in apply / rollback order per PG version. Production-scale validation via Database Lab is not yet available. See Database review evidence for the matrix rationale and how to read the numbers.

Migration PG 16 PG 17 PG 18
20260916100000_create_maven_virtual_repositories.sql OK (823.56ms / 164.08ms) OK (503.1ms / 138.09ms) OK (1.06s / 304.95ms)

Migration notes:

  • PG 18 up (1.06s) is ~1.3x PG 16 and ~2.1x PG 17 — under the 2x version-regression threshold, and ~0.4% of the 5-minute boot budget. The cost is the parent-plus-64-partition CREATE and the unique index; no out-of-band move needed.

Queries

None: the step is schema-only (parent table, partitions, unique index, jet output). No hand-written query methods changed, so there is no SQL to EXPLAIN in this MR. Query evidence follows in the steps that add the datastore methods.

Edited by Moaz Khalifa

Merge request reports

Loading
Loading