Appearance
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)
| Property | Value |
|---|---|
| Default | OFF — an admin must explicitly enable egress (app_settings key media.egress_enabled) |
| Scope | LIGHT / in-boundary — Cloudflare Workers-AI only; no third-party egress |
| What may egress | Referenced image media bytes (the same assets the visual-analysis pass loads, #1113) |
| To which model | An 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 |
| Audit | Every 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:
- The admin toggle is ON —
media.egress_enabledinapp_settings, surfaced on /admin/privacy ("Media egress to vision model", default OFF). It mirrors the buyer-geolocation toggle (#698) exactly. - A real vision analyzer is wired — the analyzer is chosen through the pure, fail-closed
selectMediaAnalyzergate (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.
Alignment with consent & retention (#346/#347)
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.comsubdomain 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_tagsproposals (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)
- Build/enable the real vision analyzer (#1188) and wire it as the
realanalyzer in the library's pass caller (src/routes/admin/media/+page.server.ts,runPass— #1370). - On /admin/privacy, turn Media egress to vision model ON.
- Run the visual-analysis pass. Egress runs appear in the audit trail; the pass-run summary states
egress → <model>vsstub, no egress. - To stop egress at any time, turn the toggle OFF — the pass immediately reverts to the stub with no image leaving the boundary.