Skip to content

Admin Portal Trio — Consistency Reconciliation Findings

Status: REVIEW 2026-05-12 Owner: SD (CPO/CTO) Scope: Cross-reference reconciliation pass across three Phase-B admin-portal draft specs: - PR #857docs/specs/procedure-onboarding-admin-ui.md (branch docs/procedure-onboarding-admin-ui-spec) — 484 lines, ~25 agent-days - PR #868docs/specs/provider-onboarding-admin-ui.md (branch docs/provider-onboarding-admin-ui-spec) — 572 lines, ~24.5 agent-days - PR #869docs/specs/capabilities-and-readiness-scoring.md (branch docs/capabilities-readiness-spec) — 738 lines, ~24-30 agent-days Method: read each spec in full, build a cross-reference matrix on data-model deltas / endpoints / events / permissions / PR sequencing / open questions / validation rules / MVP scope, then surface conflicts and overlaps. References: - All three sibling specs above - docs/specs/admin-portal-users-tenants-feature.md — Phase A pattern reference all three siblings extend - ADR-0018 §A, §H, §J, §K, §M, Amendment "Admin Console Operational Screens" - ADR-0026 — parameter registry - .claude/rules/definition-of-done.md — migration head sequencing + parallel-safe partitioning rule


1. Summary

Total findings: 22. Split:

Severity Count Description
Major (blocking) 4 Same table / endpoint / event-type claimed by two specs — must resolve before any of the three lands
Moderate (rework recommended) 9 Cross-reference errors, PR-sequencing dependencies missing, scope-overlap that wastes effort if not deduped
Minor (nits / tightening) 9 Typos, missing back-references, redundant phrasing, dedupe-able open questions

Applied inline (in this branch): 6 (cross-reference + typo-level fixes that need no SD judgment). Flagged for SD: 16 (architectural ownership calls, PR-sequencing reshuffles, open-question consolidation).

Consolidated SD question list (deduped): 12 open questions (down from 25 distinct entries across the three specs).

Recommended unified PR roadmap: 17 PRs interleaved in dependency order over 6-7 calendar weeks with parallel dispatch.

Effort estimate (re-estimated with shared infrastructure): ~67-70 agent-days vs naive 80-day sum — savings of ~10-13 agent-days (~13-16%) from dedupe + shared component reuse.


2. Findings

2.1 Data model overlap & contracts

FINDING #1 — MAJOR: provider_capabilities + procedure_capability_requirements claimed by both #857 and #869.

  • #857 §3.2 Delta C defines and creates both tables with full DDL (UNIQUE constraints, ENUMs, columns).
  • #869 §3.1 + §3.2 also defines and creates the same two tables — and adds richer columns (is_stale, staleness_reason).
  • Resolution: #869 is the canonical owner (it's the dedicated capabilities spec). #857 must drop Delta C entirely and reference #869 §3.1/§3.2 as the source. #857 PR-2's table creation step becomes "wire UI to existing capabilities endpoints from #869 PR-D".
  • Impact: prevents a migration-head collision (two specs creating the same provider_capabilities table). Saves ~1-2 agent-days from #857 PR-2.

FINDING #2 — MAJOR: provider_procedures.readiness_score column ownership ambiguous.

  • #857 Delta B adds readiness_score + readiness_score_computed_at columns to provider_procedures.
  • #869 §5.5 says: "The score is persisted on provider_procedures.readiness_score (column added by PR #857 Delta B)."
  • Resolution: ownership is clear (#857 lands the column, #869 lands the algorithm). But this creates a hard sequencing dependency: #869 PR-C cannot land before #857 PR-1. Both specs should explicitly state this. Applied inline to #869 §10 PR-C dependency line and #857 §9.1 MVP scope note.

FINDING #3 — MODERATE: acceptance_criteria JSONB column on provider_procedures is in #857 Delta B but acceptance criteria tab is reused by #868 (procedure offerings axis flipped). Cross-reference missing.

  • 857 §5.4 FacilityReadinessSheet tab 3 = Acceptance criteria editor.

  • 868 §5.4 Tab 3 says "reuses the FacilityReadinessSheet from procedure spec §5.4 rendered with axis flipped" — so the same JSONB editor must work in both contexts. No conflict in data, but the cross-reference back to #857 Delta B should be explicit.

  • Applied inline: added a clarifying note in #868 §3.1 referencing #857 Delta B's acceptance_criteria column.

FINDING #4 — MINOR: #869 §3.1 ENUM names use capability_* prefix; #857 §3.2 inline ENUM names (in the DDL block) do not.

  • 869 uses capability_category, capability_status, capability_verification_source, capability_criticality.

  • 857 Delta C DDL uses bare ENUM('diagnostic','operational','logistical') inline without naming the type.

  • Since #857 Delta C is being dropped (finding #1), this resolves naturally. No action.

2.2 Endpoint overlap

FINDING #5 — MAJOR: GET / PUT / DELETE /api/v1/admin/providers/{provider_id}/capabilities/{capability_code} claimed by both #857 and #869.

  • #857 §4.3 lists all three endpoints under "Provider capability endpoints (new, but ADR-0018 §J also needs them for the provider portal — coordinate)".
  • #869 §7.2 lists the same three endpoints. #869 explicitly states: "The endpoints PR #857 §4.3 declares need to actually exist. This spec's PRs deliver [these]."
  • Resolution: #869 PR-D ships these endpoints. #857 should mark §4.3 as "endpoints consumed from #869 PR-D, not delivered here." Applied inline as a clarifying note at top of #857 §4.3.

FINDING #6 — MODERATE: POST /api/v1/admin/procedures/{code}/facilities/{provider_id}/recompute-readiness in #857 §4.2 — algorithm lives in #869.

  • 857 §4.2 declares the endpoint that triggers recompute.

  • 869 §5.5 owns the recompute logic + the background task.

  • Resolution: the endpoint can be defined in either, but it must call into the readiness_scoring.py module that #869 PR-C ships. Recommend moving the endpoint definition to #869 PR-D (alongside the other admin capability endpoints) and have #857's UI call it. Flagged for SD.

FINDING #7 — MINOR: GET /api/v1/admin/procedures/{procedure_code}/facilities (#857 §4.2) vs GET /api/v1/admin/providers/{provider_id}/procedures (#868 §4.2) return the same provider_procedures join with different axes.

  • Both endpoints are needed (different UI surfaces). No conflict. Apply inline: add a cross-reference in #868 §4.2 noting axis-flip parity with #857. Applied inline.

FINDING #8 — MODERATE: Bulk-import endpoints are independently spec'd in #857 (procedures) and #868 (providers).

  • Paths differ (/admin/procedures/bulk-import vs /admin/providers/bulk-import). No conflict.
  • Both follow the same dry-run / transactional pattern. Recommend factoring out a shared BulkImportService (one in app/services/admin/bulk_import.py) that both specs' PRs depend on. Saves ~1 agent-day. Flagged for SD.

2.3 Workflow integration

FINDING #9 — MODERATE: #868 wizard step 5 (Procedures) writes to provider_procedures — requires #857 PR-1's provider_procedure_admin_service.

  • 868 §9.1 says "Procedure-link CRUD (read-only initially — write side is in procedure spec PR-1)". Good — explicit dependency call-out.

  • But #868 §6.1 step 5 says "N rows in provider_procedures (cost min/avg/max, currency, success_rate, annual_volume, lead_surgeon)". This is a write. Either:
  • (a) #868 PR-1 MVP defers procedure-link writes to follow-up (and step 5 is "linking only", with cost/volume edited via #857's UI after-the-fact), or
  • (b) #868 PR-1 MVP depends on #857 PR-1 having landed.
  • Recommend (a): decouple #868 PR-1 from #857 PR-1. Wizard step 5 becomes "pick procedures from catalog (autocomplete)"; the readiness inputs (cost, volume) are filled in later via the procedure-detail page after provider activation. Applied inline as a clarifying note in #868 §6.1 step 5.

FINDING #10 — MINOR: #868 §5.4 Tab 3 "reuses the FacilityReadinessSheet from procedure spec §5.4" — but #857 owns the React component code.

  • Coordination needed at impl time: the component path (apps/admin-app/src/components/FacilityReadinessSheet.tsx or similar) should be agreed upfront so both specs' implementers don't fork. Flagged for SD (file-naming convention is an impl detail but worth pinning now).

2.4 PR sequencing

FINDING #11 — MAJOR: Hidden dependency cycle if naively sequenced.

  • 857 PR-1 MVP creates readiness_score column → unblocks #869 PR-C.

  • 869 PR-A creates provider_capabilities + procedure_capability_requirements tables → unblocks #857 PR-2.

  • 869 PR-D ships the admin capability endpoints → unblocks #857 PR-2's UI panel.

  • Resolution: unified roadmap (§4 below). No actual cycle if ordered correctly, but the three specs in isolation each present their PR plan without acknowledging the others' sequencing constraints.

FINDING #12 — MODERATE: #857 §9.2 PR-2 says "create provider_capabilities + procedure_capability_requirements tables + capability UI panel + readiness-score-recompute background task" — but all three of those non-UI items belong to #869.

  • Resolution: #857 PR-2 scope shrinks to "wire admin UI to capability endpoints from #869 PR-D" (~2 agent-days instead of 5-6). Applied inline to #857 §9.2 PR-2 row.

2.5 Open SD questions — duplicates

FINDING #13 — MODERATE: 25 open questions across three specs reduce to 12 distinct decisions. See §3 below for the deduped list.

2.6 Estimated implementation sizes

FINDING #14 — MODERATE: Naive sum is 25+24.5+27 = ~76.5 agent-days; real total with shared infra is ~67-70 agent-days (savings of ~10-13%). See §6 below for breakdown.

2.7 Permission model consistency

FINDING #15 — MINOR: Permissions across the trio use consistent resource:verb namespace but have one shared permission (provider_procedure:write) defined in two places.

  • 857 §9.1 seeds provider_procedure:write.

  • 868 §9.1 also seeds provider_procedure:write ("shared with procedure spec").

  • Resolution: Whichever PR lands first owns the seed. Recommend the unified roadmap puts #857 PR-1 (or #869 PR-D) as the canonical seeder; #868 PR-1 references but does not re-seed. Applied inline as a clarifying note in #868 §9.1.

FINDING #16 — MINOR: admin:force permission referenced across all three specs but never formally introduced in this trio.

  • Existing in the codebase per admin-portal-users-tenants-feature.md Phase A. No action needed — pre-existing.

2.8 Event types

FINDING #17 — MAJOR: ADMIN_PROVIDER_CAPABILITY_UPDATED defined in both #857 §3.3 and #869 §3.8.

  • 857 §3.3 lists it singular.

  • 869 §3.8 lists ADMIN_PROVIDER_CAPABILITY_CREATED, _UPDATED, _DELETED, _REVERIFIED (richer set).

  • Resolution: #869 owns. #857 should remove the line (capability events emitted by the endpoints #869 PR-D ships). Applied inline to #857 §3.3.

FINDING #18 — MINOR: ADMIN_PROVIDER_PROCEDURE_UPDATED defined in #857 §3.3 (cell-level inline edit) and #868 §3.3 (ADMIN_PROVIDER_PROCEDURE_LINKED|UNLINKED).

  • These are complementary, not duplicates: #857 owns cell edits (cost, volume changes), #868 owns linking/unlinking a procedure to a provider. No conflict. Cross-reference added inline to #868 §3.3 noting the split. Applied inline.

2.9 Validation rules

FINDING #19 — MODERATE: Readiness score computation is described in two places with consistent but not identical wording.

  • 857 §8 says "When admin saves a cell, readiness_score recomputed and persisted (input: own row fields + linked provider_capabilities + procedure_capability_requirements)" — informal.

  • 869 §5 is the formal algorithm.

  • Resolution: #857 §8 should explicitly reference #869 §5 as the normative algorithm. Applied inline.

FINDING #20 — MINOR: Currency / cost validation is duplicated (#857 §7.1, §7.2 and #868 §7.1, §7.2).

  • Same rules in both specs — no conflict but redundant. No action — acceptable redundancy for spec readability.

2.10 MVP scope alignment

FINDING #21 — MODERATE: All three MVPs can ship in parallel only if the data-model deltas are sequenced.

  • 869 PR-A (capabilities tables) is the keystone — should land first.

  • After PR-A: #857 PR-1 and #868 PR-1 can run in parallel (disjoint schema touches: procedure_requirements/provider_procedures vs providers/contact_persons/accreditations).
  • 869 PR-C (scoring) requires #857 PR-1 to have landed (readiness_score column).

  • Roadmap §4 sequences this explicitly.

FINDING #22 — MINOR: Feature flags are spec'd inconsistently.

  • 857 §12 names procedure_admin_ui_enabled.

  • 868 §12 names provider_onboarding_admin_ui_enabled.

  • 869 §13 names readiness_scoring_weights_v1, readiness_critical_gap_disqualifies, capability_reverification_email_enabled.

  • All follow feedback_flagsmith_dual_env rule (both envs together). No conflict. No action.

3. Consolidated SD Question List (ranked by impact)

After dedupe across the three specs, 12 distinct decisions remain. Ranked high → low impact.

# Question Sources Default in specs Impact
Q1 Capability vocabulary management — YAML + redeploy, or in-app CRUD page in PR-A? #857 §11.7, #869 §12.1 YAML in MVP, in-app deferred to PR-4 Shapes #869 PR-A scope + #857 follow-up
Q2 Self-service onboarding scope — admin-only for v1? #857 §11.5, #868 §11.2 Admin-only confirmed Sets Phase 2 boundary
Q3 Approve vs activate split — separate or one-click? #868 §11.1 Separate (two buttons) Changes wizard step 6 UX
Q4 Bulk import permission gate — super_admin only, and does it skip review? #857 §11.4, #868 §11.5 super_admin only; #868 skips review, #857 doesn't apply Affects 2 PRs (one each spec)
Q5 Hard-disqualify on critical capability gap — opt-in Flagsmith flag, default off? #869 §12.6 Soft penalty default Matching engine policy
Q6 Readiness weight distribution — 40/35/25 fixed or procedure-category-conditional? #869 §12.3 40/35/25 from ADR-0018 §J Algorithm parameter
Q7 Multi-facility scoping — capabilities on provider_id or facility_id? #869 §12.4 provider_id (1:1 today) Migration design
Q8 Synchronous vs async Neo4j sync on admin writes? #857 §11.8, #869 §4.2 Synchronous Latency vs durability tradeoff
Q9 Document upload (R2-presigned-URL) in PR-1 or PR-2? #868 §11.3 PR-2 +2 agent-days if PR-1
Q10 Procedure versioning — MVP needs it? #857 §11.1 No (mutable in place + audit log) Schema impact if yes
Q11 Patient-reported capability discrepancy UI — PR-E or separate spec? #869 §12.7 PR-E unclear Patient-facing scope
Q12 Staleness reminder email — opt-in flag, default off? #869 §12.8 OFF (ops-driven v1) Ops workflow

Removed/merged (no longer distinct): - "platform_admin vs super_admin" — covered by Q4 (per-permission decision, not global) - "Currency handling" (#857 §11.6) — covered by CLAUDE.md "All money in USD cents + ISO 4217" rule; no decision needed - "Admin override on patient_satisfaction" (#868 §11.7) — left as-is (read-only in MVP) - "Onboarding-status visibility on storefront" (#868 §11.8) — answered (hidden until activated) - "Capability vocabulary size 45-60" (#869 §12.2) — implementation detail - "Doctor onboarding inside wizard" (#868 §11.6) — answered (callout-only in MVP) - "Capability name denormalization" (#869 §12.5) — implementation detail - "Recovery-flow capability reuse" (#869 §12.9) — deferred, no decision needed - "Minimum procedure count at submit" (#868 §11.4) — implementation detail, default acceptable - "Tenant-scoped vs global procedure catalog" (#857 §11.2) — answered (global, matches today's shape) - "Who can edit readiness scores" (#857 §11.3) — answered by permission spec - "Provider self-edit pathway" (#857 §11.5) — subsumed by Q2 - "Capabilities scope split MVP vs PR-2" (#857 §11.7) — answered by Finding #1 resolution


Dependency-ordered. Calendar at 1.5-2 agent-days per calendar-day with parallel dispatch.

WEEK 1
  PR-869-A     Capabilities data model + repos + YAML vocabulary  (4-5 d) [keystone]

WEEK 2  (3 chains parallel)
  PR-857-1     Procedure onboarding MVP — admin UI + procedure_requirements/provider_procedures Deltas A+B (incl readiness_score column)  (10 d, BE+FE split)
  PR-868-1     Provider onboarding MVP — wizard + lifecycle + provider_accreditations/contact_persons  (11 d, BE+FE split)
  PR-869-B     Neo4j projection helpers + sync endpoint  (3 d)
  PR-869-F     Annual staleness cron (#711)  (2-3 d)

WEEK 3
  (PR-857-1 and PR-868-1 complete; merge in dependency order)
  PR-869-D     Admin capability endpoints + perms  (4 d)
  PR-869-C     Readiness scoring + matching wiring  (5-6 d) [requires PR-857-1 Delta B]

WEEK 4
  PR-857-2     Wire capability UI panel to PR-869-D endpoints  (~2 d, reduced from spec estimate)
  PR-868-2     Document upload (R2 presigned URLs)  (4-5 d)
  PR-869-E     Patient-facing readiness panel  (5-6 d) [requires PR-869-C]

WEEK 5
  PR-857-3     Procedure bulk import  (3-4 d)
  PR-868-3     Recovery-provider variant tab  (3-4 d)
  PR-857-4     Capability vocabulary management page  (2-3 d) [resolves Q1 if SD picks in-app]

WEEK 6
  PR-857-5     Procedure history viewer  (1-2 d)
  PR-857-6     Recompute all readiness button  (1-2 d)
  PR-868-4     Provider bulk import  (3-4 d) [reuses BulkImportService from PR-857-3 — see Finding #8]
  PR-868-5     Provider history viewer  (1-2 d)

WEEK 7
  PR-868-6     Onboarding progress dashboard + Telegram alerts  (1-2 d)

Total: 17 PRs over ~6-7 calendar weeks (vs the ~9-11 weeks naive sum if each spec ran serial).

Critical-path PRs (block downstream work): - PR-869-A blocks PR-869-B, PR-869-C, PR-869-D, PR-869-F, PR-857-2 - PR-857-1 blocks PR-869-C, PR-857-2 through PR-857-6 - PR-868-1 blocks PR-868-2 through PR-868-6 - PR-869-C blocks PR-869-E

True-parallel opportunities (zero shared file conflicts): - Week 2 chains (857-1, 868-1, 869-B, 869-F) all touch disjoint files. Run in 4 separate worktrees. - Week 4 (857-2, 868-2, 869-E) — disjoint. - Week 5 (857-3, 868-3, 857-4) — disjoint.

Migration head sequencing (per .claude/rules/definition-of-done.md): - PR-869-A introduces ENUMs + 2 tables (one migration head). - PR-857-1 introduces Deltas A + B columns (one migration head, rebases on 869-A). - PR-868-1 introduces Deltas A + B + C + D + tables (one migration head, rebases on 857-1). - Subsequent PRs have at most one migration each; rebase on landing-time head.


5.1 #857 (docs/specs/procedure-onboarding-admin-ui.md)

Section Edit Type
§3.2 Delta C Drop the inline DDL for provider_capabilities and procedure_capability_requirements. Replace with a cross-reference: "Tables created by #869 PR-A — see capabilities-and-readiness-scoring.md §3.1 and §3.2." Applied inline
§3.3 Remove ADMIN_PROVIDER_CAPABILITY_UPDATED (owned by #869) Applied inline
§4.3 Add note: "Endpoints consumed from #869 PR-D, not delivered in this spec." Applied inline
§8 Reference #869 §5 as normative for readiness algorithm Applied inline
§9.2 PR-2 row Scope shrinks from "create tables + UI panel + recompute task" to "wire admin UI to capability endpoints from #869 PR-D". Reduce estimate from 5-6 to ~2 agent-days. Applied inline
§11 (open questions) Q11.2 (tenant-scoped catalog), Q11.3 (who edits readiness), Q11.7 (capabilities scope split), Q11.5 (provider self-edit) — note they're resolved by the consolidation pass Flagged for SD

5.2 #868 (docs/specs/provider-onboarding-admin-ui.md)

Section Edit Type
§3.1 Add cross-reference: "provider_procedures.acceptance_criteria column defined by #857 Delta B." Applied inline
§3.3 Add note clarifying split with #857: "#857 owns ADMIN_PROVIDER_PROCEDURE_UPDATED (cell-level), this spec owns _LINKED/_UNLINKED (relation-level)." Applied inline
§4.2 Add cross-reference to #857 §4.2: "Axis-flipped twin of GET /api/v1/admin/procedures/{procedure_code}/facilities — same join, different lead axis." Applied inline
§6.1 step 5 Clarify: "Procedure linking only in PR-1 MVP — cost/volume readiness data edited via #857's FacilityReadinessSheet after provider activation." Applied inline
§9.1 Note: provider_procedure:write permission seeded by #857 PR-1, not re-seeded here. Applied inline
§11.2 Subsumed by consolidated Q2 — note resolution Flagged for SD
§11.5 Bulk import skip-review default — confirm with consolidated Q4 Flagged for SD

5.3 #869 (docs/specs/capabilities-and-readiness-scoring.md)

Section Edit Type
§5.5 Reaffirm hard dependency: "Requires provider_procedures.readiness_score column landed by #857 PR-1 Delta B; PR-C cannot land before #857 PR-1." Applied inline
§7.2 Strengthen ownership claim: "These endpoints replace #857 §4.3's placeholders — PR-D delivers them; PR #857's UI consumes them." Applied inline
§10 PR-C row Add explicit dependency on #857 PR-1 (already noted but tighten) Applied inline
§12.1 Subsumed by consolidated Q1 — note Flagged for SD
§12.6 Subsumed by consolidated Q5 — note Flagged for SD

6. Effort Re-estimate

Spec Standalone (per its §10) Adjusted with dedupe Δ
#857 25 agent-days 21-22 (PR-2 shrinks from 5-6 to ~2; Delta C migration dropped) -3 to -4 d
#868 24.5 agent-days 22 (procedure-link write deferred; shared BulkImportService) -2 to -3 d
#869 24-30 agent-days 24-30 (no change — already keystone) 0
Cross-cutting savings -3 to -4 (shared FacilityReadinessSheet component + shared BulkImportService + shared audit pattern + shared permission seeding) -3 to -4 d
Total ~73.5 - 79.5 (naive sum: ~76.5) ~67-70 -7 to -10 d (~10-13% savings)

Calendar: at 1.5-2 agent-days/calendar-day with the 17-PR parallel dispatch plan in §4, total elapsed time is ~6-7 weeks end-to-end, vs ~9-11 weeks naive serial.

Confidence: ±2 agent-days per spec. The savings depend on: 1. SD approving Finding #1 resolution (drop #857 Delta C) — high confidence 2. Finding #8 shared BulkImportService — medium confidence (impl team must agree) 3. Finding #10 shared FacilityReadinessSheet component — medium confidence (component contract needs upfront pinning)


  1. This findings doc first — it provides context for the three sibling PRs.
  2. Then #869 (the keystone capabilities spec) — it owns the data model the other two consume.
  3. Then #857 (procedure onboarding) — it adds the readiness_score column #869 PR-C needs.
  4. Then #868 (provider onboarding) — it consumes both.

Approve Findings #1, #2, #5, #11, #17 (the 5 majors) before greenlighting any sibling PR to merge.


Last updated: 2026-05-12 — REVIEW awaiting SD approval.