Plan: Directive Compliance Remediation
On this page
- Status
- Context
- Scope
- Dependencies
- Design
- Steps
- Step 1: Verify and fix CLAUDE.md (7 findings)
- Step 2: Verify and fix architecture.md (13 findings)
- Step 3: Fill coding-conventions.md PROJECT sections (14 findings)
- Step 4: Verify delivery-protocol compliance (5 findings)
- Step 5: Fix git-workflow deviations (4 findings)
- Step 6: Verify GitLab label taxonomy (3 findings)
- Step 7: Fill local-dev.md gaps (9 findings)
- Step 8: Close security-baseline enforcement gaps (5 findings)
- Step 9: Fill security.md missing sections (4 findings)
- Step 10: Fix services.md gaps (7 findings)
- Step 11: Verify test coverage and fill testing.md (12 findings)
- Step 12: Create GitLab epics and link plans (3 findings)
- Step 13: Add commit-msg hook (2 findings)
- Step 14: Add missing forbid(unsafe_code) (2 findings)
- Step 15: Final verification
- Files Touched
- Verification
- Documentation Updates
Status
| Step | Description | Status |
|---|---|---|
1 |
Verify and fix CLAUDE.md accuracy (7 findings) |
Done (2026-04-09) — (test count updated 403→432, labels verified, signing verified) |
2 |
Verify and fix architecture.md (13 findings) |
Done (2026-04-09) — (shared crates, database topology, Redis, Garage, tools, BFF DB config) |
3 |
Fill coding-conventions.md PROJECT sections and document established patterns (14 findings) |
Done (2026-04-09) — (enforcement model, ProblemDetails, typed IDs, integration test section) |
4 |
Verify delivery-protocol compliance and fix gaps (5 findings) |
Done (2026-04-09) — (Tier 1 hash check passes, pre-commit aligned) |
5 |
Fix git-workflow deviations: delete remote branches, amend commit conventions (4 findings) |
Done (2026-04-09) — (stale branches pruned, historical deviations documented) |
6 |
Verify GitLab label taxonomy matches docs (3 findings — agents couldn’t access API) |
Done (2026-04-09) — (API verified: all scoped labels match CLAUDE.md table) |
7 |
Fill local-dev.md gaps: ports, env vars, seed command (9 findings) |
Done (2026-04-09) — (testing section fixed, jurisdiction note added, .env.example already complete) |
8 |
Close security-baseline enforcement gaps (5 findings) |
Done (2026-04-09) — (cargo-audit non-blocking with logged advisories; cargo deny blocking; allow_failure removed) |
9 |
Fill security.md missing sections (4 findings) |
Done (2026-04-09) — (determination signing, IEVS verification, disqualification screenings) |
10 |
Fix services.md endpoint/adapter gaps (7 findings) |
Done (2026-04-09) — (snap verification endpoints, canopy-verification section, BFF details) |
11 |
Fill testing.md PROJECT sections and verify actual test coverage (12 findings) |
Done (2026-04-09) — (432 tests counted empirically, per-crate breakdown, enforcement model) |
12 |
Create GitLab epics and link plans (3 findings) |
Done (2026-04-09) — (ADR epics &31-&37, milestone epics &38-&43 already existed; 12 TBD plan files updated) |
13 |
Add commit-msg hook for format enforcement (2 findings) |
Done (2026-04-09) — ( |
14 |
Add missing forbid(unsafe_code) attributes (2 findings) |
Done (2026-04-09) — ( |
15 |
Final verification: run all checks, confirm zero deviations |
Done (2026-04-09) — clippy zero warnings, policy audit 150/150, 572 unit + 205 integration tests pass |
Epic: &47
Branch: chore/directive-compliance
Labels: type::chore, priority::critical, program::infrastructure, service::shared-crates
Context
33 independent audit agents reviewed every directive document in .claude/docs/ (10 files x 3 agents each) plus .claude/CLAUDE.md (3 agents). Each agent was context-free and checked a different dimension: code compliance, GitLab compliance, and document freshness.
The audit produced 89 findings. Some may be agent errors (particularly the test coverage agent that claimed only 24 tests exist when we believe there are 210). However, every finding gets a verification step — we do not dismiss findings based on belief. If the agent is wrong, the verification step proves it. If the agent is right, we fix it.
The findings cluster into these categories:
-
Documentation staleness (coding-conventions, security, architecture, services, testing, local-dev)
-
GitLab process gaps (no epics, no commit-msg hook, stale branches, inconsistent issue linking)
-
Enforcement gaps (cargo deny not in pre-push, cargo audit allows failure, nextest profile wrong)
-
Minor code issues (2 missing forbid(unsafe_code), Askama not in BFF deps)
-
Disputed findings (test coverage agent claims — verify empirically)
Scope
In scope:
-
All 89 audit findings across 11 directive documents
-
Empirical verification of every disputed finding (test coverage claims, stale agent views)
-
GitLab API operations (label verification, epic creation, branch cleanup)
-
New commit-msg hook for commit message format enforcement
-
Enforcement gap closures (cargo deny in pre-push, CI allow_failure removal)
-
All Tier 2
<!-- PROJECT -->section fill-ins (coding-conventions.md, testing.md) -
All Tier 3 doc updates (architecture.md, security.md, services.md, local-dev.md)
-
.env.examplecompleteness
Out of scope:
-
Retroactive git history rewrites (historical commit format violations documented, not fixed)
-
Askama/htmx/Alpine.js BFF implementation (documented as planned, not yet needed)
-
canopy-cli implementation (separate plan:
canopy-cli.adoc) -
E2E test implementation (placeholder acknowledged, separate effort when Playwright wired)
-
Non-Georgia jurisdiction rulesets (Georgia-only is expected for SNAP UAT)
-
New feature development (this is purely compliance/documentation/process)
Dependencies
This plan depends on:
-
All prior MRs merged to main (verified: 19 MRs merged through MR !19)
-
GitLab API access (token in
.env.local, project 80593893, group 127623789) -
No active feature branches (verify with
git branch -r)
Design
Verification-first approach
Every finding follows the pattern:
-
Verify empirically (run a command, read a file, query an API)
-
If confirmed: fix it
-
If refuted: document the evidence that refutes it
No finding is dismissed based on memory or belief.
Enforcement model
The remediation establishes a 4-layer enforcement model:
| Layer | Checks |
|---|---|
pre-commit |
Human checklist (challenge/response protocol — 8 questions) |
commit-msg (NEW) |
Type prefix present, first line under 72 chars, Co-Authored-By for AI work |
pre-push |
fmt, clippy, nextest, SPDX headers, commit signing, visibility, Tier 3 mandatory docs, cargo deny (NEW) |
CI |
SAST, secret detection, dependency scanning, cargo-audit (blocking — NEW), docker-promote |
Steps
Step 1: Verify and fix CLAUDE.md (7 findings)
Files: .claude/CLAUDE.md
Verify each claim:
-
canopy-snap route count: Run
grep -c "\.route(" services/canopy-snap/src/api/mod.rs. Compare to CLAUDE.md claim. Fix if wrong. -
Askama in BFF deps: Run
grep askama services/canopy-web/Cargo.toml services/canopy-portal/Cargo.toml. If missing, either add it or update tech stack description to say "planned" for BFF template engine. -
canopy-eligibility Feature Status: Read the actual line in CLAUDE.md. Verify it says "implemented" with correct route count. (Agent may have seen pre-MR!18 state.)
-
canopy-snap Feature Status: Same verification.
-
UAT Target text: Verify it says Month 3 is immediate priority, not Month 2.
-
GitLab labels: Run
curlagainst GitLab API to list all group labels. Compare against CLAUDE.md label table. Report mismatches. -
Commit signing: Run
git config commit.gpgsignandgit config user.signingkey. Verify matches CLAUDE.md.
Step 2: Verify and fix architecture.md (13 findings)
Files: .claude/docs/architecture.md
-
Shared crates list: Run
ls crates/. Compare to architecture.md crates list. Add any missing (canopy-signing, canopy-rules-client). -
Database topology: Add section documenting ADR-001 implementation: 1 shared PostgreSQL (12 infra DBs) + 5 isolated PostgreSQL instances (program DBs). Include port map.
-
Redis purpose: Check docker-compose.yml for Redis usage. Document its role (session cache? rate limiting? both?).
-
Garage S3 purpose: Check which services use canopy-store. Document Garage’s role.
-
PostgreSQL services: List all 6 PostgreSQL containers with their databases and ports.
-
canopy-seed and xtask: Add tools section documenting both.
-
BFF database config: Document that canopy-web and canopy-portal use canopy_security database for sessions.
-
ADR-007 CLI status: Note as planned, not implemented.
-
Epic assignments: Verify all 30 plans show
Epic: &47. Create plan to assign epics (Step 12). -
ADR commit references: Check
git log --all --oneline | grep -i "ADR"count. Document current state. -
ADR-level epics: Verify none exist in GitLab. Plan creation in Step 12.
-
ADR MR citations: Check last 5 MR descriptions for ADR references.
-
Code ADR comments: Verify no inline ADR references exist. Decide if this is desired or not.
Step 3: Fill coding-conventions.md PROJECT sections (14 findings)
Files: .claude/docs/coding-conventions.md
This is a Tier 2 doc with <!-- PROJECT -→ sections that must be filled.
-
Add Result<T, ApiError> pattern: Document with example handler signature.
-
Add From<sqlx::Error> impl: Document the pattern and why it logs before returning generic message.
-
Add DeterminationSigner location: Document
canopy_signing::DeterminationSignertrait. -
Add ADR-003 practical guidance: When to put logic in JDM rulesets vs Rust code.
-
Add ProblemDetails struct: Show the RFC 9457 response shape.
-
Add ApiError variant guide: Table of variants and when to use each.
-
Add forbid(unsafe_code): Fix canopy-rules-client/src/lib.rs and xtask/src/main.rs.
-
Document commit-msg hook: Reference the hook created in Step 13.
-
Document pre-commit protocol: Describe the challenge/response system.
-
Verify MemoryStore ban:
grep -r "MemoryStore" services/— confirm zero hits. -
Verify event bus restrictions:
grep -r "income\|ssn\|wages" services/*/src/events.rs— confirm no PII in events. -
Remove WIP commits: Check
git log --oneline | grep -i "WIP\|index on". If present, note as historical. -
Document no-unwrap convention: Reference the bulk replacement and expect() pattern.
-
Verify 98.7% compliance claim: Run full clippy + SPDX check independently.
Step 4: Verify delivery-protocol compliance (5 findings)
Files: Git history, GitLab API
-
MRs lacking Closes N: Run
git log --oneline --merges -10 | grep -v "Closes\|". List MRs without issue refs. Document which are legitimate (chore/docs without issues). -
Post-merge closing comments: Use GitLab API to check last 5 closed issues for closing comments with commit SHA.
-
Early commits missing issue refs: Run
git log --oneline | head -20 | grep -v "#". Count non-compliant. Decide if retroactive fix is needed. -
Tier 1 integrity: Run
cargo xtask check-docs. If it fails, run--fix --yes. -
Delivery checklist overall: Review pre-commit hook questions against delivery protocol. Verify alignment.
Step 5: Fix git-workflow deviations (4 findings)
Files: Git remote, .githooks/
-
Delete 13 stale remote branches: Run
git branch -r --merged origin/main | grep -v main | xargs -I{} git push origin --delete {}. Verify withgit branch -r. -
Commit
1cc5dd6missing type prefix: Historical — cannot amend. Document as known deviation. -
Commit
5aaa220over 72 chars: Historical — cannot amend. Document as known deviation. -
Enable auto-delete source branch in GitLab: Check project settings. Enable "Delete source branch when merge request is accepted" if not already on.
Step 6: Verify GitLab label taxonomy (3 findings)
Files: GitLab API
Agents couldn’t access the API. We must verify manually:
-
List all group labels:
curl -s -H "PRIVATE-TOKEN: $TOKEN" "https://gitlab.com/api/v4/groups/127623789/labels?per_page=100". Compare against CLAUDE.md label table. -
Check 5 recent closed issues for labeling: For each, verify: 1 type:: label, 1 priority:: label, at least 1 program:: or service:: label, 1 workflow:: label.
-
Check issue templates match gitlab-workflow.md: Read
.gitlab/issue_templates/default.mdand verify it prompts for required labels.
Step 7: Fill local-dev.md gaps (9 findings)
Files: .claude/docs/local-dev.md, .env.example
-
Add Prometheus port 9090: Add to port map with
(observability profile)note. -
Add Grafana port 3000: Same.
-
Add Garage admin port 3903: Add to port map.
-
Implement or remove
cargo xtask seed: Either create the xtask subcommand wrappingdevstack/seed/seed.sh, or remove from doc. -
Document E2E placeholder: Note that
cargo xtask e2eexists but bails until Playwright is configured. -
Add CANOPY_STORE__* vars to .env.example: S3_ENDPOINT, S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY, BUCKET, BACKEND, LOCAL_ROOT, MAX_UPLOAD_BYTES.
-
Add optional service settings to .env.example: LOG_LEVEL, CORS_ORIGINS, BODY_LIMIT, DB_MAX_CONNECTIONS, DB_IDLE_TIMEOUT_SECS.
-
Add session TTL vars: Document CANOPY_WEBSESSION_TTL_SECONDS=28800 and CANOPY_PORTALSESSION_TTL_SECONDS=1800.
-
Note Georgia-only rulesets: Add a note that only
rulesets/georgia/exists currently. Other jurisdictions require creating ruleset directories.
Step 8: Close security-baseline enforcement gaps (5 findings)
Files: xtask/src/cmd/validate.rs, .gitlab-ci.yml
-
Add
cargo deny checkto validate: Add as step 5.5 in validate.rs (after SPDX headers, before fmt). Fail pre-push if banned deps detected. -
Change
allow_failure: falsefor cargo-audit: In.gitlab-ci.yml, removeallow_failure: truefrom cargo-audit job. Or add a--severity criticalflag to only block on critical CVEs. -
Verify SPDX not in
cargo xtask test: Confirm this is intentional (test is for fast iteration, validate is for pre-push). Document the design decision. -
Verify signing enforcement: Confirm
check_signing()in validate.rs catches missing config. Run with signing disabled to test. -
Document enforcement model: Add a table to testing.md or coding-conventions.md showing what’s enforced where (pre-commit, pre-push, CI).
Step 9: Fill security.md missing sections (4 findings)
Files: .claude/docs/security.md
-
Add Determination Signing section: Document ECDSA P-256, canopy-signing crate, key rotation, VerifyingKeyRegistry.
-
Add IEVS Verification section: Document ievs_match_results and ievs_discrepancies schemas, isolation boundary, CMA requirements, NoopAdapter.
-
Add Disqualification Screenings section: Document snap_disqualification_screenings schema, screening types, exemption tracking.
-
Add CMA requirement documentation: Note that SSA SOLQ/BINDEX requires executed CMA. NoopAdapter for UAT.
Step 10: Fix services.md gaps (7 findings)
Files: .claude/docs/services.md
-
Add 3 canopy-snap verification endpoints: GET discrepancies, PUT resolve, GET ievs-matches.
-
Add canopy-verification section: Document IevsAdapter trait, NoopIevsAdapter, internal /internal/v1/ievs/match endpoint.
-
List canopy-snap modules individually: abawd, categorical, deductions, determine, disqualifications, params, rules_client, store, sua.
-
Add BFF database references: canopy-web and canopy-portal use canopy_security database.
-
Add BFF session config details: TTLs, PostgresStore, cookie security settings.
-
Verify port numbers: Run
grep -E "PORT=" docker-compose.yml | sort. Compare to doc. -
Verify database names: Run
cat devstack/postgres/init.sql | grep CREATE. Compare to doc.
Step 11: Verify test coverage and fill testing.md (12 findings)
Files: .claude/docs/testing.md, test files
This step must empirically verify the disputed test coverage findings.
-
Count actual tests: Run
cargo nextest list --workspace 2>/dev/null | grep "test:" | wc -l. Record the exact number. Do NOT assume 210. -
Count inline [cfg(test)] modules: Run
grep -rl "\[cfg(test)\]" crates/ services/ | wc -l. List which files have them. -
Count test functions per service: Run
cargo nextest list --workspaceand parse output by crate. Create a table. -
Verify canopy-snap has tests:
cargo nextest list -p canopy-snap | grep "test:" | wc -l. Record count. -
Verify canopy-eligibility has tests: Same.
-
Check for testcontainers usage:
grep -r "testcontainers" crates/ services/ Cargo.toml Cargo.lock. Report what’s found. -
Check for Playwright:
ls tests/e2e/ 2>/dev/null. Report. -
Fix function name: Change
devstack_available()toinfrastructure_available()in testing.md. -
Fill Test Types table: Using data from steps 1-3.
-
Fill Commands section: Document actual cargo xtask test and nextest commands.
-
Fill CI Pipeline section: Document scan-only model.
-
Add pre-commit protocol description: Document the challenge/response system.
Step 12: Create GitLab epics and link plans (3 findings)
Files: GitLab API, all plan .adoc files
-
Create 7 ADR-level epics: ADR-001 through ADR-007. Each epic groups the plans that implement that ADR.
-
Create milestone-level epics: Month 1 Foundation, Month 2 SNAP Core, Month 3 Verification, etc.
-
Update all 30+ plan files: Replace
Epic: &47with the actual epic reference.
Step 13: Add commit-msg hook (2 findings)
Files: .githooks/commit-msg (new)
-
Create commit-msg hook: Validate:
-
Type prefix present (feat:/fix:/chore:/refactor:/docs:/test:)
-
First line under 72 characters
-
Co-Authored-By:present for AI-assisted work (optional — warn, don’t block)
-
-
Document in coding-conventions.md: Reference the hook and the format it enforces.
Step 14: Add missing forbid(unsafe_code) (2 findings)
Files: crates/canopy-rules-client/src/lib.rs, xtask/src/main.rs
-
Add
#![forbid(unsafe_code)]to both files. -
Verify:
grep -rL "forbid(unsafe_code)" crates//src/lib.rs services//src/main.rs xtask/src/main.rs tools/*/src/main.rs. Should return empty.
Step 15: Final verification
-
cargo fmt --check --all— zero issues -
cargo clippy --workspace — -D warnings— zero warnings -
cargo nextest run --workspace --profile ci— all tests pass, record count -
cargo xtask validate --skip-docker— all 8 checks pass -
cargo xtask check-docs— Tier 1 docs pass hash validation -
grep -r "\.unwrap()" crates/ services/ --include="*.rs" | grep -v target | wc -l— zero -
grep -rL "forbid(unsafe_code)" crates//src/lib.rs services//src/main.rs tools/*/src/main.rs xtask/src/main.rs— empty -
Verify all remote branches pruned:
git branch -r | grep -v main | wc -l— zero (or only active feature branches) -
Re-run 33-agent audit on a sample (3 agents on CLAUDE.md, 3 on services.md) to verify fixes
Files Touched
| File | Change |
|---|---|
|
Fix route count, verify Feature Status, tech stack Askama note |
|
Add shared crates, database topology, Redis/Garage, tools |
|
Fill PROJECT sections: ApiError, signing, ADR-003, conventions table |
|
Add signing, IEVS, disqualification screening sections |
|
Add verification endpoints, canopy-verification section, BFF details |
|
Fill PROJECT sections, fix function name, add pre-commit protocol |
|
Add missing ports, seed command, E2E note |
|
Add STORE vars, optional service settings, session TTLs |
|
New: commit message format enforcement |
|
Remove allow_failure on cargo-audit |
|
Add cargo deny check step |
|
Add forbid(unsafe_code) |
|
Add forbid(unsafe_code) |
30+ plan .adoc files |
Replace Epic: TBD with actual epic refs |
GitLab (API) |
Create ADR epics, delete stale branches, enable auto-delete |
Verification
-
Every finding from the 89-item audit list has either a fix or a documented "verified as non-issue with evidence"
-
No finding is dismissed without empirical verification
-
cargo xtask validate --skip-dockerpasses -
cargo xtask check-docspasses -
Re-audit sample confirms fixes
Documentation Updates
-
All
.claude/docs/files updated per steps above -
.claude/CLAUDE.mdverified and corrected -
CHANGELOG.adoc— entry under== Unreleased -
Plan status tables updated for completed remediation steps