Plan: Directive Compliance Remediation

On this page

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) — (.githooks/commit-msg enforces type prefix and 72-char limit)

14

Add missing forbid(unsafe_code) attributes (2 findings)

Done (2026-04-09) — (canopy-rules-client/src/lib.rs and xtask/src/main.rs)

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.example completeness

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:

  1. Verify empirically (run a command, read a file, query an API)

  2. If confirmed: fix it

  3. 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

Documentation update pattern

For each .claude/docs/ file with <!-- PROJECT --> comment blocks:

  1. Read the comment block to understand what’s expected

  2. Fill with current implementation details

  3. Reference actual file paths, struct names, and code patterns

Steps

Step 1: Verify and fix CLAUDE.md (7 findings)

Files: .claude/CLAUDE.md

Verify each claim:

  1. canopy-snap route count: Run grep -c "\.route(" services/canopy-snap/src/api/mod.rs. Compare to CLAUDE.md claim. Fix if wrong.

  2. 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.

  3. 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.)

  4. canopy-snap Feature Status: Same verification.

  5. UAT Target text: Verify it says Month 3 is immediate priority, not Month 2.

  6. GitLab labels: Run curl against GitLab API to list all group labels. Compare against CLAUDE.md label table. Report mismatches.

  7. Commit signing: Run git config commit.gpgsign and git config user.signingkey. Verify matches CLAUDE.md.

Step 2: Verify and fix architecture.md (13 findings)

Files: .claude/docs/architecture.md

  1. Shared crates list: Run ls crates/. Compare to architecture.md crates list. Add any missing (canopy-signing, canopy-rules-client).

  2. Database topology: Add section documenting ADR-001 implementation: 1 shared PostgreSQL (12 infra DBs) + 5 isolated PostgreSQL instances (program DBs). Include port map.

  3. Redis purpose: Check docker-compose.yml for Redis usage. Document its role (session cache? rate limiting? both?).

  4. Garage S3 purpose: Check which services use canopy-store. Document Garage’s role.

  5. PostgreSQL services: List all 6 PostgreSQL containers with their databases and ports.

  6. canopy-seed and xtask: Add tools section documenting both.

  7. BFF database config: Document that canopy-web and canopy-portal use canopy_security database for sessions.

  8. ADR-007 CLI status: Note as planned, not implemented.

  9. Epic assignments: Verify all 30 plans show Epic: &47. Create plan to assign epics (Step 12).

  10. ADR commit references: Check git log --all --oneline | grep -i "ADR" count. Document current state.

  11. ADR-level epics: Verify none exist in GitLab. Plan creation in Step 12.

  12. ADR MR citations: Check last 5 MR descriptions for ADR references.

  13. 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.

  1. Add Result<T, ApiError> pattern: Document with example handler signature.

  2. Add From<sqlx::Error> impl: Document the pattern and why it logs before returning generic message.

  3. Add DeterminationSigner location: Document canopy_signing::DeterminationSigner trait.

  4. Add ADR-003 practical guidance: When to put logic in JDM rulesets vs Rust code.

  5. Add ProblemDetails struct: Show the RFC 9457 response shape.

  6. Add ApiError variant guide: Table of variants and when to use each.

  7. Add forbid(unsafe_code): Fix canopy-rules-client/src/lib.rs and xtask/src/main.rs.

  8. Document commit-msg hook: Reference the hook created in Step 13.

  9. Document pre-commit protocol: Describe the challenge/response system.

  10. Verify MemoryStore ban: grep -r "MemoryStore" services/ — confirm zero hits.

  11. Verify event bus restrictions: grep -r "income\|ssn\|wages" services/*/src/events.rs — confirm no PII in events.

  12. Remove WIP commits: Check git log --oneline | grep -i "WIP\|index on". If present, note as historical.

  13. Document no-unwrap convention: Reference the bulk replacement and expect() pattern.

  14. Verify 98.7% compliance claim: Run full clippy + SPDX check independently.

Step 4: Verify delivery-protocol compliance (5 findings)

Files: Git history, GitLab API

  1. 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).

  2. Post-merge closing comments: Use GitLab API to check last 5 closed issues for closing comments with commit SHA.

  3. Early commits missing issue refs: Run git log --oneline | head -20 | grep -v "#". Count non-compliant. Decide if retroactive fix is needed.

  4. Tier 1 integrity: Run cargo xtask check-docs. If it fails, run --fix --yes.

  5. 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/

  1. Delete 13 stale remote branches: Run git branch -r --merged origin/main | grep -v main | xargs -I{} git push origin --delete {}. Verify with git branch -r.

  2. Commit 1cc5dd6 missing type prefix: Historical — cannot amend. Document as known deviation.

  3. Commit 5aaa220 over 72 chars: Historical — cannot amend. Document as known deviation.

  4. 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:

  1. 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.

  2. 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.

  3. Check issue templates match gitlab-workflow.md: Read .gitlab/issue_templates/default.md and verify it prompts for required labels.

Step 7: Fill local-dev.md gaps (9 findings)

Files: .claude/docs/local-dev.md, .env.example

  1. Add Prometheus port 9090: Add to port map with (observability profile) note.

  2. Add Grafana port 3000: Same.

  3. Add Garage admin port 3903: Add to port map.

  4. Implement or remove cargo xtask seed: Either create the xtask subcommand wrapping devstack/seed/seed.sh, or remove from doc.

  5. Document E2E placeholder: Note that cargo xtask e2e exists but bails until Playwright is configured.

  6. Add CANOPY_STORE__* vars to .env.example: S3_ENDPOINT, S3_REGION, S3_ACCESS_KEY, S3_SECRET_KEY, BUCKET, BACKEND, LOCAL_ROOT, MAX_UPLOAD_BYTES.

  7. Add optional service settings to .env.example: LOG_LEVEL, CORS_ORIGINS, BODY_LIMIT, DB_MAX_CONNECTIONS, DB_IDLE_TIMEOUT_SECS.

  8. Add session TTL vars: Document CANOPY_WEBSESSION_TTL_SECONDS=28800 and CANOPY_PORTALSESSION_TTL_SECONDS=1800.

  9. 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

  1. Add cargo deny check to validate: Add as step 5.5 in validate.rs (after SPDX headers, before fmt). Fail pre-push if banned deps detected.

  2. Change allow_failure: false for cargo-audit: In .gitlab-ci.yml, remove allow_failure: true from cargo-audit job. Or add a --severity critical flag to only block on critical CVEs.

  3. 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.

  4. Verify signing enforcement: Confirm check_signing() in validate.rs catches missing config. Run with signing disabled to test.

  5. 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

  1. Add Determination Signing section: Document ECDSA P-256, canopy-signing crate, key rotation, VerifyingKeyRegistry.

  2. Add IEVS Verification section: Document ievs_match_results and ievs_discrepancies schemas, isolation boundary, CMA requirements, NoopAdapter.

  3. Add Disqualification Screenings section: Document snap_disqualification_screenings schema, screening types, exemption tracking.

  4. 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

  1. Add 3 canopy-snap verification endpoints: GET discrepancies, PUT resolve, GET ievs-matches.

  2. Add canopy-verification section: Document IevsAdapter trait, NoopIevsAdapter, internal /internal/v1/ievs/match endpoint.

  3. List canopy-snap modules individually: abawd, categorical, deductions, determine, disqualifications, params, rules_client, store, sua.

  4. Add BFF database references: canopy-web and canopy-portal use canopy_security database.

  5. Add BFF session config details: TTLs, PostgresStore, cookie security settings.

  6. Verify port numbers: Run grep -E "PORT=" docker-compose.yml | sort. Compare to doc.

  7. 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.

  1. Count actual tests: Run cargo nextest list --workspace 2>/dev/null | grep "test:" | wc -l. Record the exact number. Do NOT assume 210.

  2. Count inline [cfg(test)] modules: Run grep -rl "\[cfg(test)\]" crates/ services/ | wc -l. List which files have them.

  3. Count test functions per service: Run cargo nextest list --workspace and parse output by crate. Create a table.

  4. Verify canopy-snap has tests: cargo nextest list -p canopy-snap | grep "test:" | wc -l. Record count.

  5. Verify canopy-eligibility has tests: Same.

  6. Check for testcontainers usage: grep -r "testcontainers" crates/ services/ Cargo.toml Cargo.lock. Report what’s found.

  7. Check for Playwright: ls tests/e2e/ 2>/dev/null. Report.

  8. Fix function name: Change devstack_available() to infrastructure_available() in testing.md.

  9. Fill Test Types table: Using data from steps 1-3.

  10. Fill Commands section: Document actual cargo xtask test and nextest commands.

  11. Fill CI Pipeline section: Document scan-only model.

  12. Add pre-commit protocol description: Document the challenge/response system.

Files: GitLab API, all plan .adoc files

  1. Create 7 ADR-level epics: ADR-001 through ADR-007. Each epic groups the plans that implement that ADR.

  2. Create milestone-level epics: Month 1 Foundation, Month 2 SNAP Core, Month 3 Verification, etc.

  3. Update all 30+ plan files: Replace Epic: &47 with the actual epic reference.

Step 13: Add commit-msg hook (2 findings)

Files: .githooks/commit-msg (new)

  1. 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)

  2. 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

  1. Add #![forbid(unsafe_code)] to both files.

  2. 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

  1. cargo fmt --check --all — zero issues

  2. cargo clippy --workspace — -D warnings — zero warnings

  3. cargo nextest run --workspace --profile ci — all tests pass, record count

  4. cargo xtask validate --skip-docker — all 8 checks pass

  5. cargo xtask check-docs — Tier 1 docs pass hash validation

  6. grep -r "\.unwrap()" crates/ services/ --include="*.rs" | grep -v target | wc -l — zero

  7. grep -rL "forbid(unsafe_code)" crates//src/lib.rs services//src/main.rs tools/*/src/main.rs xtask/src/main.rs — empty

  8. Verify all remote branches pruned: git branch -r | grep -v main | wc -l — zero (or only active feature branches)

  9. Re-run 33-agent audit on a sample (3 agents on CLAUDE.md, 3 on services.md) to verify fixes

Files Touched

File Change

.claude/CLAUDE.md

Fix route count, verify Feature Status, tech stack Askama note

.claude/docs/architecture.md

Add shared crates, database topology, Redis/Garage, tools

.claude/docs/coding-conventions.md

Fill PROJECT sections: ApiError, signing, ADR-003, conventions table

.claude/docs/security.md

Add signing, IEVS, disqualification screening sections

.claude/docs/services.md

Add verification endpoints, canopy-verification section, BFF details

.claude/docs/testing.md

Fill PROJECT sections, fix function name, add pre-commit protocol

.claude/docs/local-dev.md

Add missing ports, seed command, E2E note

.env.example

Add STORE vars, optional service settings, session TTLs

.githooks/commit-msg

New: commit message format enforcement

.gitlab-ci.yml

Remove allow_failure on cargo-audit

xtask/src/cmd/validate.rs

Add cargo deny check step

crates/canopy-rules-client/src/lib.rs

Add forbid(unsafe_code)

xtask/src/main.rs

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

  1. Every finding from the 89-item audit list has either a fix or a documented "verified as non-issue with evidence"

  2. No finding is dismissed without empirical verification

  3. cargo xtask validate --skip-docker passes

  4. cargo xtask check-docs passes

  5. Re-audit sample confirms fixes

Documentation Updates

  • All .claude/docs/ files updated per steps above

  • .claude/CLAUDE.md verified and corrected

  • CHANGELOG.adoc — entry under == Unreleased

  • Plan status tables updated for completed remediation steps

Edit this page · default