test(canopy-eligibility): compose-profile-matrix integration tests + CI job

Follow-up to the archived adr-005-graceful-degradation-verification plan, Steps 3 + 4. Recorded as "Potential Improvements" in that plan; this issue is the concrete tracker.

Scope

Step 3 — profile-matrix integration tests

Add services/canopy-eligibility/tests/profile_matrix_test.rs with one test per production Compose profile:

  • profile_snap_only_determines_snap_and_skips_others
  • profile_tanf_only_determines_tanf_and_skips_others
  • profile_medicaid_chip_determines_both_and_skips_others
  • profile_caps_only_determines_caps_and_skips_others
  • profile_wic_only_determines_wic_and_skips_others

Each test gates on the relevant TestConfig::*_url being set / others being empty (the standard infrastructure_available() + URL-presence pattern). Asserts: programs in the profile land in approved-or-denied; programs absent from the profile land in programs_pending with basis "program service not configured".

Step 4 — compose-profile-matrix CI job

Add a .gitlab-ci.yml job that runs each profile end-to-end:

compose-profile-matrix:
  stage: test
  needs: []
  parallel:
    matrix:
      - PROFILE: [snap-only, tanf-only, medicaid-chip, caps-only, wic-only]
  script:
    - export COMPOSE_PROFILES=$PROFILE
    - cargo xtask dev start
    - cargo xtask test --integration --filter profile_matrix
    - cargo xtask dev stop

Sequential vs parallel matrix is a runner-capacity question — start sequential, flip to parallel if the job fits within current GitLab runner budget.

Why deferred originally

The capability-flag tests (tests/capability_flag_test.rs, 7 tests, landed 2026-04-26) prove each capability in isolation against a live orchestrator + database + persons fetch. Profile-matrix tests add ~5x integration wall-clock for behaviour already covered in isolation. Defer-then-graduate: graduate when a regression slips past the per-capability fan-out (e.g. an interaction bug that only surfaces when an entire service is absent, not just its URL).

Companion improvement

cargo xtask compliance capabilities — re-parse docker-compose.yml and assert every program service declares the profile set in compliance/deployment-profile-capabilities.toml. Optional: file as a separate issue if scope creeps.

References

  • xref:plans/adr-005-graceful-degradation-verification.adoc[adr-005-graceful-degradation-verification plan] (archive-pending)
  • compliance/deployment-profile-capabilities.toml
  • services/canopy-eligibility/tests/capability_flag_test.rs (companion to extend pattern)