# title
Vendor / Data-Processor Registry (vendors.toml)

# description
Tier-0 contract for every external destination Billy dials. One source, six projections — same shape as the network DSL.

Projections:
  • services/backend/shared/netcfg/vendors_gen.go    — Go runtime (LookupVendor, MODEL_COSTS, ModelCost)
  • services/ai/core/foundation/io/net/_vendors_gen.py             — Python runtime (lookup_vendor, MODEL_COSTS, model_cost)
  • services/backend/api/internal/handler/connect/admin/compliancerpc/vendors.gen.json — admin embed JSON
  • infra/network/vendors.json                       — manifest for the network DSL validators
  • policy/cedar/schema.cedarschema (Billy::Vendor)  — entity attribute mirror (cross-checked by check_vendors_cedar_parity)
  • core.llm.costs.MODEL_COSTS                       — derived alias-expanded lookup table

Cross-checks:
  • infra/network/checks/vendors.py — vendors.toml ↔ perimeter.firewall coverage + BAA inventory
  • scripts/codegen/forward/trust/vendors/lint.py — every Cedar Vendor attribute is producible from every vendor row
  • scripts/codegen/forward/trust/vendors/compile.py --check — byte-parity drift gate against committed projections

Cost catalogue: each LLM-class vendor MAY declare a `cost` table mapping model id → cents-per-million-tokens rates. The vendor-cost-poll Forgejo workflow (.forgejo/workflows/vendor-costs.yml) refreshes these rates from `pricing_url` and opens a PR when drift is detected.

# x-taplo.docs.main
**Vendor / Data-Processor Registry** — Tier-0 contract for every external destination Billy dials. One TOML, six projections (Go, Python, Cedar entity, BAA inventory, cost table, admin embed). Pairs with [`infra/network/perimeter.firewall`](../../../infra/network/perimeter.firewall) — the firewall says *which hosts*, this says *what data may flow there, under what contract, at what cost*. See [`README`](./README.md) and [`supply-chain-trust-plane.mdc`](../../../.cursor/rules/supply-chain-trust-plane.mdc).

# $defs.vendor.properties.host.description
Egress hostname (or wildcard) exactly as it appears in infra/network/perimeter.firewall.

# $defs.vendor.properties.name.description
Human-readable vendor name (e.g. Anthropic, Google Cloud).

# $defs.vendor.properties.class.description
Coarse functional category. Drives admin grouping + risk reasoning. `vox` is the unified self-hosted speech I/O sidecar (STT+TTS+voice cloning, ADR-146). `billing` covers wallet / payment-processor egress (Stripe customers + SetupIntents + PaymentIntents + webhook RPC).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Large language model — chat / completion endpoints (Anthropic, OpenAI, Google).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Speech-to-text — vendor-side ASR (used only for legacy fallbacks; primary STT is in-pod Vox).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Text-to-speech — vendor-side TTS (legacy fallback; primary TTS is in-pod Vox).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Self-hosted Vox VM — STT+TTS+voice cloning unified sidecar (ADR-146).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Transport — gateway / CDN / object storage / messaging plane (GCS, Cloud Storage).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Search — web/grounding search providers (Tavily, Brave, Exa).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Knowledge — structured knowledge or geo databases (Wikidata, Wikipedia API).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Geocoding — forward / reverse geocoding (Google, Mapbox).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Comms — email / SMS / push (SendGrid, Twilio, FCM).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Observability — log / metric / trace sinks (Datadog, Sentry, Honeycomb).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Infra — non-LLM cloud control plane (GCP APIs, Firebase admin).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
VCS — version-control APIs (GitHub, Forgejo, GitLab).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
Billing — payment processor egress (Stripe customers, payment intents, webhook delivery).

# $defs.vendor.properties.class.x-taplo.docs.enumValues[]
MCP — Model Context Protocol server endpoints (per-tool registrations).

# $defs.vendor.properties.purpose.description
Free-text purpose limitation echoing the contractual scope (DPA-style).

# $defs.vendor.properties.data_classes.description
Categories of data we actually transmit to this destination.

# $defs.vendor.properties.phi_allowed.description
Operator policy: may PHI-classified payloads transit this vendor? Defaults to false; flipping to true requires baa.status = signed AND vendor capability.

# $defs.vendor.properties.pii_allowed.description
Operator policy: may PII-classified payloads transit this vendor?

# $defs.vendor.properties.byok_only.description
If true, this vendor may only be dialed when a BYOK key is bound on the request — the user owns the upstream relationship.

# $defs.vendor.properties.baa.properties.status.description
signed: operator has executed BAA; unverified: vendor offers BAA on appropriate plan but operator has not recorded execution; none: no BAA needed (low-sensitivity / public read / BYOK passthrough); ineligible: vendor does not offer a BAA.

# $defs.vendor.properties.baa.properties.status.x-taplo.docs.enumValues[]
Operator has executed the BAA — `phi_allowed = true` is permitted.

# $defs.vendor.properties.baa.properties.status.x-taplo.docs.enumValues[]
Vendor offers a BAA on the appropriate plan but operator has not recorded execution — `phi_allowed` must remain false until upgraded.

# $defs.vendor.properties.baa.properties.status.x-taplo.docs.enumValues[]
No BAA needed for this vendor — low-sensitivity / public read / BYOK passthrough.

# $defs.vendor.properties.baa.properties.status.x-taplo.docs.enumValues[]
Vendor does not offer a BAA at all — `phi_allowed` must be false.

# $defs.vendor.properties.baa.properties.eligible.description
Vendor capability: does this vendor offer a BAA at all (on any plan)?

# $defs.vendor.properties.baa.properties.scope.description
Optional contract scope label (e.g. 'anthropic-api', 'gcp-workspace').

# $defs.vendor.properties.baa.properties.executed.description
Optional ISO-8601 (YYYY-MM-DD) execution date.

# $defs.vendor.properties.baa.properties.expires.description
Optional ISO-8601 (YYYY-MM-DD) expiry date. Empty string means no expiry / unknown.

# $defs.vendor.properties.baa.properties.contact.description
Optional vendor legal contact (email / inbox).

# $defs.vendor.properties.baa.properties.uri.description
Optional vault://path/to/contract.pdf reference. Never store contract bytes in this registry.

# $defs.vendor.properties.zero_retention.description
Vendor offers a zero-retention rider that is in effect for our usage.

# $defs.vendor.properties.training_opt_out.description
Vendor will not train on our payloads (default-on for API tier or contractually enforced).

# $defs.vendor.properties.data_regions.description
Region codes (e.g. 'us', 'eu') where the vendor processes our data.

# $defs.vendor.properties.subprocessor_list_url.description
Vendor's published subprocessor list URL — operator must monitor for changes.

# $defs.vendor.properties.pricing_url.description
Public pricing page consumed by the vendor-cost-poll workflow. Required when `cost` is non-empty so the polling job knows where to refresh from.

# $defs.vendor.properties.cost.description
Per-model rate table keyed by canonical model id (e.g. `claude-sonnet-4-6`). Cents per million tokens. Source of truth for core.llm.costs.MODEL_COSTS — refreshed by the vendor-cost-poll workflow.

# $defs.modelCost.properties.cache_read.description
Cents per million cached-prompt-read tokens (Anthropic / Gemini cache hit rate).

# $defs.modelCost.properties.cache_write.description
Cents per million cache-write tokens (cache priming).

# $defs.modelCost.properties.aliases.description
Alternate model slugs (provider-prefixed forms, OpenRouter routes) that resolve to these rates. The codegen expands MODEL_COSTS to include each alias as a top-level key.

# $defs.modelCost.properties.observed_at.description
ISO-8601 (YYYY-MM-DD) date the rates were last verified against the vendor's public pricing page. Updated by the vendor-cost-poll workflow.