# Backend Managed Enrichment Routing V01

Issue: #431

Parent: #428

## Purpose

This artifact defines deterministic backend-managed enrichment routing by assistant mode, selected profile, and repo-controlled operator configuration. The normal proof request sends mode and profile intent. The backend resolves eligible enrichment sources for the run.

This is field guidance and implementation evidence, not policy, not package authority, and not source-set approval.

## Routing Artifact

The machine-readable routing policy is `docs/product-architecture/backend_managed_enrichment_routing_v01.json`.

The routing policy references the static enrichment-source registry at `docs/product-architecture/enrichment_source_registry_v01.json`. It does not mutate that registry, promote enrichment sources to package authority, or create source discovery.

## Why Routing Moves Backend Managed

The previous run-scoped model allowed `selected_source_ids` in the client request. That remains useful for advanced diagnostics, but it should not be the normal source of truth for enrichment. Normal users should choose mode, question, source scope, and profile. The backend should resolve eligible sources from controlled routing rules and the server-side allowlisted source registry.

Backend-managed routing keeps these decisions auditable:

- which mode was requested
- which profile was selected
- which source packs were eligible
- which server allowlisted sources matched the routing policy
- which sources were excluded and why
- whether retrieval was unavailable, retrieved, or failed closed

## Supported Modes

| Mode | Routing behavior |
|---|---|
| `Answer` | Package evidence first. If `package_plus_enrichment` is explicit, backend may add profile-eligible enrichment. |
| `Explain` | Package evidence first. If `package_plus_enrichment` is explicit, backend may add profile-eligible enrichment. |
| `Assess` | Package evidence first. Missing proposal evidence refusal happens before enrichment retrieval. If not refused and `package_plus_enrichment` is explicit, backend may add profile-eligible enrichment. |
| `Find evidence` | Package evidence first. Enrichment is allowed only when `package_plus_enrichment` is explicit and profile-eligible. |

## Supported Profiles

| Profile | Eligible source packs |
|---|---|
| `general_ai_capability` | `core_ai_capability` |
| `ai_security` | `core_ai_capability`, `ai_security` |
| `ai_governance` | `core_ai_capability`, `ai_governance` |
| `gxp_regulated_life_sciences` | `core_ai_capability`, `gxp_regulated_life_sciences` |
| `medical_device_samd` | `core_ai_capability`, `medical_device_samd` |
| `ot_endpoint_infrastructure` | `core_ai_capability`, `ot_endpoint_infrastructure` |
| `foundation_model_providers` | `core_ai_capability`, `foundation_model_providers` |
| `agent_rag_engineering` | `core_ai_capability`, `agent_rag_engineering` |
| `independent_evidence` | `core_ai_capability`, `independent_evidence` |
| `vendor_product_docs` | `core_ai_capability`, `vendor_product_docs` |

The default profile is `general_ai_capability`. The default source scope remains `package_only`. Package plus enrichment must be explicit or controlled by a repo/operator default.

## Source Eligibility Rules

Backend routing may select a source only when all of these are true:

- The source resolves to `docs/product-architecture/enrichment_source_registry_v01.json`.
- The source pack is eligible for the selected profile and mode.
- The source status is `active_default`, `active_available`, or `profile_default`.
- The source license mode is `public`, `metadata_only`, or `rights_cleared_controlled_excerpt`.
- `browser_fetch_allowed` is `false`.
- `provider_call_allowed` is `false`.
- `package_authority` is `false`.
- `registry_mutable_by_user` is `false`.
- The retrieval mode is compatible with the existing server-side allowlisted retrieval adapter.
- Package authority is not mutated.

## Exclusion Rules

Backend routing excludes sources with these statuses:

- `preview_only`
- `unavailable`
- `deprecated`
- `retired`
- `admin_gated`

Backend routing excludes `licensed_excerpt_required` content unless a later owner-approved rights-cleared implementation exists.

Client-selected source IDs cannot override eligibility. Advanced/operator override IDs are diagnostic run input only and must still pass server validation.

Vendor/provider source packs are not global defaults. `foundation_model_providers` and `vendor_product_docs` may be used only by profile, product trigger, or explicit controlled configuration.

## Runtime Alias Boundary

The server-side current-source registry uses current-source candidate IDs. The static enrichment registry uses governed enrichment source IDs. Backend routing bridges those identities through explicit aliases, for example:

- `nist-ai-rmf-public-framework-candidate` maps to `nist-ai-rmf-1-0`
- `nist-ssdf-sp-800-218-candidate` maps to `nist-sp-800-218-ssdf`
- `owasp-genai-llm-top-10-2025-candidate` maps to `owasp-genai-llm-top-10-2025`
- `cisa-nsa-ncsc-secure-ai-system-development-guidelines-candidate` maps to `cisa-nsa-ncsc-secure-ai-system-development`

The alias bridge does not add sources, broaden origins, change Cloudflare configuration, or mutate the registry.

## Telemetry Contract

Compact UI telemetry should show:

- source scope
- selected profile
- routing mode
- routing result

Routing result values are:

- `package-only`
- `resolved eligible sources`
- `no eligible sources`
- `retrieval unavailable`
- `retrieved`
- `failed closed`

Advanced/operator/debug telemetry should show:

- resolved mode
- selected profile
- eligible source packs
- eligible source IDs
- excluded source IDs with reason where practical
- routing policy artifact path
- server registry configured or unconfigured
- retrieval adapter
- retrieval status
- used enrichment source IDs
- eligible-but-unused source IDs
- package authority unchanged

Telemetry is run-scoped. It is not durable memory.

## Refusal And Degrade Behavior

If package support is missing, the server refuses before enrichment routing.

If deterministic refusal applies, including approval-boundary refusal or missing Assess proposal evidence refusal, the server does not retrieve enrichment.

If the server-side current registry is unconfigured, existing fail-closed behavior is retained.

If routing config exists but no eligible sources exist, the server returns no enrichment refs and reports `backend enrichment routing resolved no eligible sources`.

If retrieval fails after eligible routing, the server returns no enrichment refs and reports failed-closed telemetry.

## Operator Override Boundary

Advanced/operator source controls may show manual source selection and override diagnostics. Those IDs are not normal routing authority. The server validates any override IDs against backend routing, source eligibility, and the allowlisted runtime registry before retrieval.

## Explicit Non-Goals

This artifact and implementation do not add:

- arbitrary web search
- source discovery
- external crawling
- browser-side external source fetching
- browser-side provider calls
- user-entered URL fetching
- source registry mutation
- package authority mutation
- durable memory
- vector DB, graph DB, Supabase, hosted retrieval, crawler, worker, webhook, queue, or polling
- Cloudflare configuration changes
- provider or model configuration changes
- #432 answer-evidence proof work

## Boundary Confirmations

- #78 is not mutated.
- #271 is not reopened or mutated.
- #428 is not closed.
- #432 is not started.
- The enrichment source registry is not mutated.
- Package authority is not mutated.
- No `codex-automerge` label is applied.
