{
  "endpoints": [
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_tasks_list",
      "method": "GET",
      "notes": "Task records are backend truth for workbench state.",
      "path": "/api/agents/tasks",
      "query_params": [
        "status",
        "lane",
        "limit"
      ],
      "response_sections": [
        "tasks"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Lists agent task ledger records.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "lane",
        "title",
        "instructions",
        "source_systems",
        "scope",
        "mutation_level",
        "model_provider",
        "break_glass_acknowledged"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_create",
      "method": "POST",
      "notes": "Policy verdict must be explicit at creation.",
      "path": "/api/agents/tasks",
      "query_params": [],
      "response_sections": [
        "task",
        "policy_verdict"
      ],
      "status_codes": [
        200,
        201,
        400,
        401,
        409,
        500
      ],
      "summary": "Creates a governed agent task.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "lane",
        "title",
        "instructions",
        "mutation_level",
        "model_provider"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_from_it_request",
      "method": "POST",
      "notes": "Source request lineage must remain in task scope.",
      "path": "/api/agents/tasks/from-it-request/{request_number}",
      "query_params": [],
      "response_sections": [
        "task",
        "policy_verdict",
        "itr_context"
      ],
      "status_codes": [
        200,
        201,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Creates an agent task seeded from an ITR.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_detail",
      "method": "GET",
      "notes": "Includes policy verdict and terminal reason when present.",
      "path": "/api/agents/tasks/{task_id}",
      "query_params": [],
      "response_sections": [
        "task"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns one task record.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "reason",
        "break_glass_acknowledged"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_approve",
      "method": "POST",
      "notes": "Owner break-glass must be explicit and audited.",
      "path": "/api/agents/tasks/{task_id}/approve",
      "query_params": [],
      "response_sections": [
        "task",
        "trace"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Approves a task requiring operator review.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_artifacts",
      "method": "GET",
      "notes": "Artifact payloads should reference safe storage metadata, not secrets.",
      "path": "/api/agents/tasks/{task_id}/artifacts",
      "query_params": [],
      "response_sections": [
        "artifacts"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns artifact records for one task.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "reason"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_cancel",
      "method": "POST",
      "notes": "Cancellation should be traceable.",
      "path": "/api/agents/tasks/{task_id}/cancel",
      "query_params": [],
      "response_sections": [
        "task",
        "trace"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Cancels an agent task.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_dispatch",
      "method": "POST",
      "notes": "Unconfigured Service Bus returns not_configured and records trace.",
      "path": "/api/agents/tasks/{task_id}/dispatch",
      "query_params": [],
      "response_sections": [
        "status",
        "dispatch",
        "task"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Dispatches a task to Service Bus / AKS worker lane.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "reason"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_retry",
      "method": "POST",
      "notes": "Retry should preserve prior traces and artifacts.",
      "path": "/api/agents/tasks/{task_id}/retry",
      "query_params": [],
      "response_sections": [
        "task",
        "trace"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Marks an agent task for retry.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "reason",
        "remediation"
      ],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_rollback",
      "method": "POST",
      "notes": "Production write lanes require rollback/remediation metadata.",
      "path": "/api/agents/tasks/{task_id}/rollback",
      "query_params": [],
      "response_sections": [
        "task",
        "trace"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Requests rollback or remediation for an agent task.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_run",
      "method": "POST",
      "notes": "Missing SDK or policy denial must record explicit blocked state.",
      "path": "/api/agents/tasks/{task_id}/run",
      "query_params": [],
      "response_sections": [
        "status",
        "task",
        "sdk_available",
        "artifacts",
        "traces"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Runs the task through the local OpenAI Agents SDK hook.",
      "tests": [
        "tests/test_agents_runner.py",
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_task_traces",
      "method": "GET",
      "notes": "Policy blocks, SDK missing, dispatch, worker receipt, and terminal transitions must be traceable.",
      "path": "/api/agents/tasks/{task_id}/traces",
      "query_params": [],
      "response_sections": [
        "traces"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns trace events for one task.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "agent-workbench",
      "handler": "_handle_agent_workspaces",
      "method": "GET",
      "notes": "Use for task composer defaults and policy-aware UI state.",
      "path": "/api/agents/workspaces",
      "query_params": [],
      "response_sections": [
        "lanes",
        "sources",
        "role",
        "providers",
        "policy_profiles"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns available agent lanes, role profile, source systems, and provider policy posture.",
      "tests": [
        "tests/test_agents_service.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "action",
        "scope",
        "metadata"
      ],
      "cache": "none",
      "family": "contract-intelligence",
      "handler": "_handle_contract_intelligence_queue_job",
      "method": "POST",
      "notes": "Supported jobs include registry sync, normalization, and corpus operationalization.",
      "path": "/api/contract-intelligence/queue-job",
      "query_params": [],
      "response_sections": [
        "status",
        "job"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        500
      ],
      "summary": "Queues a contract-intelligence upkeep job.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "contract-intelligence",
      "handler": "_handle_contract_intelligence_queue_status",
      "method": "GET",
      "notes": "Contract intelligence queue is a targeted registry path, not broad platform SQL cutover.",
      "path": "/api/contract-intelligence/queue-status",
      "query_params": [],
      "response_sections": [
        "queue",
        "jobs"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns contract-intelligence queue status.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "contract-intelligence",
      "handler": "_handle_contract_intelligence_registry_summary",
      "method": "GET",
      "notes": "Registry is governed evidence, not raw file browsing.",
      "path": "/api/contract-intelligence/registry-summary",
      "query_params": [],
      "response_sections": [
        "registry",
        "counts",
        "coverage"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns contract registry summary and posture.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "contract-intelligence",
      "handler": "_handle_contract_intelligence_schedules",
      "method": "GET",
      "notes": "Used by internal contract-ops UI.",
      "path": "/api/contract-intelligence/schedules",
      "query_params": [],
      "response_sections": [
        "schedules"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Lists contract-intelligence recurring schedules.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "schedule_id",
        "dry_run"
      ],
      "cache": "none",
      "family": "contract-intelligence",
      "handler": "_handle_contract_intelligence_schedule_materialize",
      "method": "POST",
      "notes": "Use dry-run before schedule mutation where possible.",
      "path": "/api/contract-intelligence/schedules/materialize",
      "query_params": [],
      "response_sections": [
        "status",
        "materialized_jobs",
        "preview"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        500
      ],
      "summary": "Materializes contract-intelligence schedules into queued jobs.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_export_workbooks",
      "method": "GET",
      "notes": "Only exact eligible scopes should be included.",
      "path": "/api/ops/it-requests/export-workbooks",
      "query_params": [
        "request_numbers"
      ],
      "response_sections": [
        "application/zip"
      ],
      "status_codes": [
        200,
        400,
        401,
        409,
        500
      ],
      "summary": "Exports a batch workbook package for eligible ITRs.",
      "tests": [
        "tests/test_report_workbook.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "route cache with refresh bypass",
      "family": "itr-workbench",
      "handler": "_handle_it_request_open_workbench",
      "method": "GET",
      "notes": "UI should treat rows as the server-authoritative filtered slice.",
      "path": "/api/ops/it-requests/open-workbench",
      "query_params": [
        "page",
        "page_size",
        "search",
        "lane",
        "status",
        "refresh"
      ],
      "response_sections": [
        "rows",
        "pagination",
        "filter_options",
        "cache"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns cached, paginated Salesforce ITR workbench rows.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py",
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "filters",
        "request_numbers",
        "preview_token"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_queue_run_batch_execute",
      "method": "POST",
      "notes": "Should preserve per-request blocker details.",
      "path": "/api/ops/it-requests/queue-runs/execute",
      "query_params": [],
      "response_sections": [
        "queued",
        "blocked",
        "results"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        409,
        500
      ],
      "summary": "Executes bulk queueing for eligible ITR run plans.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "filters",
        "request_numbers"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_queue_run_batch_preview",
      "method": "POST",
      "notes": "Preview before mutating queue state.",
      "path": "/api/ops/it-requests/queue-runs/preview",
      "query_params": [],
      "response_sections": [
        "preview",
        "eligible",
        "blocked"
      ],
      "status_codes": [
        200,
        400,
        401,
        500
      ],
      "summary": "Previews bulk queueing for ready ITR run plans.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "dry_run",
        "limit",
        "since"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_full_mirror_sync",
      "method": "POST",
      "notes": "Requires backend Salesforce and Azure SQL bindings.",
      "path": "/api/ops/it-requests/sync/full-mirror",
      "query_params": [],
      "response_sections": [
        "status",
        "sync_run_id",
        "counts",
        "blockers"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        500
      ],
      "summary": "Starts or executes the full Salesforce ITR mirror sync.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "route cache with refresh bypass",
      "family": "itr-workbench",
      "handler": "_handle_it_request_workbench_detail",
      "method": "GET",
      "notes": "Detail loads should not depend on the open-workbench list request.",
      "path": "/api/ops/it-requests/{request_number}",
      "query_params": [
        "refresh"
      ],
      "response_sections": [
        "request",
        "history",
        "artifacts",
        "run_plan_summary",
        "remediation"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns the detail drawer payload for one ITR.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_evidence_bundle",
      "method": "GET",
      "notes": "Raw Salesforce body URLs and credentials stay backend-only.",
      "path": "/api/ops/it-requests/{request_number}/evidence-bundle",
      "query_params": [],
      "response_sections": [
        "request",
        "counts",
        "evidence_sources",
        "search_documents"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns sanitized Salesforce ITR evidence bundle.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "upload_adls",
        "upload_search",
        "limit"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_evidence_refresh",
      "method": "POST",
      "notes": "Backend-only source body retrieval.",
      "path": "/api/ops/it-requests/{request_number}/evidence-refresh",
      "query_params": [],
      "response_sections": [
        "status",
        "materialized_files",
        "extracted_chunks",
        "search_upload"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        404,
        500
      ],
      "summary": "Materializes Salesforce files, extracts text, persists chunks, and optionally uploads search documents.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_export_workbook",
      "method": "GET",
      "notes": "Reject ambiguous or drifted ITR-to-scope lineage.",
      "path": "/api/ops/it-requests/{request_number}/export-workbook",
      "query_params": [
        "selected_scope_key",
        "selected_scope_kind"
      ],
      "response_sections": [
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Exports the governed workbook for one ITR when exact scope lineage is valid.",
      "tests": [
        "tests/test_report_workbook.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "selected_scope_key",
        "selected_scope_kind"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_queue_run",
      "method": "POST",
      "notes": "Reject missing or ambiguous exact scope.",
      "path": "/api/ops/it-requests/{request_number}/queue-run",
      "query_params": [],
      "response_sections": [
        "status",
        "queued_requests",
        "selected_scope",
        "handoff"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Queues one exact governed savings/audit run from an ITR run plan.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_remediation_log",
      "method": "GET",
      "notes": "Keeps operator decisions visible for later triage.",
      "path": "/api/ops/it-requests/{request_number}/remediation-log",
      "query_params": [],
      "response_sections": [
        "events",
        "outcomes"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns remediation/outcome history for an ITR.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "outcome",
        "notes",
        "next_step",
        "lane"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_record_remediation",
      "method": "POST",
      "notes": "Should use proxied identity when available.",
      "path": "/api/ops/it-requests/{request_number}/remediation-log",
      "query_params": [],
      "response_sections": [
        "status",
        "event"
      ],
      "status_codes": [
        200,
        201,
        400,
        401,
        404,
        500
      ],
      "summary": "Records an operator remediation or routing outcome for an ITR.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "selected_scope_key",
        "selected_scope_kind"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_run_plan",
      "method": "POST",
      "notes": "Ambiguous or pair-level scopes must surface resolve_in_savings instead of queue-ready.",
      "path": "/api/ops/it-requests/{request_number}/run-plan",
      "query_params": [],
      "response_sections": [
        "resolution_state",
        "resolution_category",
        "candidate_scopes",
        "queue_allowed",
        "blocking_reason_codes"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Resolves capability lane, exact scope candidates, blockers, and queueability for an ITR.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_search_documents",
      "method": "GET",
      "notes": "Documents should be extracted, hashed, request-scoped evidence, not raw links.",
      "path": "/api/ops/it-requests/{request_number}/search-documents",
      "query_params": [],
      "response_sections": [
        "index_name",
        "documents",
        "counts"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns Azure AI Search / Foundry IQ-ready search documents for an ITR.",
      "tests": [
        "tests/test_salesforce_it_request_full_mirror.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "selected_scope_key",
        "selected_scope_kind"
      ],
      "cache": "none",
      "family": "itr-workbench",
      "handler": "_handle_it_request_validate_workbook",
      "method": "POST",
      "notes": "Use explicit blocked states for scope/evidence gaps.",
      "path": "/api/ops/it-requests/{request_number}/validate-workbook",
      "query_params": [],
      "response_sections": [
        "status",
        "validation_notes",
        "workbook_export"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Validates workbook readiness for an ITR-governed export.",
      "tests": [
        "tests/test_report_workbook.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "ops-observability",
      "handler": "_handle_deployment_auth",
      "method": "GET",
      "notes": "Use this to confirm Cloudflare Access identity reached the backend through the frontend proxy.",
      "path": "/api/deployment-auth",
      "query_params": [],
      "response_sections": [
        "status",
        "auth_source",
        "proxied_identity",
        "deployment_mode"
      ],
      "status_codes": [
        200,
        401
      ],
      "summary": "Reports trusted proxy and proxied identity posture for hosted rollout validation.",
      "tests": [
        "tests/test_deployment_auth.py",
        "scripts/smoke_deployment_site.py"
      ]
    },
    {
      "auth": "public",
      "body_fields": [],
      "cache": "none",
      "family": "ops-observability",
      "handler": "inline health handler",
      "method": "GET",
      "notes": "Keep this as the narrow public exception; all other internal API routes should remain protected.",
      "path": "/api/health",
      "query_params": [],
      "response_sections": [
        "status",
        "service",
        "generated_at_utc"
      ],
      "status_codes": [
        200
      ],
      "summary": "Public uptime check for the backend process.",
      "tests": [
        "tests/test_deployment_auth.py",
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "ops-observability",
      "handler": "_handle_issue_inbox_list",
      "method": "GET",
      "notes": "Uses Leaf-owned SQLite issue records with proxied identity context.",
      "path": "/api/ops/issues",
      "query_params": [
        "status",
        "limit"
      ],
      "response_sections": [
        "issues",
        "summary",
        "pagination"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Lists internal issue inbox records.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "title",
        "issue_type",
        "severity",
        "route",
        "description",
        "repro_steps",
        "metadata"
      ],
      "cache": "none",
      "family": "ops-observability",
      "handler": "_handle_issue_inbox_submit",
      "method": "POST",
      "notes": "Captures employee identity from protected headers when available.",
      "path": "/api/ops/issues",
      "query_params": [],
      "response_sections": [
        "issue",
        "status"
      ],
      "status_codes": [
        200,
        201,
        400,
        401,
        500
      ],
      "summary": "Submits an internal bug, data, access, or performance issue.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "ops-observability",
      "handler": "_handle_queue_status",
      "method": "GET",
      "notes": "Queue status should reflect the backend queue model, not inferred browser state.",
      "path": "/api/queue/status",
      "query_params": [],
      "response_sections": [
        "status",
        "queued",
        "running",
        "completed",
        "failed"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns run queue state for local/internal operations.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "ops-observability",
      "handler": "_handle_system_health",
      "method": "GET",
      "notes": "App-native health surface; not a replacement for vendor dashboards or full tracing.",
      "path": "/api/system-health",
      "query_params": [],
      "response_sections": [
        "status",
        "runtime",
        "request_windows",
        "queue",
        "cache",
        "deployment"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Protected internal runtime health and observability snapshot.",
      "tests": [
        "scripts/smoke_client_portal.py",
        "scripts/smoke_deployment_site.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "action_id",
        "mode",
        "overrides",
        "scope"
      ],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_execute_action",
      "method": "POST",
      "notes": "Keep deterministic and guardrail-evaluated.",
      "path": "/api/actions/execute",
      "query_params": [],
      "response_sections": [
        "status",
        "projected_savings",
        "guardrails",
        "trace_id"
      ],
      "status_codes": [
        200,
        400,
        401,
        409,
        500
      ],
      "summary": "Legacy optimization action execution endpoint.",
      "tests": [
        "tests/test_pocket_consultant.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_ai_runtime",
      "method": "GET",
      "notes": "Do not expose provider secrets.",
      "path": "/api/ai/runtime",
      "query_params": [],
      "response_sections": [
        "provider",
        "transport",
        "deployments",
        "fallback"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Reports AI provider runtime, transport, and fallback posture.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "question",
        "messages",
        "scope"
      ],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_chat",
      "method": "POST",
      "notes": "Legacy for Savings Audit and AI Optimization pages; use module-copilot for those modules.",
      "path": "/api/chat",
      "query_params": [],
      "response_sections": [
        "answer",
        "grounding",
        "guardrails",
        "trace_id"
      ],
      "status_codes": [
        200,
        400,
        401,
        429,
        500
      ],
      "summary": "Legacy guarded chat endpoint.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "module_key",
        "action_type",
        "mode",
        "scope",
        "parameters",
        "report_context"
      ],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_module_action_execute",
      "method": "POST",
      "notes": "Executable actions must remain deterministic and queue/lineage-backed.",
      "path": "/api/module-actions/execute",
      "query_params": [],
      "response_sections": [
        "status",
        "preview",
        "queue_request",
        "guardrails",
        "trace_id"
      ],
      "status_codes": [
        200,
        400,
        401,
        409,
        500
      ],
      "summary": "Previews or executes deterministic module actions.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "module_key",
        "question",
        "messages",
        "scope",
        "report_context"
      ],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_module_copilot",
      "method": "POST",
      "notes": "Savings and AI Optimization use module_copilot, not legacy chat, for page AI.",
      "path": "/api/module-copilot",
      "query_params": [],
      "response_sections": [
        "answer",
        "runtime",
        "grounding",
        "actions",
        "trace_id"
      ],
      "status_codes": [
        200,
        400,
        401,
        429,
        500
      ],
      "summary": "Runs the governed module assistant for savings, AI optimization, pricing, contracts, or renewals.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "scope",
        "action_id",
        "overrides",
        "report_context"
      ],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_optimization_report_pdf",
      "method": "POST",
      "notes": "Server-rendered export; not a screenshot of the browser chart state.",
      "path": "/api/optimization-report-pdf",
      "query_params": [],
      "response_sections": [
        "application/pdf"
      ],
      "status_codes": [
        200,
        400,
        401,
        409,
        500
      ],
      "summary": "Exports a print-first optimization PDF from the selected recommendation context.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "optimization-ai",
      "handler": "_handle_optimize",
      "method": "GET",
      "notes": "Must expose missing evidence and block rebate-backed claims without exact evidence.",
      "path": "/api/optimize",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date",
        "request_number"
      ],
      "response_sections": [
        "recommendations",
        "optimization_grounding",
        "ai_parity",
        "itr_handoff",
        "contract_guarantee_evidence"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Returns evidence-first optimization recommendations for the active report context.",
      "tests": [
        "tests/test_pocket_consultant.py",
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_clinical_hub_opportunities",
      "method": "GET",
      "notes": "Clinical/medical evidence must not silently upgrade rebate-backed savings posture.",
      "path": "/api/clinical-hub/opportunities",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "opportunities",
        "target_prices",
        "clinical_hub_cases"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns Medical Rx, J-code, site-of-care, and sourcing opportunities.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_contract_oversight",
      "method": "GET",
      "notes": "Do not infer final guarantee conclusions from candidate evidence.",
      "path": "/api/contracts/oversight",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "guarantee_monitor",
        "variance_summary",
        "recommended_actions"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns live contract oversight state derived from claims, audits, and guarantee monitors.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_contract_review",
      "method": "GET",
      "notes": "Contract packets are governed evidence; raw documents remain backend-side.",
      "path": "/api/contracts/review",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "contract_packet",
        "negotiation_issues",
        "guarantee_monitors"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns normalized contract packet and review posture for a scope.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_market_checks_qualitative",
      "method": "GET",
      "notes": "Qualitative evidence complements pricing comparisons.",
      "path": "/api/market-checks/qualitative",
      "query_params": [
        "rfp_project_id",
        "pbm",
        "tpa"
      ],
      "response_sections": [
        "qualitative_scorecard",
        "criteria",
        "recommendation"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns qualitative PBM scorecard and fit assessment.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "action_type",
        "scope",
        "metadata",
        "mode"
      ],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_ops_queue_action",
      "method": "POST",
      "notes": "Queue action contracts are generated from service_contracts.py.",
      "path": "/api/ops/queue-action",
      "query_params": [],
      "response_sections": [
        "status",
        "preview",
        "queue_request",
        "validation"
      ],
      "status_codes": [
        200,
        400,
        401,
        409,
        500
      ],
      "summary": "Previews or queues cross-module operational actions.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_partners_programs",
      "method": "GET",
      "notes": "Supports partner deliverable lanes without merging them into savings-only workflows.",
      "path": "/api/partners/programs",
      "query_params": [
        "partner",
        "limit"
      ],
      "response_sections": [
        "partner_programs",
        "templates",
        "active_deliverables"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns partner-channel program metadata and deliverable templates.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_pricing_coverage",
      "method": "GET",
      "notes": "Should make coverage gaps explicit.",
      "path": "/api/pricing/coverage",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "coverage_summary",
        "top_missing_pricing_keys",
        "top_gap_slices",
        "artifact_coverage"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns pricing coverage gaps and missing pricing-key concentrations.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_pricing_registry",
      "method": "GET",
      "notes": "Pricing registry can support contract-aware outputs but does not replace exact contract packets.",
      "path": "/api/pricing/registry",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "pricing_term_sets",
        "pricing_assignments",
        "coverage_summary",
        "effective_dates",
        "entity_links"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns pricing term sets and assignments for a scope.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_rebates_manufacturers",
      "method": "GET",
      "notes": "Exact rebate evidence is required before rebate-backed savings claims.",
      "path": "/api/rebates/manufacturers",
      "query_params": [
        "program_name",
        "limit"
      ],
      "response_sections": [
        "manufacturer_programs",
        "program_rules",
        "reporting",
        "exception_summary"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns manufacturer-linked program context for rebate and Medical Rx workflows.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "product-ops",
      "handler": "_handle_renewals_status",
      "method": "GET",
      "notes": "Keep renewal readiness distinct from savings report readiness.",
      "path": "/api/renewals/status",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "renewal_event",
        "deliverables",
        "partner_programs"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns renewal windows, due dates, and deliverable readiness.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "runtime cache optional",
      "family": "report-deliverables",
      "handler": "_handle_client_report",
      "method": "GET",
      "notes": "Browser pages must treat returned client_context as authoritative over requested query values.",
      "path": "/api/client-report",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date",
        "request_id",
        "top_n"
      ],
      "response_sections": [
        "client_context",
        "executive_summary",
        "channel_segmentation",
        "top_drugs",
        "specialty_high_cost",
        "groups",
        "deliverables"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns the interactive savings/audit report payload for a resolved scope.",
      "tests": [
        "scripts/smoke_client_portal.py",
        "tests/test_report_workbook.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "internal narrative cache",
      "family": "report-deliverables",
      "handler": "_handle_report_narrative",
      "method": "GET",
      "notes": "Azure OpenAI can draft text, but metrics remain deterministic report payload values.",
      "path": "/api/client-report-narrative",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "narrative",
        "runtime",
        "grounding",
        "fallback"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns or drafts an executive narrative for the active report context.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "report-deliverables",
      "handler": "_handle_report_pdf",
      "method": "GET",
      "notes": "Export must stay consistent with the same run context used by the UI payload.",
      "path": "/api/client-report-pdf",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ],
      "response_sections": [
        "application/pdf"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Exports the current savings/audit report as a PDF artifact.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "none",
      "family": "report-deliverables",
      "handler": "_handle_report_workbook",
      "method": "GET",
      "notes": "Final workbook path; ITR-governed exports should reject missing or drifted exact-scope lineage.",
      "path": "/api/client-report-xlsx",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date",
        "request_number"
      ],
      "response_sections": [
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      ],
      "status_codes": [
        200,
        400,
        401,
        404,
        409,
        500
      ],
      "summary": "Exports the governed audit workbook for the current resolved report scope.",
      "tests": [
        "tests/test_report_workbook.py",
        "tests/test_serve_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "runtime cache optional",
      "family": "report-deliverables",
      "handler": "_handle_client_report_context",
      "method": "GET",
      "notes": "Primary backend authority for savings-page lineage and AI handoff posture.",
      "path": "/api/client-report/context",
      "query_params": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date",
        "request_number",
        "refresh"
      ],
      "response_sections": [
        "client_context",
        "workbook_export",
        "run_lineage",
        "ai_handoff",
        "itr_handoff",
        "contract_guarantee_evidence",
        "domo_takeover"
      ],
      "status_codes": [
        200,
        401,
        404,
        500
      ],
      "summary": "Returns authoritative report context, workbook posture, run lineage, AI handoff, and evidence status.",
      "tests": [
        "scripts/smoke_client_portal.py",
        "tests/test_report_workbook.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date",
        "source_request_number",
        "selected_scope_key",
        "selected_scope_kind"
      ],
      "cache": "none",
      "family": "report-deliverables",
      "handler": "_handle_client_report_queue",
      "method": "POST",
      "notes": "Operator-facing only; do not blindly fan out ambiguous ITR scopes.",
      "path": "/api/client-report/queue",
      "query_params": [],
      "response_sections": [
        "status",
        "queued_requests",
        "loaded_scope",
        "itr_handoff"
      ],
      "status_codes": [
        200,
        202,
        400,
        401,
        409,
        500
      ],
      "summary": "Queues or refreshes a governed savings/audit run for the selected scope.",
      "tests": [
        "tests/test_serve_client_portal.py"
      ]
    },
    {
      "auth": "trusted frontend proxy",
      "body_fields": [],
      "cache": "runtime cache optional",
      "family": "report-deliverables",
      "handler": "_handle_filter_options",
      "method": "GET",
      "notes": "Keep completed report scopes distinct from broader capability-ready scopes.",
      "path": "/api/filter-options",
      "query_params": [],
      "response_sections": [
        "pbms",
        "tpas",
        "groups",
        "date_windows",
        "scope_registry"
      ],
      "status_codes": [
        200,
        401,
        500
      ],
      "summary": "Returns governed filter/scope options for UI controls.",
      "tests": [
        "scripts/smoke_client_portal.py"
      ]
    }
  ],
  "families": {
    "agent-workbench": {
      "owner": "Agent runtime backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/agents/"
      ],
      "summary": "Internal agent task ledger, traces, artifacts, policy approvals, SDK execution, and Service Bus dispatch.",
      "title": "Agent Workbench"
    },
    "contract-intelligence": {
      "owner": "Contract intelligence backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/contract_intelligence/"
      ],
      "summary": "Contract intelligence queue, schedule, registry summary, and materialization APIs.",
      "title": "Contract Intelligence Admin"
    },
    "itr-workbench": {
      "owner": "Salesforce ITR backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/salesforce_it_requests/"
      ],
      "summary": "Salesforce ITR list, detail, run-plan, queue, evidence, materialization, workbook validation, and remediation routes.",
      "title": "Salesforce ITR Workbench"
    },
    "ops-observability": {
      "owner": "Platform operations backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/system_health.py",
        "LeafEnterprise/issue_inbox.py"
      ],
      "summary": "Health, deployment-auth, system-health, queue status, and internal issue intake APIs.",
      "title": "Operations And Observability"
    },
    "optimization-ai": {
      "owner": "AI optimization backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/module_copilot.py",
        "LeafEnterprise/pocket_consultant.py",
        "LeafEnterprise/ai/"
      ],
      "summary": "Evidence-first optimization payloads, deterministic action previews, legacy chat, and module copilot surfaces.",
      "title": "Optimization And AI"
    },
    "product-ops": {
      "owner": "Cross-module operations backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/ops_portal.py",
        "LeafEnterprise/service_contracts.py"
      ],
      "summary": "Pricing, contract, renewal, partner, market-check, clinical, rebate, and generic queue-action APIs.",
      "title": "Product Operations"
    },
    "report-deliverables": {
      "owner": "Savings/Audit backend",
      "source_modules": [
        "scripts/serve_client_portal.py",
        "LeafEnterprise/client_preview.py",
        "LeafEnterprise/report_workbook.py",
        "LeafEnterprise/pocket_consultant.py"
      ],
      "summary": "Governed savings/audit report payloads, lineage, queue refresh, PDF export, workbook export, and narrative outputs.",
      "title": "Report And Deliverables"
    }
  },
  "intended_consumers": [
    "humans",
    "enterprise_agents",
    "mcp_service_generators",
    "retrieval_indexes"
  ],
  "queue_actions": [
    {
      "action_type": "contract_review",
      "description": "Extract or refresh normalized contract packets for the selected scope.",
      "optional_metadata_fields": [
        "contract_packet_id",
        "pricing_term_set_id",
        "renewal_event_id"
      ],
      "product_module": "contract_oversight",
      "required_metadata_fields": [
        "product_module",
        "source_artifact_ids"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "contract_oversight_refresh",
      "description": "Measure live claims and audit outputs against contracted guarantees and fee terms.",
      "optional_metadata_fields": [
        "guarantee_monitor_id",
        "renewal_event_id"
      ],
      "product_module": "contract_oversight",
      "required_metadata_fields": [
        "product_module",
        "contract_packet_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "pricing_refresh",
      "description": "Ingest or refresh pricing and rosetta mappings from curated workbook sources.",
      "optional_metadata_fields": [
        "pricing_term_set_id",
        "entity_crosswalk_id"
      ],
      "product_module": "pricing_registry",
      "required_metadata_fields": [
        "product_module",
        "source_artifact_ids"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "market_check",
      "description": "Build incumbent-versus-alternative PBM market-check output for the selected scope.",
      "optional_metadata_fields": [
        "contract_packet_id",
        "rfp_project_id",
        "qualitative_scorecard_id"
      ],
      "product_module": "market_checks",
      "required_metadata_fields": [
        "product_module",
        "pricing_term_set_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "qualitative_scorecard_refresh",
      "description": "Refresh structured qualitative PBM scorecards used alongside pricing comparisons.",
      "optional_metadata_fields": [
        "response_packet_ids",
        "qualitative_scorecard_id"
      ],
      "product_module": "market_checks",
      "required_metadata_fields": [
        "product_module",
        "rfp_project_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "renewal_checkup",
      "description": "Run a renewal-timed PBM checkup workflow and stage repricing deliverables.",
      "optional_metadata_fields": [
        "partner_program_id",
        "deliverable_commitment_id"
      ],
      "product_module": "delivery_ops",
      "required_metadata_fields": [
        "product_module",
        "renewal_event_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "partner_deliverable_generation",
      "description": "Generate co-branded or partner-program deliverables for broker, captive, or underwriting channels.",
      "optional_metadata_fields": [
        "partner_program_id",
        "renewal_event_id",
        "queue_request_parent_id"
      ],
      "product_module": "delivery_ops",
      "required_metadata_fields": [
        "product_module",
        "deliverable_template_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "medical_rebate_validation",
      "description": "Validate medical rebate or HCPCS layout readiness before submission.",
      "optional_metadata_fields": [
        "manufacturer_program_id",
        "file_layout_id"
      ],
      "product_module": "rebates_hcpcs",
      "required_metadata_fields": [
        "product_module",
        "submission_job_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "medical_rebate_submission",
      "description": "Execute the quarter-bound medical rebate submission workflow.",
      "optional_metadata_fields": [
        "manufacturer_program_id",
        "reconciliation_id"
      ],
      "product_module": "rebates_hcpcs",
      "required_metadata_fields": [
        "product_module",
        "submission_job_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "medical_rebate_reconciliation",
      "description": "Compare expected manufacturer or program rebate outcomes against paid outcomes.",
      "optional_metadata_fields": [
        "manufacturer_program_id",
        "payment_reconciliation_id",
        "quarter_label",
        "reporting_period_start",
        "reporting_period_end",
        "latest_deadline_date",
        "program_type"
      ],
      "product_module": "rebates_hcpcs",
      "required_metadata_fields": [
        "product_module",
        "submission_job_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "manufacturer_rebate_reconciliation",
      "description": "Compare expected manufacturer or program rebate outcomes against paid outcomes using a packet-backed manufacturer program context.",
      "optional_metadata_fields": [
        "packet_id",
        "quarter_label",
        "reporting_period_start",
        "reporting_period_end",
        "latest_deadline_date",
        "program_type",
        "cycle_count"
      ],
      "product_module": "rebates_hcpcs",
      "required_metadata_fields": [
        "product_module",
        "submission_job_id",
        "manufacturer_program_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "clinical_hub_review",
      "description": "Run a medical-Rx or Clinical Hub review for specialty, J-code, or site-of-care opportunities.",
      "optional_metadata_fields": [
        "clinical_hub_case_id",
        "provider_packet_id"
      ],
      "product_module": "medical_rx_clinical_hub",
      "required_metadata_fields": [
        "product_module",
        "opportunity_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "site_of_care_analysis",
      "description": "Evaluate site-of-care or infusion routing opportunities for medical-benefit claims.",
      "optional_metadata_fields": [
        "provider_packet_id",
        "manufacturer_program_id"
      ],
      "product_module": "medical_rx_clinical_hub",
      "required_metadata_fields": [
        "product_module",
        "opportunity_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "sourcing_quote",
      "description": "Generate quote packets for specialty or J-code sourcing opportunities.",
      "optional_metadata_fields": [
        "target_price_id",
        "partner_vendor_ids"
      ],
      "product_module": "medical_rx_clinical_hub",
      "required_metadata_fields": [
        "product_module",
        "opportunity_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    },
    {
      "action_type": "sourcing_followup",
      "description": "Continue sourcing coordination, white-bagging checks, or partner follow-up.",
      "optional_metadata_fields": [
        "case_owner",
        "quote_packet_id"
      ],
      "product_module": "medical_rx_clinical_hub",
      "required_metadata_fields": [
        "product_module",
        "opportunity_id"
      ],
      "required_scope_fields": [
        "pbm",
        "tpa",
        "group_name",
        "start_date",
        "end_date"
      ]
    }
  ],
  "schema_version": "2026-05-14.leafenterprise.api-reference.v1",
  "source_of_truth": true
}
