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_othersprofile_tanf_only_determines_tanf_and_skips_othersprofile_medicaid_chip_determines_both_and_skips_othersprofile_caps_only_determines_caps_and_skips_othersprofile_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 stopSequential 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.tomlservices/canopy-eligibility/tests/capability_flag_test.rs(companion to extend pattern)