Skip to content

SOP-PROOF-01: Proof Portal System v1.2

Public-facing verification portal for batch safety testing results

Document ID: SOP-PROOF-01-v1.2 Version: 1.2 Status: ✅ Production Ready Last Updated: 2026-04-16 Owner: Protocol Raw Operations Replaces: SOP-PROOF-01-v1.1 Review Date: 2026-07-16


Key Changes in v1.2

  • Batch page restructured from campaign-page to certificate-style document. Hero replaced by Verdict section; Results replaced by Evidence section.
  • Verdict section: seal + "All clear." + metadata line + result chips + quiet outline action buttons. Replaces the hero with info card + filled CTAs.
  • Evidence section: "INDEPENDENT LAB ANALYSIS" label, "Full test details" heading, Warm Linen background, white detail cards with expandable rows.
  • Sample page at /batch/sample with quiet inline caption ("Sample report. Every batch you receive will have its own verified results."). Replaces the full-width green banner. /sample retained as legacy alias.
  • /batch/latest redirect via Cloudflare Worker proof-latest-redirect. Falls back to /batch/sample pre-launch. Supabase custom-domain gateway blocks plain-English slugs (latest, current, now, recent) and rejects responses on those paths, so the redirect is handled at the Cloudflare layer.
  • Green pill badges for test status: "NOT DETECTED" (Salmonella, Listeria), "PASS" (Hygiene). Replaces "Clear" + checkmark icon.
  • Seal restored to original design: cream/neutral outer bezel with green jewel center, white checkmark, stamp-in animation with checkmark draw.
  • Entrance animations: seal stamp, checkmark draw, staggered fade-up on headline / metadata / chips / actions / hint.
  • Info card removed. Replaced by single metadata line: {batch_code} · Tested {date} · {lab_name}.
  • Share buttons restyled as outline buttons (1.5px Stone border, Taupe text). Burnt Sienna removed from proof page actions.
  • Removed "Tested before shipping. Results below." subtitle (evidence is now visible above the fold).

Key Changes in v1.1

  • Architecture rewritten to DB-owned control flow. All business logic moved into 5 named PostgreSQL functions. Edge Function is now a thin HTTP wrapper only.
  • Security hardened. Revoked all anon/authenticated grants on proof_page_events. All writes go through SECURITY DEFINER functions with validated inputs.
  • Nonce-based CSP. Replaced script-src 'unsafe-inline' with per-request nonce generation. unsafe-inline removed from script-src entirely.
  • Batch enumeration leak fixed. Search API and batch page no longer disclose existence of unreleased batches. Non-released and non-existent return identical responses.
  • Server-side page view logging. proof_page_view events logged inside fn_get_batch_proof_v1() on successful RELEASED page render. Client-side tracking removed for page views (kept for clicks/shares only).
  • SOP-MON-01 monitoring implemented. fn_check_proof_portal_health_v2() deployed on 5-minute pg_cron schedule. Checks event volume anomalies, batch freshness, and ingestion errors.
  • INNER JOIN contract on lab results. RELEASED batches without lab results are treated as data integrity failures, not graceful degradations.
  • Cloudflare rate limiting. /api/event endpoint rate-limited to 10 requests/minute per IP.
  • Idempotent migration. All DB changes use existence guards for safe re-deployment.
  • Removed duplicated batch release flow. Cross-references SOP-PROOF-00 and SOP-LAB-01 instead.
  • Removed stale document references. Updated to Brand Voice v1.3, Visual Identity v2.4, SOP-LAB-01.

1. Overview

1.1 Purpose

The Proof Portal is Protocol Raw's public-facing verification system. It allows customers, vets, and prospects to verify the safety testing results for any released batch. The portal serves as the operational manifestation of "Proof, Not Promises" — transforming trust claims into verifiable evidence.

1.2 Strategic Role

The Proof Portal is not a marketing asset. It is:

  1. A verification tool — Customers confirm their batch passed testing
  2. A trust-transfer mechanism — Customers share proof with vets and family
  3. A competitive moat — Time-locked trust capital that compounds with each batch
  4. A differentiation signal — Proves Protocol Raw operates differently than competitors

1.3 Access Points

Entry Point URL Use Case
QR Code Scan proof.protocolraw.co.uk/batch/{id} Customer scans packaging
Portal Homepage proof.protocolraw.co.uk Manual batch search
Sample Page proof.protocolraw.co.uk/batch/sample Pre-purchase prospect exploration
Latest Redirect proof.protocolraw.co.uk/batch/latest Dynamic 302 to most recent released batch (via Cloudflare Worker proof-latest-redirect). Falls back to /batch/sample pre-launch.
Shared Link proof.protocolraw.co.uk/batch/{id} Vet/family receives link
Website CTAs Various site pages All proof CTAs link to /batch/sample pre-launch, /batch/latest post-launch
Legacy alias proof.protocolraw.co.uk/sample Retained alias for the sample page; new links should use /batch/sample

2. System Architecture

2.1 Technical Stack

Component Technology Purpose
Edge Function Supabase Deno (proof-page) Thin HTTP wrapper, HTML rendering
Database Supabase PostgreSQL (raw_ops schema) All business logic, validation, analytics
Domain Cloudflare DNS, SSL, caching, rate limiting
Fonts Google Fonts Inter, Montserrat

2.2 Architecture Principle

PostgreSQL owns all business logic. The Edge Function is a thin HTTP wrapper.

All data retrieval, search, analytics ingestion, and validation happen in named PostgreSQL functions. The Edge Function's responsibilities are limited to: parsing HTTP requests, calling the appropriate database function via RPC, and rendering HTML from the returned data.

2.3 Edge Function: proof-page

Location: Supabase Edge Functions Auth: Service role key (required because anon access to events table has been revoked) JWT Verification: Disabled (public endpoint) Domain: proof.protocolraw.co.uk (Cloudflare DNS → Supabase Edge Function) CSP: Per-request nonce-based. No unsafe-inline in script-src.

Routes

Route Method DB Function Called Purpose
/ GET None (pre-launch redirect) Redirects to main site
/batch/{public_batch_id} GET fn_get_batch_proof_v1() Individual batch page
/sample GET None (hardcoded data) Sample report for prospects
/api/search GET fn_search_public_batch_v1() Batch lookup API
/api/event POST fn_ingest_proof_event_v1() Click/share analytics

Route Handler Contract

Each route handler follows the same pattern:

  1. Parse and sanitise input from the HTTP request
  2. Call the named PostgreSQL function via supabase.rpc()
  3. Map the function result to an HTTP response (HTML page or JSON)
  4. Return with appropriate headers (CSP, caching, security)

The Edge Function never queries tables or views directly. It never contains business logic, validation rules, or data transformation beyond HTML rendering.

2.4 Database Functions

Function Purpose Called By
fn_get_batch_proof_v1(p_public_batch_id, p_referrer, p_user_agent, p_device_type) Retrieve batch proof data. Logs server-side page view for RELEASED batches. Returns status-only for QA_HOLD/REJECTED. NULL for not found. serveBatchPage()
fn_search_public_batch_v1(p_search_term) Search by batch_code or public_batch_id. RELEASED only. No enumeration leak. handleSearch()
fn_ingest_proof_event_v1(p_event_type, p_batch_code, ...) Validated click/share event ingestion. Rejects proof_page_view (server-side only). handleEvent()
fn_get_latest_released_batch_v1() Most recently released batch for homepage. Ordered by released_at. serveHomepage()
fn_check_proof_portal_health_v2() SOP-MON-01 compliant health monitor. run-monitor Edge Function

All functions are SECURITY DEFINER with SET search_path = raw_ops, pg_temp.

2.5 Database Schema

View: v_released_batches_verified

Retained for Metabase dashboard queries. Not used by the Edge Function (which calls functions directly).

Table: proof_page_events

Analytics tracking for proof portal engagement.

CREATE TABLE raw_ops.proof_page_events (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  event_type TEXT NOT NULL,
  batch_code TEXT NOT NULL,
  public_batch_id TEXT,
  referrer TEXT,
  user_agent TEXT,
  device_type TEXT,
  share_method TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT chk_proof_event_type
    CHECK (event_type IN ('proof_page_view', 'send_to_vet_click', 'share_proof_click'))
);

-- Indexes
CREATE INDEX idx_proof_page_events_type_created
  ON raw_ops.proof_page_events(event_type, created_at DESC);
CREATE INDEX idx_proof_page_events_batch
  ON raw_ops.proof_page_events(batch_code, created_at DESC);

Access control: - RLS enabled, no anon or authenticated policies (service_role only) - All writes go through fn_ingest_proof_event_v1() (click/share events) or fn_get_batch_proof_v1() (server-side page views) - Metabase reads via service_role connection


3. Portal Homepage

3.1 URL

https://proof.protocolraw.co.uk/

3.2 Pre-Launch Behaviour

Currently redirects (302) to https://www.protocolraw.co.uk. Remove redirect at launch to enable the full homepage with search and recent batches.

3.3 Data Source

fn_get_latest_released_batch_v1() — returns the most recently released batch ordered by released_at DESC. INNER JOIN on lab_results ensures only batches with complete proof data are shown.

3.4 Page Structure

Hero Section: "Proof, Not Promises" headline, subtitle, batch lookup card with search input.

Recent Batches Section: Displays latest released batch(es) with status, batch code, test date, and link to full results.

Bridge Section: CTAs to calculator and how-it-works pages.

3.5 Search API

Endpoint: GET /api/search?batch_code={id}

DB Function: fn_search_public_batch_v1(p_search_term)

Response:

// Found and released
{ "found": true, "status": "RELEASED", "public_batch_id": "PR-2CCF573F" }

// Not found OR not released (identical — no enumeration leak)
{ "found": false }

Security note: Prior to v1.1, the search endpoint returned {"found": true, "status": "NOT_RELEASED"} for unreleased batches, confirming their existence to unauthenticated users. This has been fixed. All non-released batches now return the same response as non-existent batches.


4. Individual Batch Page

4.1 URL

https://proof.protocolraw.co.uk/batch/{public_batch_id}

4.2 Data Source

fn_get_batch_proof_v1(p_public_batch_id, p_referrer, p_user_agent, p_device_type)

Response shapes:

Batch Status Function Returns Page Rendered
RELEASED Full proof data (lab results, product, formulation) + server-side page view logged Full results page with wax seal, test cards, share buttons
QA_HOLD {"status": "QA_HOLD"} Status page: "This batch is undergoing safety testing."
REJECTED {"status": "REJECTED"} Status page: "This batch did not pass our safety requirements."
Not found NULL 404 page

Integrity contract: RELEASED batches use INNER JOIN on lab_results. If a RELEASED batch has no lab results, the function logs a data integrity error to ops_events and returns NULL (404 to the user). This is deliberate: the proof portal exists to publish evidence. A released batch without evidence is a system failure, not a graceful degradation.

4.3 Server-Side Page View Logging

Page views are logged server-side inside fn_get_batch_proof_v1() when a RELEASED batch is successfully fetched. This is the authoritative source for QR scan and page view counts. Client-side sendBeacon was removed because it is unreliable (ad blockers, race conditions, silent failures).

Client-side tracking is retained only for click events (send_to_vet_click, share_proof_click) where server-side logging is not possible.

4.4 Page Structure

The page is two sections: Verdict (above the fold) and Evidence (below). The Verdict delivers the headline answer; the Evidence backs it up for anyone who scrolls.

Verdict Section

  • Sample caption (sample page only): quiet inline text "Sample report. Every batch you receive will have its own verified results."
  • Wax seal (200px): cream/neutral outer bezel with green jewel center (radial gradient #4A8B72 → #3D6B5A → #2D5144 → #234238), shine overlay, white checkmark on the jewel. Stamp-in animation with delayed checkmark draw and continuous subtle glow.
  • Headline: "All clear." (Montserrat 800, 52px desktop / 40px ≤900 / 36px ≤600)
  • Metadata line: {batch_code} · Tested {reported_at, formatted en-GB} · {lab_name} (13px Inter 500, Taupe; separators in Stone). Sample page uses "Independent lab" in place of lab_name.
  • Result chips: three inline white chips, each with chip-name (e.g. "Salmonella") + chip-badge green pill ("NOT DETECTED" or "PASS"). Salmonella and Listeria show "NOT DETECTED" when *_absent; Hygiene shows "PASS" when enterobacteriaceae value is below the limit.
  • Action row: "Send to Vet" + "Share" as outline buttons (1.5px Stone border, Taupe text, transparent background; hover Espresso/white).
  • Action hint: "Handy for vets, family, or anyone who asks."

Evidence Section

  • Background: Warm Linen (#EBE8E3) with Stone top divider + 6px inset shadow.
  • Label: "INDEPENDENT LAB ANALYSIS" (11px, 0.15em letter-spacing, Burnt Sienna).
  • Heading: "Full test details" (Montserrat 700, 24px).
  • Three detail cards: white on Linen, Forest Green icon (44px, gradient var(--forest)var(--forest-light)), test name, green detail-badge pill, expandable detail rows revealing Test / Result / Method / Lab. Cards expand on click.
  • Two bottom cards: Complete nutrition (links to formulation_pdf_url; disabled on sample) + Full lab report (download link; replaced with "Lab certificates are available on live batch reports." copy on sample).

4.5 Sample Report

Canonical URL: proof.protocolraw.co.uk/batch/sample Legacy alias: proof.protocolraw.co.uk/sample (still served by the same serveSamplePage() handler)

Hardcoded data, no database queries. The page renders the same Verdict + Evidence layout as a real batch, with a quiet inline caption above the seal: "Sample report. Every batch you receive will have its own verified results."

Uses the current request time as the "Tested" field — a cosmetic recency signal disclosed by the caption.

4.6 Cloudflare Worker: proof-latest-redirect

The Edge Function exposes /batch/latest (and the alias /batch/PR-00LATEST) which 302-redirects to the most recent released batch via fn_get_latest_released_batch_v1(), falling back to /batch/sample when no released batches exist.

The Supabase custom-domain gateway intercepts plain-English slugs under /batch/ (latest, current, now, recent) and returns {"error":"requested path is invalid"} before requests reach the function. To work around this, the redirect is fronted by a Cloudflare Worker.

Field Value
Worker name proof-latest-redirect
Routes proof.protocolraw.co.uk/batch/latest, proof.protocolraw.co.uk/batch/PR-00LATEST
Behaviour Fetches the direct Supabase function URL (znfjpllsiuyezqlneqzr.supabase.co/functions/v1/proof-page/batch/PR-00LATEST) and passes the 302 response through
Response cache Cache-Control: no-cache (redirect target changes when new batches release)
Fallback If no released batches, the function returns 302 to /batch/sample; the Worker passes that through
Analytics The worker does not log; the destination batch page logs its own proof_page_view

5. Share Functionality

5.1 Strategic Purpose

Share buttons are a growth primitive, not a marketing feature. They enable customers to transfer trust to skeptical audiences (vets, family) using verifiable evidence rather than brand claims.

5.2 Send to My Vet

Trigger: Button click Action: Opens mailto with prefilled content Tracking: send_to_vet_click event via client-side track()/api/eventfn_ingest_proof_event_v1()

Subject:

Lab results for my dog's food (Protocol Raw)

Body:

Hi,

I wanted to share the safety test results for the raw food I'm feeding.

Batch: {batch_code}
Tests: Salmonella, Listeria, Enterobacteriaceae
Result: All clear

Full report: {batch_url}

Happy to discuss if you have questions.

Best regards

5.3 Share This Proof

Trigger: Button click Action: Web Share API (mobile) or copy to clipboard (desktop) Tracking: share_proof_click event with share_method: 'native' or 'copy'

5.4 Share Hint

Text: "Handy for vets, family, or anyone who asks."


6. Analytics

6.1 Event Sources

Event Source Properties
proof_page_view Server-side (fn_get_batch_proof_v1) batch_code, public_batch_id, referrer, user_agent, device_type
send_to_vet_click Client-side JS → /api/event → fn_ingest_proof_event_v1 batch_code, share_method: 'email'
share_proof_click Client-side JS → /api/event → fn_ingest_proof_event_v1 batch_code, share_method: 'native' or 'copy'

6.2 Validation

All events are validated by fn_ingest_proof_event_v1(): - event_type must be in allowed list (proof_page_view rejected from client — server-side only) - device_type must be 'mobile', 'desktop', or 'tablet' (else NULL) - share_method must be 'email', 'native', or 'copy' (else NULL) - All text fields truncated to prevent oversized payloads - Empty strings normalised to NULL - Failures logged to ops_events with nested exception protection

6.3 Key Metrics

Metric Query Insight
Daily page views COUNT(*) WHERE event_type = 'proof_page_view' AND created_at > now() - interval '1 day' QR scan engagement
Share rate share_clicks / page_views Trust transfer activity
Vet share rate vet_clicks / page_views Professional validation seeking
Mobile vs Desktop GROUP BY device_type Access context
Referrer breakdown GROUP BY referrer Entry point analysis

6.4 Metabase Dashboard Queries

Collection: "SOP-PROOF-01 — Proof Portal"

Daily Views:

SELECT
  DATE(created_at) as date,
  COUNT(*) as views
FROM raw_ops.proof_page_events
WHERE event_type = 'proof_page_view'
GROUP BY DATE(created_at)
ORDER BY date DESC
LIMIT 30;

Share Funnel:

SELECT
  event_type,
  COUNT(*) as count
FROM raw_ops.proof_page_events
WHERE created_at > now() - interval '30 days'
GROUP BY event_type
ORDER BY count DESC;

Share Method Breakdown:

SELECT
  share_method,
  COUNT(*) as count
FROM raw_ops.proof_page_events
WHERE event_type = 'share_proof_click'
  AND created_at > now() - interval '30 days'
GROUP BY share_method;

Weekly Share Report:

SELECT
  DATE_TRUNC('week', created_at) as week,
  COUNT(*) FILTER (WHERE event_type = 'proof_page_view') as views,
  COUNT(*) FILTER (WHERE event_type = 'send_to_vet_click') as vet_shares,
  COUNT(*) FILTER (WHERE event_type = 'share_proof_click') as social_shares,
  ROUND(
    COUNT(*) FILTER (WHERE event_type IN ('send_to_vet_click', 'share_proof_click'))::numeric /
    NULLIF(COUNT(*) FILTER (WHERE event_type = 'proof_page_view'), 0) * 100,
    2
  ) as share_rate_pct
FROM raw_ops.proof_page_events
WHERE created_at > now() - interval '12 weeks'
GROUP BY DATE_TRUNC('week', created_at)
ORDER BY week DESC;


7. Visual Design

7.1 Design System Reference

Source: Visual Identity Guide v2.5

7.2 Color Palette

Token Hex Usage
--col-espresso #2B2523 Primary text, footer
--col-forest-green #2D5144 Pass badges, verified status, share buttons
--col-burnt-sienna #B85C3A Primary CTAs
--col-cream #F9F7F4 Body background, header gradient
--col-warm-linen #EBE8E3 Card backgrounds, borders
--col-taupe #6B6360 Secondary text, labels

Batch Page Container: Cream (#FCFBF9) background with paper texture overlay. This is intentionally lighter than the standard Cream to create a clean, clinical context for lab results. Declared as a proof-context override from the standard brand palette.

7.3 Typography

Element Font Weight Size (Desktop) Size (Mobile)
Brand header Montserrat 700 18px 18px
H1 Montserrat 800 48px 28px
H2 Montserrat 700 28px 22px
Body Inter 400 17px 16px
Labels Inter 600 10-12px 10-11px
Buttons Inter 600 14px 14px

7.4 Animations

All animations respect prefers-reduced-motion: reduce.

Element Animation Duration Delay
Seal sealStamp (scale 0.85 → 1.04 → 1, opacity 0 → 1) 700ms 100ms
Seal text / hr / pips fadeIn 400ms 500ms
Seal checkmark checkDraw (stroke-dashoffset 40 → 0) 400ms 500ms
Seal glow ring sealGlow (continuous pulse) 3000ms 800ms (loops)
Headline fadeUp 500ms 400ms
Metadata line fadeUp 500ms 500ms
Result chips fadeUp 500ms 600ms
Action row fadeUp 500ms 700ms
Action hint fadeUp 500ms 800ms

7.6 UI Patterns

  • Green pill badge (.chip-badge, .detail-badge): background #E8F5E9, text #2D5144, border-radius 100px, 12px Inter 600, uppercase, 0.03em letter-spacing. Used for "NOT DETECTED" and "PASS" labels in the verdict chips and detail cards. The green background carries the pass signal — no checkmark icon is rendered inside the badge.
  • Evidence section background: Warm Linen (#EBE8E3) — a deliberate override from the proof-page Cream canvas to delineate Evidence from Verdict.
  • Cards on Linen: white background with 1px solid rgba(43,37,35,0.05) border and subtle shadow (0 1px 3px rgba(43,37,35,0.06), 0 4px 12px rgba(43,37,35,0.03)).
  • Seal: the canonical render is a cream/neutral outer bezel (linear-gradient(145deg, #e8e5e0 0%, #d4d0ca 50%, #e2dfda 100%)) with a green jewel center (radial gradient #4A8B72 0%#3D6B5A 30%#2D5144 70%#234238 100%) and a white checkmark on the jewel.

7.5 Responsive Breakpoints

Breakpoint Changes
≤600px Single column layout, stacked share buttons, smaller headings, stacked test cards
≤900px Reduced padding, smaller seal, vertical info card
>900px Full desktop layout with 3-column test cards

8. Security

8.1 Content Security Policy

Generated per-request with a unique nonce:

default-src 'self';
script-src 'nonce-{random}' https://cdn.protocolraw.co.uk https://my.protocolraw.co.uk;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' data: https:;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'

unsafe-inline is removed from script-src. All inline scripts use the per-request nonce attribute. unsafe-inline is retained for style-src due to Google Fonts and inline styles.

8.2 Additional Headers

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()

8.3 Data Access

  • Edge Function uses service_role key (anon access revoked)
  • Only RELEASED batches return full proof data
  • QA_HOLD and REJECTED return status-only (no lab data, no batch details)
  • Non-existent batches return NULL (404)
  • No PII is exposed through the proof portal
  • Search endpoint does not disclose existence of unreleased batches

8.4 Analytics Endpoint Security

  • /api/event rate-limited via Cloudflare: 10 requests/minute per IP
  • fn_ingest_proof_event_v1() validates event_type against allowed list
  • Field truncation prevents oversized payloads
  • CHECK constraint on event_type column as DB-level defence in depth
  • No direct table access: all writes through SECURITY DEFINER functions

9. Caching

Page Cache-Control Rationale
Batch pages public, max-age=3600 Lab results don't change once released
Portal homepage public, max-age=300 Latest batch updates more frequently
Sample page public, max-age=3600 Static content
API endpoints No cache Real-time data

10. Copy Principles

10.1 Voice Guidelines

Aligned with: Protocol Raw Brand Voice & Copy Guidelines v1.3

  • Show, don't tell — Let lab results speak
  • Systematic, not emotional — Facts over reassurance
  • Clinical where appropriate — Vets are an audience
  • No anxiety amplification — Don't mention risks at relief moments

10.2 Key Copy Decisions

Element Decision Rationale
Summary verdict (h1) "All clear." retained Headline summary, not an individual test label. Conversational, confident, low-key.
Subtitle Removed in v1.2 Evidence is now visible above the fold via result chips, so the directional subtitle is redundant.
Salmonella status "Not detected" Matches lab terminology (ISO 6579-1 reports detection state).
Listeria status "Not detected" Matches lab terminology (ISO 11290-1 reports detection state).
Hygiene status "Pass" Threshold-based test (Enterobacteriaceae count vs limit), not binary detection.
Share hint "Handy for vets, family, or anyone who asks." Frames sharing as practical, not promotional.
Vet email tone Clinical, bullet points Vets want data, not marketing.
FEDIAF claim "Meets FEDIAF guidelines for all life stages" Only claim what we can evidence.

11. Monitoring

11.1 Health Monitor

Function: fn_check_proof_portal_health_v2() Schedule: Every 5 minutes via pg_cron (monitor-proof-portal-health) Pattern: SOP-MON-01 compliant (pg_cron → pg_net → run-monitor → fn_check → monitoring_runs → ops-alerter)

Checks:

Check Threshold Severity Channel
Event volume spike >5x 7-day hourly average AND >100 absolute Warning #ops-alerts
Batch freshness >7 days since last release Warning #ops-alerts
Ingestion errors >10 errors in last hour Critical #ops-urgent

11.2 Metabase Dashboard

Collection: "SOP-PROOF-01 — Proof Portal"

See Section 6.4 for saved question SQL.

11.3 Operational Procedures

Upstream dependencies: Batch creation and release (SOP-PROOF-00, SOP-LAB-01). If batches stop being released, the freshness monitor will alert.

For batch lifecycle and release flow: See SOP-LAB-01 for lab result processing and batch release, and SOP-PROOF-00 for proof generation pipeline (QR codes, labels, co-packer delivery).


12. Future Enhancements

12.1 Planned

Enhancement Priority Status
Deploy Metabase saved questions High Ready (SQL exists in Section 6.4)
Partition/retention strategy for proof_page_events Medium Design now, implement Phase B
Download certificate tracking event Medium Not started
Formulation link click tracking event Medium Not started

12.2 Considered but Deferred

Enhancement Reason Deferred
Social proof counters Could feel like marketing
Comments/reviews Out of scope for verification tool
Batch comparison Low value, adds complexity

Document Relationship
Visual Identity Guide v2.4 Design system source
Protocol Raw Brand Voice & Copy Guidelines v1.3 Copy voice reference
SOP-PROOF-00 v1.0 Upstream: proof generation pipeline, batch creation, QR/label system
SOP-LAB-01 Upstream: lab result processing, batch release/rejection
SOP-MON-01 v1.0 Monitoring pattern
SOP-INV-01 Downstream: allocation after release

14. All Objects

Object Type Purpose
raw_ops.proof_page_events Table Portal analytics
raw_ops.fn_get_batch_proof_v1() Function Batch page data + server-side page view
raw_ops.fn_search_public_batch_v1() Function Public batch search
raw_ops.fn_ingest_proof_event_v1() Function Validated click/share ingestion
raw_ops.fn_get_latest_released_batch_v1() Function Homepage latest batch
raw_ops.fn_check_proof_portal_health_v2() Function SOP-MON-01 health monitor
monitor-proof-portal-health pg_cron job 5-minute health check schedule
chk_proof_event_type CHECK constraint DB-level event_type validation
ux_batches_public_batch_id Unique index Guarantees batch lookup contract
ux_batches_batch_code Unique index Guarantees search contract
proof-page Edge Function Thin HTTP wrapper, HTML rendering

15. Version History

Version Date Author Changes
1.1 2026-03-20 Protocol Raw Operations Architecture remediation: DB-owned functions, security hardening, nonce-based CSP, server-side page views, SOP-MON-01 monitoring, enumeration fix, Cloudflare rate limiting. Updated all document references.
1.0 2026-01-27 Protocol Raw Operations Initial comprehensive documentation

End of SOP-PROOF-01 v1.1

Last reviewed: 2026-03-20 Next review: 2026-06-20 System status: ✅ Production Ready

Protocol Raw — Verified safe, batch by batch