Skip to content

Media Egress Governance & Posture

The governance layer for sending media bytes to a vision model (issue #1190, part of capability #1185). Decision #1123 shipped visual analysis with explicitly no media egress; sending image bytes to a model is egress of user / brand content, so #1190 establishes the posture, the admin control, and the audit trail that must be in place before any real vision model (#1188) is enabled. It sits alongside the behavioral-data governance in Privacy, Consent & Retention and the model bindings in RAG Intelligence Bindings.

The one-line version: media egress is OFF by default, requires an explicit admin opt-in, runs only against an in-boundary model, and every egress run is recorded in the audit trail — with OFF the pipeline runs the deterministic stub and no image ever leaves the boundary.

Posture (decision #1195)

PropertyValue
DefaultOFF — an admin must explicitly enable egress (app_settings key media.egress_enabled)
ScopeLIGHT / in-boundary — Cloudflare Workers-AI only; no third-party egress
What may egressReferenced image media bytes (the same assets the visual-analysis pass loads, #1113)
To which modelAn in-boundary @cf/… vision model (#1188); the model id is recorded on every egress event
Fallback (OFF)The deterministic stub analyzer (#1123) — lexical, no network, no image leaves
AuditEvery real-egress run recorded (media-egress entity: asset count, model, purpose, time)

Even though Workers-AI is in-boundary (inference runs on Cloudflare's platform, not a third party — see RAG Intelligence Bindings § Secrets), the gate still applies: egress of brand/user imagery to any model is governed, defaulting off until an operator opts in.

The gate

Two things must both hold before an image is sent to a model:

  1. The admin toggle is ONmedia.egress_enabled in app_settings, surfaced on /admin/privacy ("Media egress to vision model", default OFF). It mirrors the buyer-geolocation toggle (#698) exactly.
  2. A real vision analyzer is wired — the analyzer is chosen through the pure, fail-closed selectMediaAnalyzer gate (src/lib/server/media-egress.ts), which returns the real analyzer only when the toggle is ON and a real analyzer exists; otherwise it returns the stub. The real analyzer is #1188 (not built yet), so today the gate always resolves to the stub — the fallback path is provably intact.

An unset flag, a missing real analyzer, or an unreadable setting can never leak an image — the gate fails closed to the stub.

Media egress is governed under the same consent & retention topology as behavioral data, adapted for content rather than PII:

  • Consent tier. Referenced media are brand/product content, not identifiable personal data — they do not carry a Tier-2 (marketing) identifiable subject. The egress decision is therefore an operator governance control (the admin toggle), not a per-visitor consent gate. This is the deliberate distinction from buyer geolocation (#698), which is Tier-1 (measurement) consent-gated because it derives from a visitor.
  • Deployment precondition. Egress does not depend on the .nanawall.com subdomain topology that the Iubenda cookie requires (§ Deployment precondition) — it is server-side and operator-controlled, so it works on any origin. It remains OFF by default regardless.
  • Retention of model-side artifacts. The in-boundary Workers-AI vision model returns tag proposals + (separately) embeddings; it retains no copy of the submitted image. What persists in NanaSelect is derived signal only — media_visual_tags proposals (human-reviewed, #1113) and the audit trail — governed by the existing admin data paths, not by the session retention windows (which cover visitor behavioral data, a different data class). No raw egressed image is stored beyond the pass.

Audit trail

Every real-egress run is recorded via recordMediaEgress as a media-egress audit entity (src/lib/server/media-egress.ts, on the shared admin audit trail), capturing:

  • asset count — how many assets egressed in the run,
  • model — the model id bytes were sent to,
  • purpose — e.g. visual-analysis-pass,
  • timestamp — the audit createdAt.

The admin toggle flip itself is also audited (media-egress / update). The trail is filterable by the media-egress entity kind on the admin audit screen, so an operator can review exactly what was sent to which model and when.

Enabling egress (operator runbook)

  1. Build/enable the real vision analyzer (#1188) and wire it as the real analyzer in the library's pass caller (src/routes/admin/media/+page.server.ts, runPass — #1370).
  2. On /admin/privacy, turn Media egress to vision model ON.
  3. Run the visual-analysis pass. Egress runs appear in the audit trail; the pass-run summary states egress → <model> vs stub, no egress.
  4. To stop egress at any time, turn the toggle OFF — the pass immediately reverts to the stub with no image leaving the boundary.