Files
svg-backend/backend/docs/smoke-regression.md
greebo ac3a62f108 feat(backend): add publish readiness contract and guarded publish flow
add backend readiness contract for publish prechecks

guard publish flow with explicit validation and version-aware checks
make publish behavior more predictable for clients and safer against stale state
2026-03-19 20:41:08 +03:00

7.1 KiB

Smoke regression checklist

This file is the backend manual regression baseline for svg-service.

Preconditions

  • docker compose stack is up
  • backend responds on port 9020
  • valid admin API key is available
  • test scheme exists

Environment

Use these variables in shell:

export API_URL="http://127.0.0.1:9020" export API_KEY="admin-local-dev-key" export SCHEME_ID="82086336d385427f9d56244f9e1dd772"

1. Health / system

  • GET /healthz -> 200
  • GET /api/v1/ping -> 200
  • GET /api/v1/db/ping -> 200
  • GET /api/v1/manifest -> 200

2. Scheme registry

  • GET /api/v1/schemes -> 200
  • GET /api/v1/schemes/{scheme_id} -> 200
  • GET /api/v1/schemes/{scheme_id}/current -> 200
  • GET /api/v1/schemes/{scheme_id}/versions -> 200

Validate:

  • scheme_id is stable
  • current version exists
  • version list contains current version
  • status and counts are consistent

3. Structure read model

  • GET /api/v1/schemes/{scheme_id}/current/sectors -> 200
  • GET /api/v1/schemes/{scheme_id}/current/groups -> 200
  • GET /api/v1/schemes/{scheme_id}/current/seats -> 200

Validate:

  • total counts are non-negative
  • known sample scheme returns expected object lists
  • seats contain seat_id / sector_id / group_id contract where applicable

4. SVG / display pipeline

  • GET /api/v1/schemes/{scheme_id}/current/svg -> 200
  • GET /api/v1/schemes/{scheme_id}/current/svg/display -> 200
  • GET /api/v1/schemes/{scheme_id}/current/svg/display/meta -> 200
  • GET /api/v1/schemes/{scheme_id}/current/svg/display?mode=optimized -> 200 or explicit controlled failure
  • GET /api/v1/schemes/{scheme_id}/current/svg/display/meta?mode=optimized -> 200 or explicit controlled failure

Validate:

  • response content type for svg endpoints is image/svg+xml
  • meta returns scheme_id, scheme_version_id, view_box, width, height
  • no 500 on passthrough mode
  • unsupported mode returns 422

5. Pricing read model

  • GET /api/v1/schemes/{scheme_id}/pricing -> 200
  • GET /api/v1/schemes/{scheme_id}/current/seats/{seat_id}/price -> 200 for priced seat
  • GET /api/v1/schemes/{scheme_id}/test/seats/{seat_id} -> 200 for priced and unpriced seat
  • GET /api/v1/schemes/{scheme_id}/pricing/coverage -> 200
  • GET /api/v1/schemes/{scheme_id}/pricing/unpriced-seats -> 200
  • GET /api/v1/schemes/{scheme_id}/pricing/explain/{seat_id} -> 200

Validate:

  • pricing bundle contains categories and rules arrays
  • effective seat price resolves according to domain priority
  • test seat preview explains selectable / has_price state
  • coverage endpoint is internally consistent
  • explain endpoint returns matched_rule for priced seat and null for unpriced seat

6. Draft editor read/write guards

  • GET /api/v1/schemes/{scheme_id}/draft/structure -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/validation -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/compare-preview -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/seats/records/{seat_record_id} -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/sectors/records/{sector_record_id} -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/groups/records/{group_record_id} -> 200
  • PATCH /api/v1/schemes/{scheme_id}/draft/seats/records/{seat_record_id} with unknown sector_id -> 422
  • POST /api/v1/schemes/{scheme_id}/draft/seats/bulk with unknown group_id -> 422
  • POST /api/v1/schemes/{scheme_id}/draft/remap/preview with unknown target group -> 422
  • POST /api/v1/schemes/{scheme_id}/draft/sectors duplicate sector_id -> 422
  • POST /api/v1/schemes/{scheme_id}/draft/groups duplicate group_id -> 422

Validate:

  • stale expected_scheme_version_id returns 409 on guarded draft endpoints
  • duplicate/reference failures return typed detail payloads
  • successful read endpoints stay stable after failed mutations

7. Draft publish preview / readiness

  • GET /api/v1/schemes/{scheme_id}/publish/validation -> 200
  • POST /api/v1/schemes/{scheme_id}/draft/pricing/snapshot -> 200 when scheme is in draft
  • GET /api/v1/schemes/{scheme_id}/draft/publish-preview?refresh=true -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/publish-preview -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/publish-preview?refresh=true&baseline_scheme_version_id={published_version_id} -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/publish-readiness -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/publish-readiness?expected_scheme_version_id={current_version_id} -> 200
  • GET /api/v1/schemes/{scheme_id}/draft/publish-readiness?expected_scheme_version_id=deadbeef... -> 409

Validate:

  • refresh and cached read both succeed
  • preview summary contains is_publishable / has_structure_changes / has_artifacts / snapshot_available
  • pricing_coverage is internally consistent
  • baseline override returns override strategy when explicit baseline is provided
  • preview retention does not grow unbounded for same version+variant
  • readiness returns validation_summary, pricing_coverage, snapshot, readiness flags

8. Publish / version lifecycle

  • POST /api/v1/schemes/{scheme_id}/versions?expected_current_scheme_version_id=deadbeef... -> 409
  • POST /api/v1/schemes/{scheme_id}/publish?expected_scheme_version_id=deadbeef... -> 409
  • POST /api/v1/schemes/{scheme_id}/publish?expected_scheme_version_id={current_version_id} -> 200 when environment is ready

Validate:

  • stale protection returns typed 409 payload
  • successful publish returns scheme_id, scheme_version_id, status, current_version_number, published_at, pricing_snapshot, validation_summary
  • after publish, current scheme status is published
  • audit contains scheme.published event for the same scheme_version_id

9. Admin / ops

  • GET /api/v1/admin/schemes/{scheme_id}/current/artifacts -> 200
  • GET /api/v1/admin/schemes/{scheme_id}/current/validation -> 200
  • GET /api/v1/admin/artifacts/publish-preview/audit -> 200
  • POST /api/v1/admin/artifacts/publish-preview/cleanup?dry_run=true -> 200

Optional:

  • POST /api/v1/admin/schemes/{scheme_id}/current/display/regenerate?mode=passthrough -> 200
  • POST /api/v1/admin/display/backfill?mode=passthrough&limit=10&only_missing=true -> 200

Validate:

  • audit endpoint does not report orphan files or missing files for DB rows in normal state
  • validation report is readable and deterministic
  • admin routes do not produce 500 for healthy scheme state

10. Audit trail

  • GET /api/v1/schemes/{scheme_id}/audit -> 200

Validate:

  • recent publish preview / pricing / version events are present when corresponding operations were run
  • audit total is non-negative
  • event payloads stay JSON-serializable

11. Fail criteria

Regression is considered failed if any of the following happen:

  • health or db ping fails
  • any stable read endpoint returns 500
  • passthrough display endpoint fails on known-good sample
  • publish preview refresh or cached read returns 500
  • pricing bundle contract changes unexpectedly
  • admin audit/cleanup endpoints fail on healthy environment
  • artifact retention grows without bound for repeated preview refresh on same variant
  • publish readiness says ready but guarded publish fails for non-stale reasons

12. Operator note

Run this checklist after:

  • schema changes
  • pricing schema/repository refactors
  • artifact lifecycle changes
  • display pipeline changes
  • route reorganization
  • startup/import/config changes
  • publish lifecycle changes