Plan T1 — Foundations & Traits (sub-plan of Plan T umbrella)
On this page
Status
| Step | Description | Status |
|---|---|---|
1 |
[#560] T1.1 SHINES placement decision (lock macro shape). SHINES currently routes through |
Done (2026-06-09) — !662 / |
2 |
[562] T1.2 ErasedAdapter trait + impl_erased_adapter! macro in craig-exchange-contracts. Per ADR-032 A1 + ADR-038 §1 Tier-O. Dep prep: T1.2 promotes |
Done (2026-06-09) — !663 / |
3 |
[#563] T1.3 AuditCodec trait + 10 per-partner impls + struct exports in craig-partner-audit. Per ADR-032 A2 + ADR-038 §2 (trait-location via Rust orphan rule). NEW |
e |
ErasedAdapterError::Inner(Box::new(e))) typed decoder */ }`. Crate exports: |
Done (2026-06-10) — !664 / |
4 |
[564] T1.4 FederalPartnerCategory extension in craig-reference. Per ADR-032 §2.3 (unchanged by amendments) + D3. NEW |
Done (2026-06-10) — !665 / |
5 |
[#565] T1.5 NEW crates/craig-state-bundle. Per ADR-032 A6 + §2.1 + D1. NEW workspace member at * |
Done (2026-06-10) — crate shipped (6 files); 7 tests (2 happy incl. factory materialization smoke / 5 duplicate-sad, one per registry). Dep deviations: |
6 |
[#566] T1.6 NEW crates/craig-state-default seed bundle. Per ADR-032 D6. NEW workspace member. * |
ctx: &BootContext |
Arc::new(CapsAdapter::new(ctx.http_client.clone())) as Arc<dyn ErasedAdapter>)) Tests at |
Done (2026-06-10) — crate shipped; 4 tests (counts / 14-token lockstep / federal-5 / factory token↔kind materialization sweep — bonus beyond spec). !669 / |
7 |
[567] T1.7 per-partner impl_erased_adapter! macro adoption (10 per-partner + 1 host-service invocations). 10 typed-partner crates |
Done (2026-06-10) — #462 OPEN at MR time; REVIEWER WAIVER granted in-session 2026-06-10 ("Waive — proceed now": T1.7 touches per-partner adapter.rs + standard.rs; #462’s cross-handler scan targets service handler modules — near-zero conflict surface); waiver cited verbatim in the MR description. 10 macro invocations + SHINES passthrough + send_with_format/audit_with_format direct methods (transform_outbound gains a format param; shared send_inner extracted); 23 new tests (20 partner + 3 host). !668 / |
8 |
[568] T1.8 per-partner audit_payload_from_value typed decoders + T1.3 codec swap. Each of the 10 typed per-partner crates ships |
e |
ErasedAdapterError::Inner(Box::new(e)))` to surface typed per-partner errors instead of bare |
Done (2026-06-10) — executed in DAG order (T1.8 before T1.7/T1.6 per §Step DAG). 10 decoders + 10 codec-body swaps in one bundled MR; 20 new tests (10 happy round-trip / 10 sad MalformedResponse); codec sad tests updated Serde → Inner; lockstep grep clean. !667 / |
9 |
[#569] T1.9 plan-completion audit + archive (Plan T1). Standard close-out per |
Done (2026-06-10) — this MR (audit + archive close-out). Audit subagent dispatched pre-archive; T1.6 cite backfilled (!669 / |
Context
ADR-032 (Multi-Jurisdiction Partner Registry and Transport Abstraction) anchors Plan S Phase 1; ADR-038 (Trait-Object & Registry Patterns) codifies reusable principles. ADR-032 amendments A1-A11 (landed via !657) resolve the 8-round Plan T iteration findings.
Plan T1 lands the FOUNDATIONS the rest of Plan T (T2/T3) + the downstream Plans U/V/W/X/Y all build on:
-
ErasedAdaptertrait incraig-exchange-contractsis the object-safe seam Plan T2’sAdapterRegistrydispatches through. The typedExchangeAdaptertrait atcrates/craig-exchange-contracts/src/lib.rs:175-215is UNCHANGED (Plan L invariant preserved per ADR-032 A1). -
AuditCodectrait + impls incraig-partner-auditis the typed encode seam Plan T2’sAuditCodecRegistryconsults. Distinct fromPartnerAuditEvent::decode_jsonbatcrates/craig-partner-audit/src/lib.rs:168(read-side JSONB decoder). Closed-aggregator limitation inherited from Plan L Step 5 per ADR-032 A2 + #558. -
FederalPartnerCategoryincraig-referenceis the typed enum thatStateBundle::federal_mapping()returns. Federal-completeness check is REPORT-EMIT time (T3.4 surface), NOT boot — per ADR-032 A7. -
craig-state-bundleNEW crate hostsBundleContributionaggregate (5 Phase-1 fields per §2.1 lines 105-111),StateBundletrait (4 methods per §2.1 lines 99-103),BootContextshared resource type, and 5 registries — per ADR-032 A6 + A4 + ADR-038 §3. -
craig-state-defaultNEW seed bundle implementsStateBundlefor the 10 typed per-partners + 14 partner_type tokens verbatim per ADR-032 D6. SHINES factory NOT contributed bycraig-state-default(host-service registers SHINES at orchestrator boot — Plan T2.1 scope). -
Per-partner macro adoption wires the 10 typed-partner adapters + 1 host-service SHINES catch-all into the erased seam — F-065 SOFT gate.
-
Per-partner typed decoders swap T1.3’s inline
serde_json::from_valuefor per-partner-typed error surfaces.
SHINES placement architecture (T1.1 outcome)
T1.1 locks "SHINES stays catch-all". Architectural consequence:
-
StandardAdapterREMAINS atservices/craig-exchange/src/adapters/standard.rs::StandardAdapter(visibilitypub(crate)— unchanged). -
T1.7 adopts the SHINES-passthrough macro arm at the same site (where
StandardAdapteris reachable). This is the ONLYimpl_erased_adapter!invocation that lives OUTSIDEcrates/craig-partner-*/src/adapter.rs. -
T1.6’s
craig-state-default::DefaultBundle::contribute()returns 10 adapter factories (typed partners only); does NOT include SHINES. -
Plan T2.1 (registry migration) is where the boot orchestrator builds
AdapterRegistryby MERGING bundle contributions (10 typed factories) + adding the host-service SHINES factory entry. Plan T2.1 body specifies this orchestrator-side SHINES injection. -
No
crates/craig-partner-shinesis created; SHINES architecturally lives at host-service layer.
Decisions inherited (D1-D10 from Phase A artifact)
-
D1:
BundleContribution+StateBundlein NEWcrates/craig-state-bundle(T1.5 ships) — ADR-032 A6 -
D2: Factory-shaped adapter contribution +
BootContext(T1.5 ships) — ADR-032 A4 -
D3: Typed
federal_mapping() → HashMap<&'static str, FederalPartnerCategory>onStateBundletrait (T1.4 + T1.5 ship) — ADR-032 §2.1 lines 102 + 124-137 -
D4: F-065 / Plan G Step 6 / #462 hard-gates T2.1 (mentioned in T1.7 as SOFT gate during macro adoption — T1.7 may proceed if #462 open but reviewer prefers waiting)
-
D5:
ExchangeAdapterKindenum DELETED in T3.1 — Plan T3 scope, NOT T1 -
D6: NEW
crates/craig-state-defaultseed bundle (T1.6 ships 10 typed adapters; SHINES added by orchestrator at T2.1) -
D7:
AuditCodectrait + impls + struct exports BOTH incraig-partner-auditper Rust orphan rule (T1.3 ships) -
D8: Mock partners self-state-bound; shared
MockStatedeleted in T2.3 — Plan T2 scope (T1.6 ships mock_routes asvec![]placeholder) -
D9: Temp hardcoded validators preserve 400→400 during T3.1 + T3.3 transition windows — Plan T3 scope
-
D10: T3.4 ships federal mapping seam only; reporting wire-up deferred (per A7) — Plan T3 scope
Hard sequencing gates within Plan T1
-
T1.1 (SHINES decision) → T1.2 (macro shape lock): T1.2 ships TWO macro variants per A1.
-
T1.4 (FederalPartnerCategory enum) → T1.5 (state-bundle crate).
-
T1.2 → T1.7 (macro adoption needs trait + macro to exist).
-
T1.3 → T1.8 (T1.3 ships impls with inline
serde_json::from_value; T1.8 ships per-partner decoders + swaps the T1.3 impls). -
T1.7 + T1.3 + T1.5 → T1.6 (state-default bundle constructs adapter factories referencing
impl ErasedAdapter for <X>Adapter(T1.7) + audit codec types (T1.3) + bundle trait/types (T1.5)). -
T1.9 (archive) — last step.
Calendar
| Step | Scope | Anticipated MRs | Calendar |
|---|---|---|---|
T1.1 |
SHINES decision (lock to catch-all) |
1 |
~0.5 day |
T1.2 |
ErasedAdapter trait + impl_erased_adapter! macro + dep prep |
1 |
~1 day |
T1.3 |
AuditCodec trait + 10 per-partner impls + struct exports |
1 |
~1 day |
T1.4 |
FederalPartnerCategory enum extension |
1 |
~0.5 day |
T1.5 |
NEW craig-state-bundle crate |
1 |
~1 day |
T1.6 |
NEW craig-state-default seed bundle (10 typed adapter factories) |
1 |
~1 day |
T1.7 |
per-partner + host-service macro adoption (11 invocations) |
1 (bundled — RECOMMENDED) |
~1 day |
T1.8 |
per-partner audit_payload_from_value decoders + T1.3 codec swap |
1 (bundled — RECOMMENDED) |
~0.5 day |
T1.9 |
plan-completion audit + archive |
1 |
~0.5 day |
Total: ~9 MRs under bundled strategy; up to 29 MRs if T1.7 ships 11 per-invocation + T1.8 ships 10 per-partner. Bundled strategy strongly RECOMMENDED for calendar alignment + reviewer efficiency.
Step DAG
T1.1 (SHINES decision) T1.4 (FederalPartnerCategory)
↓ ↓
T1.2 (Erased trait + macro) T1.5 (state-bundle crate)
↓ ↓
└─────┬───────────────┬────────┘
↓ ↓
T1.3 (AuditCodec inline from_value)
↓
T1.8 (per-partner typed decoders + T1.3 codec swap)
↓
T1.7 (per-partner + host-service macro adoption — F-065 SOFT gate)
↓
T1.6 (state-default seed bundle, 10 adapter factories)
↓
T1.9 (audit + archive)
Note: T1.7 and T1.8 internal deps are independent — T1.7 needs T1.2; T1.8 needs T1.3. They may execute in either order or in parallel before T1.6.
Threat model
-
Under-specified
BundleContributionshape cascades downstream — Plan W/X/Y addplugins,compositions,field_ownershipetc. as additiveBundleContributionfields. If T1.5 ships a shape that constrains future additions (e.g. fixed-size struct), every Phase 2 plan inherits the defect. Mitigation: T1.5 usesVec<(K, V)>+HashMap<K, V>shapes per ADR-032 §4; ADR-038 §4 field-sourcing pre-flight; T1.5 5-field struct verbatim from §2.1 lines 105-111. -
AuditCodec dep cycle on per-partner crates — naive impl placing
<X>AuditCodecin per-partner crates would cycle (craig-partner-auditALREADY depends on per-partner crates per Plan L Step 5). T1.3 ships impls INcraig-partner-auditper ADR-038 §2 + ADR-032 A2 + Rust orphan rule. Mitigation: T1.3 reviewercargo build -p craig-partner-auditpre-flight. -
Macro hygiene gotchas in
impl_erased_adapter!— declarativemacro_rules!macros must use $crate-rooted paths to avoid call-site dep requirements. T1.2 macro uses$crate::ErasedAdapter,$crate::BoxFuture,::std::boxed::Box::pin,::serde_json::{from_value,to_value}— all reachable fromcraig-exchange-contractsroot or std prelude. Per-partner crates remainfutures-util-free. Mitigation: T1.2 macro tests + T1.7 first-partner adoption (caps) is smoke test before remaining 9. -
T1.6 default-bundle 14-partner_type-token list drifts from migration —
services/craig-exchange/migrations/20260321100000_expand_partner_types.sqlis SOURCE; T1.6 hardcodes them. Mitigation: T1.6 ships locksteppartner_types_match_migration_check_constrainttest mirroringservices/craig-exchange/src/adapters/mod.rs:435. -
Closed-aggregator surfaces during non-georgia state adoption —
PartnerAuditEventis closed (per A2 limitation). Plan T inherits + accepts. #558 tracks decoupling. -
F-065 / #462 timing slips T1.7 — Plan G Step 6 cross-handler DRY scan ideally lands before macro adoption. Mitigation: T1.1-T1.6 non-blocking; T1.7 gate-check via
glab issue view 462. -
SHINES catch-all dispatch double-registration risk — T1.6 ships 10 factories; orchestrator (T2.1) adds SHINES. If orchestrator + bundle BOTH register
"shines",AdapterRegistry::from_bundlesreturnsBundleMergeError::DuplicateEntry { kind: "adapter", key: "shines" }at boot. Mitigation: T1.6’s lockstep test assertspartner_types.count() == 14 && adapter_factories.count() == 10 && !adapter_factories.iter().any(|(k,_)| *k == "shines"). T2.1 body specifies its SHINES injection happens AFTER bundle merge.
Cross-cutting invariants
| Invariant | Enforced by | Verification |
|---|---|---|
ErasedAdapter is object-safe (Tier-O per ADR-038 §1) |
|
|
AuditCodec is object-safe (Tier-O per ADR-038 §1) |
|
|
StateBundle is object-safe (Tier-O per ADR-038 §1) |
|
|
BundleContribution Phase-1 minimum carries 5 fields verbatim from ADR-032 §2.1 |
T1.5 struct definition matches §2.1 lines 105-111 |
ADR-032 §2.1 cited in T1.5 commit message |
BundleContribution grows additively per ADR-032 §4 + ADR-038 §4 |
T1.5 uses |
ADR-032 §4 cited |
StateBundle ships 4 trait methods per §2.1 lines 99-103 |
T1.5 trait + T1.6 DefaultBundle impl complete |
ADR-032 §2.1 cited |
Per-partner crates compile WITHOUT axum or futures-util dep at lib level |
T1.7 macro adoption adds no axum/futures-util dep; mock-routes deferred to T2.3 per A5; macro hygiene routes through |
|
Quality budgets monotonic |
|
Pre-push gate |
Axis coverage opt-out monotonic; new tests tag |
|
Pre-push gate |
|
|
Pre-push gate |
New crate |
T1.5 + T1.6 lib roots |
Plan H Step 10 + Plan M Tier-3 precedent |
Workspace clippy lint set clean (17 denies + nursery group) |
Pre-push battery |
|
T1.6 partner_types match migration CHECK constraint |
|
Per-push test (precedent: |
T1.6 adapter factories DO NOT include "shines" (host-service responsibility) |
|
Per-push test gate |
T1.8 swap complete (no inline |
T1.8 archive-time grep of |
T1.8 reviewer verify |
Risk register
| # | Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|---|
1 |
T1.2 macro hygiene defect propagates to T1.7 11-call adoption |
11-call re-spin |
Low |
T1.2 macro uses |
2 |
T1.5 |
Architectural drift |
Med |
T1.5 uses additive |
3 |
T1.3 AuditCodec dep cycle blocks compile |
T1.3 re-spin |
Low |
ADR-038 §2 + A2 dictate placement; T1.3 reviewer pre-flight |
4 |
T1.7 F-065 / #462 timing slip |
Schedule slip ~5 days |
Med |
T1.1-T1.6 non-blocking; T1.7 mechanical gate via |
5 |
T1.6 14-token list drifts from migration |
Boot registry mismatch |
Low |
T1.6 ships lockstep test mirroring |
6 |
Closed-aggregator (PartnerAuditEvent) surfaces during non-georgia adoption |
Adoption friction |
Low |
#558 filed; T1.3 documents inline; decoupling deferred |
7 |
T1.6 mock_routes |
Mock-server breakage |
Low |
T1.6 commit message references T2.3 follow-up |
8 |
SHINES double-registration (bundle + orchestrator both register "shines") |
Boot |
Low |
T1.6 lockstep test asserts SHINES excluded from bundle adapters; T2.1 body specifies orchestrator injection happens AFTER bundle merge |
9 |
T1.2 dep additions miss workspace-level |
Cargo resolve fail |
Low |
T1.2 description explicitly calls out adding |
10 |
T1.7’s per-call |
SHINES regression |
Low |
T1.7 adds |
Related decisions
-
ADR-032 — Multi-Jurisdiction Partner Registry; amendments A1/A2/A4/A6/A7/A11 anchor T1.2/T1.3/T1.5/T1.6.
-
ADR-038 — Trait-Object & Registry Patterns; §1 Tier-O cited by T1.2/T1.3/T1.5 object-safety smokes; §2 trait-location cited by T1.3 AuditCodec placement; §3 registry factory shape cited by T1.5 ErasedAdapterFactory; §4 field-sourcing cited by T1.5 BundleContribution + T1.6 mock_routes deferment.
-
ADR-030 — Status vocabulary on every cell.
-
Plan T umbrella — parent; this Plan T1 body sits at Plan T umbrella Step 1.
-
Plan S — grandparent; Plan T1 sits at Plan S Step 4 (T1 body filed) / Step 5 (T1 executed).
-
Plan G — F-065 / Plan G Step 6 / #462 SOFT-gates T1.7.
-
Plan L — Plan L Step 5 PartnerAuditEvent landed; T1.3 + T1.8 extend the pattern.
-
the pre-1.0 destructive-rebuild posture — N/A for T1 (no DDL changes).
-
the service-initialization pattern — orchestrator pattern referenced by future T2.1 bundle + SHINES injection wiring.
-
the quality-budget enforcement gate — B3a (
serde_json::Valuesrc budget) verification discipline applies to T1.2 + T1.3; STRUCTURAL-VALUE markers per-site. -
#462 (Plan G Step 6 / F-065) — SOFT-gates T1.7.
-
#558 (closed-aggregator decoupling tracking) — known limitation inherited at T1.3.