Sub-processors

Last updated [[EFFECTIVE_DATE]]

A sub-processor is any third party that may access customer data while we deliver the service. We give 30 days' notice before adding one, so you can object.

Current — production (P0 containment)

Sub-processorPurposeData accessedLocation
Microsoft Corporation (Azure)Hosting, compute, storage, identity, telemetryAll customer dataUnited States — Azure West US 2

P0 status (effective immediately): Production runs deterministic-only for Wanda (QBR Copilot / audit insights). No customer data is sent to any external AI model provider in any deployed environment (WEBSITE_SITE_NAME set). The code gate is shared/agent.py:_llm_allowed() which returns False when deployed, regardless of AGENT_PROVIDER or whether a key is present. Credentials for NVIDIA / Azure OpenAI, if retained, are held in Azure Key Vault only and are not wired to the Function App in production (infra/09-harden.sh unwires them).

Wanda's deterministic path (shared/agent.py:_fallback_narrate, shared/audit_insights.py:_fallback_narrate_audit) uses only data already in storage and is grounding-checked (is_grounded) the same way.

What an external model would receive (when enabled)

shared/agent.py:build_context() (QBR Copilot) and shared/audit_insights.py:build_audit_context() (Instant Audit) assemble only aggregates — never raw directory objects. If an external provider were enabled, the following would be sent as the model context:

This is customer data under the DPA (financial aggregates + tenant identifiers). It is sent only when an external LLM is intentionally enabled.

Conditional / future sub-processors — NOT active in production

Sub-processorPurposeData that would be accessedLocationStatus
NVIDIA Corporation (NVIDIA Integrate API, https://integrate.api.nvidia.com)QBR Copilot narration (meta/muse-glimmer-30b) when AGENT_PROVIDER=nvidia and key presentAggregates listed aboveUnited States — NVIDIA hosted inferenceDisabled in production (P0). Would require re-enablement checklist below.
Microsoft Corporation (Azure OpenAI)Alternative QBR Copilot narration (openai/deployments/{AZURE_OPENAI_DEPLOYMENT}/chat/completions)Same aggregatesUnited States — Azure West US 2 (same boundary as hosting)Disabled in production (P0). Covered by Microsoft DPA when enabled, but still requires checklist.
Local Ollama (OLLAMA_HOST)Dev-only local model (qwen3:8b)Same aggregatesDeveloper machine / private networkNever in production. Dev only.

Until the re-enablement checklist is satisfied, these rows are disclosed but not authorized for customer-data access in production.

Re-enablement checklist — required before any external model may receive customer data

External LLM re-enablement is not part of the P0 launch. Each item must be completed and documented:

  1. Approved subprocessor disclosure and notice — update this file and legal/DPA.md:Annex III, publish 30 days' notice, provide objection mechanism.
  2. Contractual retention / no-training terms — signed terms with the provider stating customer data is not retained beyond processing, not used to train models, and deleted within provider's documented window (commit to specific days and cite provider docs).
  3. Region and data-flow review — confirm processing region(s), data residency, and that the flow stays within the disclosed transfer mechanism (SCCs / DPA). Document in COMPLIANCE.md / DPA Annex I.
  4. Tenant-level opt-in — explicit per-tenant / per-org consent stored and enforced in shared/agent.py / routes/agent.py before any call; default remains deterministic.
  5. Provider-specific labeling — UI and API must report the actual provider. Backend returns provider: nvidia|azure|ollama|deterministic (shared/agent.py:chat, routes/agent.py), frontend renders via NVIDIA / via Azure OpenAI / via Ollama vs grounded in … (dashboard/dashboard.html:wireCopilot).
  6. Prompt / output redaction and audit controls — strip or hash any tenant identifiers not needed for narration, log provider, model, prompt hash, output hash, and grounding result to immutable audit trail; sample and review.

No code change that would make _llm_allowed() return True in a deployed environment may ship until this checklist is signed.

Deliberately not used

Listed because "which third parties see our data" is the real question behind the one above, and the absence of these is more informative than the presence of Microsoft.

CategoryStatus
Analytics (Google Analytics, Segment, Mixpanel)None. The site sets no analytics cookies and does not track visitors.
Error tracking (Sentry, Rollbar)None. Diagnostics stay in Azure Application Insights.
Support desk (Intercom, Zendesk, Front)None. Support is email only.
Email marketing (Mailchimp, SendGrid)None.
CDN outside Azure (Cloudflare, Fastly)None. Azure Static Web Apps only.
AI or LLM services (production)None in production (P0). Deterministic only; see conditional table above for future.

The one third-party request the site makes is to Google Fonts for typefaces. That transmits the visitor's IP address to Google as part of an ordinary HTTP request. It carries no customer data and applies to the marketing site only — but it is a third-party request, so it is disclosed rather than omitted.

Infrastructure without customer data access

These support development but never receive customer data.

ServicePurpose
GitHubSource control and deployment automation. Contains no customer data.
PyPI, npmDependency distribution during build.

Changes

Material changes are notified to account holders by email at least 30 days before taking effect. Contact kyler@ebbwater.net to object.