Roadmap

On this page

The roadmap is organized into phases that reflect the modular OpenStack-style architecture. Each phase delivers independently deployable services that collectively satisfy the CCWIS federal requirements under 45 CFR Part 1355.

For detailed technical specifications — database schemas, API endpoints, event flows, and verification steps — see the Implementation Guide.

Live Tracking

The phase checklists below are the high-level long-arc roadmap. For day-to-day triage and what’s actively in flight, use the live GitLab views — they update as issues, MRs, and epics change without requiring a roadmap doc edit:

Issue Board: Development

Kanban view with columns by priority (P0-critical / P1-high / P2-medium / P3-low). Add --label=blocked filter to see externally-owned or dependency-blocked items.

Open P1-high issues

Production blockers + compliance-critical work

Open P2-medium issues

High-value, actively schedulable

Open P3-low issues

Quality / hygiene / nice-to-have

Open blocked issues

Awaiting external dependency or ADR resolution; excluded from the active triage queue

Open CRAIG epics

Multi-issue initiatives at the group level

Closed CRAIG epics

Historical record of completed multi-issue initiatives

Every issue carries a P-label. New issues without one will not show up on the board until a priority is assigned — backfill via glab issue update <N> --label P2-medium (or whatever fits).

Phase 1 — Foundation

Goal: Establish the core platform infrastructure on which all services are built.

  • Monorepo workspace structure (Cargo workspace with per-service crates)

  • Shared authentication and authorization service (OAuth2 / OpenID Connect via Keycloak)

  • RabbitMQ integration layer — shared message bus client library (craig-mq)

  • Core REST API framework (Axum-based) with shared middleware (logging, tracing, auth, error handling) (craig-api)

  • Database migration framework (SQLx) (craig-db)

  • CI/CD pipeline (GitLab CI) with SAST, dependency auditing, and lint checks

  • Plain-language automated function documentation framework (§ 1355.53(a)(2)) — cargo xtask api-docs

  • Developer environment setup (Docker Compose: Postgres, RabbitMQ, Keycloak)

Phase 2 — Rules and Policy Engine

Goal: Establish the jurisdiction-configurable rules engine that all other services rely on for policy evaluation — directly satisfying the § 1355.53(a)(1) requirement to separate business rules from core programming.

  • Integrate zen-engine (GoRules Zen Engine Rust crate)

  • REST API for rule evaluation (synchronous) and rule management (CRUD for JDM rule sets)

  • RabbitMQ event subscription — rule evaluation triggered by case and eligibility events

  • Jurisdiction rule set loader — load JDM rule sets from database or file system at startup and on update

  • Rule set versioning and audit trail — every rule evaluation records the rule set version used

  • Jurisdiction-configurable rule set activation (CRAIG_RULES__JURISDICTION)

  • Title IV-E eligibility JDM rule set — Georgia DFCS (rulesets/georgia/georgia-ive-eligibility.json)

  • Safety and risk assessment JDM rule set — Georgia DFCS (rulesets/georgia/georgia-safety-assessment.json)

  • Timeliness monitoring JDM rule set — Georgia DFCS with ASFA deadlines (rulesets/georgia/georgia-timeliness.json)

  • Intake screening JDM rule set — Georgia DFCS (rulesets/georgia/georgia-intake-screening.json)

  • Placement matching JDM rule set — Georgia DFCS (rulesets/georgia/georgia-placement-matching.json)

  • Rule set import/export tooling for jurisdiction onboarding

  • Title IV-E eligibility JDM rule set — Texas DFPS (rulesets/texas/texas-ive-eligibility.json)

  • Safety assessment JDM rule set — Texas DFPS, three-outcome model (rulesets/texas/texas-safety-assessment.json)

  • Timeliness monitoring JDM rule set — Texas DFPS with TFC 262/263 deadlines (rulesets/texas/texas-timeliness.json)

  • Intake screening JDM rule set — Texas DFPS Statewide Intake with P1/P2 priorities (rulesets/texas/texas-intake-screening.json)

  • Placement matching JDM rule set — Texas DFPS with four-tier LOC and ICWA preferences (rulesets/texas/texas-placement-matching.json)

  • Case routing and complexity classification JDM rule set — Georgia + Texas, 12 evaluation tests

  • Plain-language rule documentation generation from JDM rule sets (§ 1355.53(a)(2))

Phase 3 — Case Management Service

Goal: Core child welfare case lifecycle management.

  • Intake and referral management

  • Investigation and assessment tracking

  • Case plan creation and management

  • Family and household composition management

  • Worker assignment and caseload management

  • Court order and legal status tracking (supports court data exchange)

  • ICWA compliance tracking and documentation (§ 1355.52(b))

  • Case notes and narrative documentation — contacts table with narrative field, 6 endpoints, UI tab, attachments via object storage

  • Automated data quality monitoring and staff alerting (§ 1355.52(d)(1)) — data_quality_issues table, dashboard endpoint, Rules Engine continuous monitoring

Phase 4 — Placement and Foster Care Service

Goal: Foster care, kinship, and residential placement management.

  • Foster home and provider licensing and capacity management

  • Placement matching and history

  • Title IV-E eligibility determination — calls Rules Engine (Phase 2) for identical automated functions for all users (§ 1355.52(g)) — JDM rule sets (GA + TX), POST /v1/rules/evaluate with eligibility context, financial service tracks IV-E fields

  • Placement stability and sibling group tracking

  • Reunification and permanency planning — case plan permanency goals, timeliness monitoring (permanency hearing 365d, TPR 455d per ASFA)

  • Educational enrollment tracking (supports education data exchange) — education_records table, 5 endpoints, CLI, web UI

  • Health and developmental records (supports health agency data exchange) — health_records table, 6 endpoints (incl. overdue), CLI, web UI

  • Major changes monitoring — major_changes table on craig-security, 5 admin endpoints, CLI, web UI

Testing Infrastructure

Goal: Comprehensive integration test harness inspired by OpenStack Tempest — typed service clients, credential isolation, event verification, and API-only black-box testing.

  • craig-test-lib shared crate — test configuration, Keycloak token provider, generic HTTP client

  • Typed service clients — RulesClient, CasesClient, PlacementClient, ExchangeClient, FinancialClient, ReportingClient, SecurityClient, IntakeClient (one method per endpoint)

  • Test harness with cleanup stack — resource creation, UUID-suffixed naming, LIFO teardown

  • Event collector — RabbitMQ temporary queue for verifying published events

  • Test data builders — fluent builders with valid defaults for all request types

  • Unit test additions — craig-common error/pagination/settings, craig-auth claims/middleware, craig-mq envelope (~33 tests)

  • craig-rules integration tests — CRUD, evaluation, auth, import/export, events (~123 tests)

  • craig-cases integration tests — persons, referrals, investigations, cases, plans, contacts, court orders, events, cross-service workflow (~84 tests)

  • craig-placement integration tests — foster homes, placements, kinship, matching, events (~62 tests)

  • craig-exchange integration tests — partners, agreements, ICPC, transactions, home studies (~39 tests)

  • craig-cli integration tests — library-level tests for all 22 command modules via cmd::*::run() (~86 tests)

  • CI pipeline integration test job (manual trigger with docker-compose)

Performance Testing

Goal: Establish automated performance baselines and regression detection for all CRAIG services using industry-standard load testing tools, ensuring the platform meets production throughput and latency requirements without building a custom testing framework.

Tooling

  • k6 test runner — Grafana k6 as the primary load testing tool, invoked via cargo xtask perf (Docker grafana/k6 image)

  • k6 test scripts directory structure — tests/k6/ (services/ one script per service, scenarios/ per profile, helpers/, baselines/)

  • Shared k6 utility module — tests/k6/helpers/auth.js (Keycloak ROPC token acquisition) + config.js + thresholds.js

  • Docker Compose performance profile (docker-compose.perf.yml) — resource limits mimicking production sizing

Test Scenarios per Service

  • Per-service k6 scripts — tests/k6/services/{rules,cases,placement,exchange,financial,reporting,security,intake,web}.js (coverage depth varies by service; the named scenario person-suggestions-bench.js covers the matching hot path)

  • Deep per-service scenario coverage as originally scoped (cache hit-vs-miss, concurrent same-key contention profiles)

  • Cross-service workflow tests — full intake-to-placement lifecycle (cases → rules engine safety assessment → placement matching), measuring end-to-end latency

  • Authentication overhead tests — token acquisition latency, JWT validation throughput, comparison of cold vs. warm JWKS cache

  • Database contention tests as k6 scenarios — the contested-environment program (epic &83, ADR-067) covers contention at the Rust test layer instead

Test Types

  • Smoke tests — 1 VU across all 9 services, ~5 s; the pre-push gate (cargo xtask perf --profile smoke; request counts live in tests/k6/baselines/)

  • Load tests — sustained realistic concurrency ~5 minutes with SLO thresholds (--profile load; the CI perf-load job)

  • Stress tests — ramp beyond expected load, 10-30 minutes (--profile stress; manual/scheduled)

  • Soak tests — moderate sustained load 30+ minutes for leak/drift detection (--profile soak; manual)

Performance Thresholds

  • p95 latency thresholds defined — tests/k6/helpers/thresholds.js (#1134 class budgets: Read<50 / List<100 / Write<200 / Cross<500 / BFF<300 ms, validated against the dated baseline in tests/k6/baselines/)

  • Error-rate threshold — <1% in thresholds.js (the original <0.1% aspiration lives in the implementation guide)

  • Throughput baselines — tests/k6/baselines/ dated recordings; re-record via --save-baseline

  • k6 threshold assertions — k6 exits non-zero on breach, failing the pre-push smoke and the CI perf-load job

Profiling and Optimization Infrastructure

  • tokio-console integration — conditional compilation flag for async runtime introspection (task polling latency, waker counts, resource utilization)

  • Criterion micro-benchmarks — targeted benchmarks for hot paths (rule evaluation, JWT validation, pagination query construction)

  • Connection pool tuning guide — documented methodology for sizing PostgreSQL and HTTP client pools based on load test results

  • Performance baseline documentation — recorded results for each service at known hardware specs, updated with each phase

CI/CD Integration

  • Pre-push k6 smoke gate — cargo xtask perf --profile smoke runs on every push (1 VU, 29 requests, ~5s); not a CI job by design (the per-push gate model keeps smoke out of CI)

  • GitLab CI perf-load job (#258, !187) — runs cargo xtask perf --profile load --save-baseline against a devstack on dhs-aws-autoscaler-docker.medium. Threshold breaches fail the job. main + schedule triggers; allow_failure: true while baselining noise (flip after a clean week)

  • GitLab CI perf-stress job (#258, !187) — cargo xtask perf --profile stress --save-baseline, manual + scheduled invocation only

  • Performance trend tracking — test-results/k6/ JSON retained as CI artifacts for 30 days

  • Alerting on regression — currently k6 threshold breach fails the job; no pager hook yet (P3 follow-up after allow_failure flips to blocking)

Object Storage

Goal: Store non-machine-readable documents (PDFs, images, scanned forms, generated report files) in an S3-compatible object store instead of PostgreSQL. Services store only metadata and an object_key in the database; actual file bytes live in the object store.

  • craig-store shared crate — wraps Apache object_store crate; unified put/get/delete/list API

  • Garage devstack container — local S3-compatible backend for development

  • craig-exchange adoption — ICPC attachments (100A forms, medical records, birth certificates)

  • craig-cases adoption — court order documents, contact attachments

  • craig-placement adoption — foster home documents (home_documents store + the BFF upload route; DB-anchoring hardening tracked as #990)

  • Upload validation — max file size, MIME type allowlist, content-type verification, filename sanitization

  • craig-web file upload/download UI (multipart forms, streaming downloads)

  • craig-cli attachment upload/download commands (ICPC attachments)

  • craig-reporting adoption — generated AFCARS/NCANDS export files (craig-store backed, ADR-062 §U deterministic export attempts)

  • craig-security adoption — security review evidence artifacts

  • craig-portals adoption — family document upload (when Phase 11 is built)

Phase 5 — Data Exchange Service

Goal: Satisfy all 11 mandatory bi-directional data exchange requirements (§ 1355.52(e-f)).

  • Unified data exchange standard implementation (ExchangeAdapter trait + NoopAdapter)

  • CWCA exchange adapter — format transformer with case_data, service_record, placement_notification exchange types

  • Financial payments and claims exchange adapter — payment_submission, claim_submission, rate_update

  • Medicaid eligibility exchange adapter — eligibility_request, enrollment_notification

  • Child abuse and neglect system exchange adapter — report_submission, disposition_notification (NCANDS codes)

  • TANF / Title IV-A exchange adapter — family_referral, benefit_status

  • Child support / Title IV-D exchange adapter — case_referral, support_order

  • External data collection system adapter — generic data_submission pass-through

  • Court system exchange adapter — case_notice, order_submission, hearing_schedule

  • Education system exchange adapter — enrollment_notification, records_request

  • Health agency exchange adapter — health_notification, immunization_record

  • Tribal entity exchange adapter (§ 1355.54) — icwa_notice, placement_notification, kinship_verification

  • Data sharing agreement management (per ACF Technical Bulletin #8)

  • Exchange audit trail and error logging

  • RabbitMQ event publication for all inbound and outbound exchange events

  • ICPC interstate compact — full workflow (draft → home study → decision → completion)

  • ICPC home studies with structured evaluation criteria

  • ICPC attachments (upload, download, list via object storage)

Hardening — Seed Data, Tests & Documentation

Goal: Strengthen the foundation before adding new feature services — improve seed data realism, close test coverage gaps, and produce developer/operator documentation.

Seed Data Overhaul

  • craig-seed generator — replaced static SQL with scalable Rust binary (tools/craig-seed/), deterministic via --seed N, arbitrary scale via --families N, 21 tests

  • Deterministic UUIDv7s — custom generator using monotonic counter + seeded RNG for reproducible, time-ordered IDs

  • Cross-service FK integrity — all foreign key references validated across craig_cases, craig_placement, craig_exchange

  • Seed attachments — the seed uploads attachment fixtures on first start (gated on the in-graph garage-init one-shot since the C4 gate, #1012)

  • E2E manifest integration — generate seed.ts with --manifest flag, pinned CRAIG_SEED=42 and CRAIG_FAMILIES=12 for deterministic E2E runs

Test Audit

  • E2E assertion hardening — strengthened flash text assertions, added waitForLoadState/waitForURL patterns

  • Negative and error path e2e tests — 404 pages, invalid UUIDs, form validation, RBAC boundary tests

  • Cross-service integration tests — services/craig-cases/tests/api/workflow.rs covers the referral → investigation → case arc; the placement/exchange legs ride their services' own suites

  • API contract tests — response schema validation for all endpoints

  • Pagination tests — verified pagination controls with per_page override

Documentation

  • Data model documentation — ER diagrams (Mermaid) per service (the data-model-*.adoc family) + the 16-machine state-machine inventory (craig-test-lib::state_machine_matrix; exhaustive matrix pinning first adopted in craig-financial, sibling matrices tracked per D4.5)

  • Domain glossary — 30 CCWIS domain terms across 5 categories

  • Developer onboarding guide — project structure, initialization pattern, how-to guides, testing reference

  • Architecture Decision Records (ADRs) — the practice is established; the ADR index under adrs/ is the source of truth (60+ records at 2026-08-25, from the Rust-monorepo foundation through the contested-environment program)

  • Deployment and operations guide — env var reference, container deployment, infrastructure config, scaling

Phase 6 — Financial and Claims Service

Goal: Title IV-B and IV-E financial management.

  • Foster care maintenance payment calculation and issuance

  • Adoption assistance payment management — enum + seed-rate scaffolding only; no live writer generates adoption-assistance payments (#1080 corrected the overstatement; the real capability rides the DFCS-confirmed program set, #1073)

  • Guardianship assistance payment management — delivered by epic &70 (ADR-056 SG/NRSG agreement lifecycle + the ADR-053/055 monthly generator); state-funded per GA 22.8 (structurally never IV-E; per-code UAS/TANF reportability recorded by #1072) — federal IV-E GAP claiming is NOT implemented, funding confirmations ride #1073

  • Title IV-E eligibility and claiming

  • Title IV-B claiming and reporting

  • Federal financial participation (FFP) cost allocation tracking (§ 1355.57)

  • APD budget tracking and reporting integration

Phase 7 — Reporting and Data Quality Service

Goal: Federal reporting, NCANDS, and ongoing data quality assurance (§ 1355.52(d)).

  • NCANDS data collection and submission

  • AFCARS (Adoption and Foster Care Analysis and Reporting System) reporting

  • Biennial data quality review workflow and tooling (§ 1355.52(d)(2))

  • Automated data quality monitoring dashboard

  • Data quality plan management and APD submission support (OMB Form 0970-0463)

  • CCWIS automated function checklist reporting (OMB Form 0970-0463)

  • ACF review and assessment support artifacts (§ 1355.55)

Phase 8 — Security and Compliance Service

Goal: Satisfy all security, privacy, and compliance requirements.

  • Biennial security review workflow (45 CFR § 95.621(f))

  • Data archiving and purging automation (2 CFR § 200.334)

  • Role-based access control with audit logging for all data access and modifications

  • Confidentiality controls enforcing Section 471(a)(8), 45 CFR § 205.50, and CAPTA § 106

  • Data breach detection and notification workflows — detection_rules + security_alerts tables, 8 endpoints, 6 rule types, audit log anomaly detection, webhook notification, CLI + web UI, periodic background scheduler (#266 / !186, configurable via CRAIG_SECURITY__DETECTION_INTERVAL_SECS, default 60s)

  • NIST SP 800-53 control mapping documentation

  • Penetration testing and vulnerability management integration

  • ATO pathway and continuous compliance documentation

Phase 9 — CLI Client (craig)

Goal: A first-class command-line interface providing complete access to all CRAIG API functionality, modeled after the openstack CLI.

  • Unified craig binary (Rust, single statically-linked executable)

  • Authentication and session management (craig login, craig token)

  • Case management commands (craig case, craig person, craig referral, craig investigation, craig plan)

  • Placement commands (craig placement, craig home, craig kinship)

  • Financial and claims commands (craig financial, craig adjustment, craig claim)

  • Data exchange commands (craig exchange, craig agreement, craig icpc)

  • Reporting commands (generate and export reports)

  • Rules management commands (craig rules list, craig rules evaluate, craig rules import)

  • Security and compliance CLI commands (audit log, security reviews, archive, NIST controls)

  • Output formatting (table, JSON) for scripting and human use

  • Shell completion (bash, zsh, fish)

  • Configurable profiles for multi-jurisdiction deployments

  • Integration tests — ~86 library-level tests across 22 modules (rules, person, referral, investigation, case, plan, home, placement, exchange, agreement, ICPC, auth, workflow, financial, adjustment, claim, reporting, security, archive, nist, intake, kinship)

Phase 10 — Caseworker Web UI

Goal: A browser-based interface for caseworkers built entirely on the public REST APIs — no privileged backend access.

Implemented as craig-web BFF (Axum + Askama + htmx + Alpine.js) instead of the originally planned Dioxus WASM SPA.
  • Case dashboard with live stats — parallel API calls for total cases, open investigations, active placements, pending reviews

  • Case detail view and editing (cases, contacts, household, court orders, plans, tasks)

  • Intake module (referrals, investigations, safety assessments)

  • Placement management interface (foster homes, placements, training, matching)

  • Title IV-E eligibility determination workflow (financial module — payments, rates, claims)

  • Data exchange module (partners, agreements, ICPC with home studies and attachments)

  • Rules management interface (rule sets CRUD, import/export)

  • Reporting and data quality dashboard — quality metrics, issues list, AFCARS/NCANDS workflow pages, 14 handlers

  • OIDC authentication via Keycloak (Authorization Code + PKCE)

  • Georgia Orchard theming with CSS custom properties

  • Accessible design (Section 508 / WCAG 2.1 AA compliance) — the enumerated page set audited by axe-core with zero violations as a blocking pre-push gate; VPAT 2.5 published (page counts and dates live there)

  • Multi-language support

Phase 11 — Constituent and Provider Portal

Goal: Self-service interfaces for constituents, foster parents, and contracted providers, also built entirely on the public REST APIs.

The Multi-Jurisdiction Foundation program (Plan S, complete 2026-06-19 — Plan S: Multi-Jurisdiction Foundation) made the platform state-neutral and is the foundation this portal builds on: bundle-contributed partners / transport / theme / terminology / plugins / composition, plus the surface-agnostic field-permission authz (craig-authz::resolve_field_permission).
  • Constituent application and case status portal

  • Foster parent and kinship caregiver portal

  • CWCA provider portal for bi-directional data submission (supports Phase 5 exchange) — also the home of the surface-bound per-field ownership application (ADR-037 §4–§7: the field_ownership bundle axis, per-surface ownership tables, the pending_edits_<surface> propose/accept/reject queue, BFF lock-icon + Studio), building on Plan Y’s evaluation capability. Tracked by #634 under the still-open epic &50.

  • Accessible design (Section 508 / WCAG 2.1 AA compliance)

  • Multi-language support

Phase 12 — Public Intake Service

Goal: Public-facing child abuse reporting system with web form and API/SDK for third-party integration. See Public Child Abuse Reporting plan for full design.

  • craig-intake service (port 8008; stateless edge — no database, ADR-017)

  • Public web form for anonymous and identified reporters (/report)

  • Public status check via confirmation code (/report/status)

  • Confirmation code generation (RPT-YYYYMMDD-XXXX format)

  • Honeypot anti-bot field (silently accepts, does not persist)

  • IP-based rate limiting (governor crate, configurable per-hour)

  • CAPTCHA integration (Cloudflare Turnstile, disabled in devstack)

  • Partner API with API key authentication (/partner/v1/)

  • API key management — create, list, revoke (admin only)

  • Authenticated report review — list, detail, claim, convert, screen out

  • Report-to-referral conversion (cross-service call to craig-cases)

  • State machine: pending → screening → converted / screened_out

  • RabbitMQ events (6 event types, captured by craig-security audit)

  • craig-intake-sdk crate (AGPL-3.0, typed client with builder API)

  • craig-web public report pages (standalone templates, no auth)

  • craig-web authenticated review pages (caseworker intake module)

  • CLI craig intake command group (8 subcommands)

  • Integration tests (~101 tests) + unit tests (68 + 27 SDK tests)

  • OpenAPI/Swagger documentation

  • E2E tests — Playwright browser tests: intake.spec.ts, intake-review.spec.ts, intake-embedded-ui.spec.ts (the edge public form — the craig-web public-report*.spec.ts were removed with craig-web’s /report in Phase 5, #736)

  • Phase 2a — Reference enums, typed JSONB structs, expanded data model (7 enums, 15+ columns)

  • Phase 2b — Typed validation, file upload endpoint, SDK expansion, craig-store integration

  • Phase 2c — Multi-step wizard form (6-step Alpine.js wizard with expanded fields, file upload on confirmation page)

  • Phase 2d — Full test coverage and documentation for field expansion

  • Phase 2e — JWS integrity verification: signer key registry, detached ES256 signing, verification audit endpoint

  • Phase 2f — Multi-language SDKs: TypeScript (@craig/intake-sdk), Python (craig-intake-sdk), browser signing library (craig-sign.js), Rust SDK signing support

  • CAPTCHA integration testing (Turnstile end-to-end with real token)

Phase 13 — Mobile & Offline-Capable Client

Goal: Field-ready client application for caseworkers operating in rural areas and other low-connectivity environments. Works on phones (iOS, Android), laptops (Windows, macOS, Linux), and tablets. Offline-first with encrypted local storage and bidirectional sync. See Mobile & Offline Client plan and ADR-009 for architecture decision.

  • ADR-009 decision accepted (Tauri 2.0 recommended)

  • craig-client Tauri workspace crate (desktop: Windows, macOS, Linux)

  • craig-sync shared crate (sync engine, conflict resolution)

  • SQLCipher encrypted local database (AES-256 at rest)

  • Keycloak OIDC authentication with offline token caching

  • Pull sync — assigned cases, persons, contacts, placements, reference data

  • Offline write — contact notes, safety assessments, case plan tasks

  • Push sync with field-level conflict detection and resolution UI

  • Mobile builds (iOS, Android) via Tauri 2.0 mobile

  • Biometric unlock and device security

  • Camera integration for document capture

  • Attachment caching for offline document viewing

  • Admin dashboard for device management and remote wipe

  • Sync health monitoring and alerting

Known Issues & Tech Debt

Bugs and technical debt discovered during development and testing. These are tracked here rather than in a separate issue tracker until the project moves to a public GitLab issue board.

Rules Engine — Cache Invalidation Race Condition ✓ RESOLVED

Status: Fixed — replaced reload_all() in API mutation handlers with incremental insert_decision() / remove_decision() cache operations. See Rules Cache Race Fix plan for details.

Reference Data — Remaining Steps

Steps 3-4 from the Reference Data Management plan are complete. Worker identity architecture uses claims.sub (UUID) for API handlers and preferred_username for web display per standard OIDC practice.

  • Admin registry — admin_unit_registry table on craig-security, 5 CRUD + config endpoints, 159 Georgia counties seeded

  • Texas counties — 254 rows seeded via default_admin_units/texas.csv + cargo xtask seed-admin-units (Plan A § Step 13a; closes #225)

  • Worker identity — claims.sub (UUID) for API, preferred_username for display; lazy-populated into worker_identities from JWT claims (Plan A § Step 3) — IdP-neutral, no admin-API dependency

  • Worker display names on detail pages — denormalized _name columns populated from claims.preferred_username at write time, templates render display names with UUID fallback (!43, !44)

Multi-Jurisdictional Authorization ✓ COMPLETE

Plan A — archived May 2026. 14 step MRs (!230–!246) land record-level authorization across all 7 stateful services.

  • Record-level authz engine on zen-engine/JDM — ~140 handler sites enforce per-row access decisions via authz.check(…​) (single row) and authz.auto_scope_list(…​) (LIST).

  • Cross-service assigned_worker_sub UUID denormalization across 11 tables. Identity normalized to claims.sub UUID.

  • Default JDM rulesets for Georgia + Texas under rulesets/{jurisdiction}-authz-{resource}.json.

  • IdP-neutral worker_identities populated lazily from JWT claims.

  • Georgia hardcoded defaults removed — CRAIG_<SVC>JURISDICTION + CRAIG_<SVC>ADMIN_UNIT_LABEL are now required env vars (Plan A § Step 12).

  • Admin units externalized to per-jurisdiction CSVs (georgia 159 + texas 254) with idempotent cargo xtask seed-admin-units upsert (Plan A § Step 13a).

  • BFF/intake i18n hardcodes generic; ICPC deadline + payment-period config externalized (Plan A § Step 13b).

  • 5 ADRs accepted: ADR-023 (architecture), ADR-024 (zen-engine + RMQ cache invalidation), ADR-025 (identity normalization), ADR-026 (IdP-neutral identity), ADR-027 (architectural principles).

Non-Georgia adopters now onboard via rulesets + CSVs + env vars — no code changes.

Service Identity + On-Behalf-Of (Plan E)

Plan E — complete (15 step MRs across 2026-05-09 → 2026-05-11). Service-to-service auth runs on per-service client_credentials against any OIDC issuer, with on-behalf-of worker attribution via the signed X-Craig-Actor header.

  • Steps 1–2/2b — Plan filing + ADR-028 + OIDC discovery convergence + destructive keycloak_*oidc_* rename (!235, !248)

  • Steps 3–7 — Claims::{is_service, service_id, acting_worker, actor} + OidcServiceToken + ActorTokenIssuer + per-service JWKS registry + CraigClientExt outbound helpers (!250–!254)

  • Step 8 — bootstrap wiring; BootstrapResult gains service_token + actor_issuer; 6 standard services migrated (!255)

  • Steps 9–10 — devstack actor-key provisioning + craig-web BFF flip (P0 fix routing JDM input through claims.acting_worker()) + craig-intake outbound flip (!256–!259)

  • Step 11 — audit-log enrichment with actor_service + actor_user_sub columns + filter API (!261)

  • Step 12 — cargo xtask identity verify OIDC conformance gate; soft-check wired into the pre-push validate battery (!262)

  • Step 13 — cargo xtask identity render --backend keycloak\|authentik\|dex reference IaC generator (!263)

  • Step 14a — cargo xtask gen-actor-keys + file-path env loaders (CRAIG_<SVC>__SIGNING_JWK_FILE / CRAIG_PEER_JWKS_JSON_FILE) + 6-step rotation procedure (!264). Step 14b (xtask dev identity provision Keycloak admin-API automation) deferred — devstack works via committed config; per ADR-026 IdP-neutrality the admin-API client isn’t justified.

  • Step 15 — archive (this MR)

Operators of any compliant OIDC backend (Keycloak, authentik, dex, Okta, Azure AD/Entra, ForgeRock, PingFederate, custom) can now deploy CRAIG without backend-specific code in the codebase. ADR-028 Accepted.

API Idempotency Audit

All API endpoints must be safe to retry without unintended side effects. GET, PUT, and DELETE are naturally idempotent; POST create endpoints need idempotency keys or de-duplication to prevent duplicate records on retry. This audit covers all existing services (rules, cases, placement, exchange, financial, reporting, security) and must be applied to all future services.

  • Audit all POST create endpoints across all services for retry safety — 51 POST endpoints classified (11 naturally idempotent, 35 need key, 5 stateless)

  • Add idempotency-key header support where needed — shared IdempotencyLayer middleware in craig-api with DashMap cache, applied to all 8 services

  • Document idempotency guarantees in OpenAPI specs

Pre-1.0 API Contract Stability — Prioritization Guidance

CRAIG is pre-1.0 and its REST API surface is still being redesigned (see the ADR series around intake and identity). While the contracts are still moving, deprioritize work whose value depends on those contracts being frozen — it either gets rewritten every time an API shape changes (negative ROI) or it locks in an immature contract and fights legitimate redesigns.

Defer (revisit at 1.0 / API stabilization):

  • API contract tests (response-schema validation as a stability gate).

  • Heavy external-integration work that bakes in current API shapes — third-party orgs, federal data-exchange partners, and downstream automation that would have to migrate when a response shape evolves.

Prefer instead (uses the APIs as-is without freezing them externally):

  • Internal craig-web / BFF / UX work — consumes the APIs but does not expose a frozen external contract.

  • Compliance-driven features that use the APIs as readers and may surface gaps to fix.

  • Domain features inside CRAIG’s own service boundaries, plus refactor / cleanup / docs / observability work.

A quick prioritization test: "would this work need to be redone if we changed an API response shape next month?" If yes, defer it.

Scope: the caution is for external integrators only

The contract-locking concern applies narrowly to external API integrators who cannot migrate on demand. It does NOT gate first-party or human-facing work, which is in fact more valuable pre-launch because it surfaces gaps before real users have frozen expectations. Do not over-apply a "wait for API stability" gate to:

  • Internal UIs — even those aimed at external user populations (constituents, foster parents, providers). Until users exist in production the UI can be rebuilt freely.

  • Internal tooling and admin surfaces.

  • First-party clients — the mobile/offline app, the web BFF, and the CLI.

  • Compliance-driven reporting that consumes the APIs as a reader.

Default disposition pre-launch: build it, evaluate it, iterate. Lock-in is the exception, not the rule — the deciding question is whether a real production integrator could exist today that would break when the shape changes.

Deployment Work Is Owned by a Separate Team

AWS deployment and standalone-application deployment are owned by a separate team and are out of scope for this repository’s active work. Do not propose plans, MRs, or implementation for them, and skip them when surfacing backlog — mention them for awareness only if a draft or issue references one.

The recognizable artifacts in this family:

  • Draft MR !71 — Craig Deployment to AWS

  • Draft MR !124 — Standalone Craig App Deployment (using container-registry images)

  • Issues #163, #172, #199 — the deployment issues those drafts correspond to

The reason for the carve-out is ownership, not deprioritization: another team is delivering this work, so duplicating or volunteering to take it on here would collide with theirs.

Edit this page · latest