test(managementapi): DB-backed composition floor for the read handlers

Follow-up to !788 (merged) (was stacked on its branch; retargeted to main when it merged).

!788 (merged)'s unit tests drive the read handlers through fakeRepositoryReader, which mirrors the store's keyset contract in parallel code. That leaves one documented hole (called out in !788 (merged)'s description): a symmetric misreading of the contract, the same bug in the fake's bound and the store's SQL, passes both test tiers separately. This MR adds the composition authority that closes it.

One integration-tagged file (//go:build integration), following the OCI package's handler-integration precedent and the datastore package's TestMain convention (own isolated database per package):

  • managementapi.NewHandler wired exactly as production: real NamespaceStore resolves the slug, real RepositoryStore serves the reads, repository rows seeded through the real Create write path (namespace + default collection seeded directly; they have no write surface yet).
  • TestReadHandlersIntegration_KeysetWalkRoundTrip: the full forward-and-backward Link walk against the real keyset SQL, including backward-page link emission, prev-then-next symmetry, and a saved rel="next" replayed after its boundary row is soft-deleted (the bound is a row-value comparison, not a boundary-row lookup; only this tier can catch a store rewrite that changes that).
  • TestReadHandlersIntegration_FilteredWalkAndSortedUnion: a format filter surviving followed pages against the real WHERE clause, and a last_updated_at walk asserting exact page order across both COALESCE(last_updated_at, created_at) arms, so an updated row's timestamptz rides the wire cursor's JSON round trip and never-updated rows take the created_at fallback. (Index usage is pinned by the schema tier, not here.)
  • TestReadHandlersIntegration_Detail: detail hit with real-column-state body assertions, and the existence-hiding 404 through the store's wrapped ErrNotFound.

The fake stays authoritative for what a live database cannot do: deterministic error injection, the zero-store-calls-on-400 assertion, and param-mapping seam checks.

Runs in the test:integration CI job (-tags=integration); locally via testcontainers. This MR adds the missing CI wiring for internal/managementapi (the job's go list set and its changes: anchor) plus a drift guard, scripts/ci/check-integration-test-wiring.sh (pre-commit hook and lint:integration-test-wiring job), which fails whenever a package has //go:build integration tests but is missing from either place.

Related to #171 (closed)

Edited by João Pereira

Merge request reports

Loading
Loading