What leaves your network, and what we do not have

ProofPack runs inside your environment. This page lists every channel by which anything can leave it, generated from the engine’s own egress schema rather than written by hand — and lists, by name, the security assurances we do not hold.

Page last updated 2026-09-10. Nothing on this page is a certification, an approval or an endorsement, and none is claimed anywhere on this site.

Egress — everything that may ever leave

The field lists below are generated at build time fromegress_schema.json, the schema the engine validates its own outbound payload against, vendored from the engine repository as it stood at commit8e98728, the last commit that changed it. A continuous-integration check re-derives this table and fails the build if the page and the schema disagree, so the table cannot quietly understate what is sent.

Egress channels, when each fires, the exhaustive field list and the limits applied
ChannelWhenFields (exhaustive)Limits and suppressionExists today?
Demo — uploadneverNo endpoint exists that accepts uploads. To be verified by the visible network counter and by a CI network-capture test (Playwright HAR).Not built yet

The in-browser demo is a later lane-S day. Nothing on this site accepts an upload today because no upload route exists in the repository at all.

Demo — eventon run completion, unless opted out
  • source
  • rows_bucket
  • duration_ms
  • halted
No headers, no numbers, no file names. `source` is one of `sample` or `upload`.Not built yet

No analytics of any kind is wired up on this site yet — not even Cloudflare Web Analytics.

Runner — licence checknever (removed before launch)There is no licence server. A licence file is an Ed25519-signed document that verifies offline against the public key published on the trust page (/trust#licence-key), so the runner never phones home to check it.Removed

D2 §5.1 listed a licence-check call. D1 §6 and §7 removed it: at launch the runner makes at most one outbound call, and it is not this one. The row is kept so the removal is on the record rather than silently absent.

Runner — telemetryrun end; skipped entirely with `--offline` or `egress.telemetry: false`
  • schema
  • licence_id
  • run_id
  • engine_version
  • platform
  • manifest_sha256
  • duration_s
  • halt_code
  • row_count_bucket
  • timestamp

Generated from $defs/telemetry in the schema below.

The manifest hash only — no column names, no counts below bucket level, no metric values, no row-level field, no free-text declaration field. `row_count_bucket` is one of `<1k`, `1k-10k`, `10k-100k`, `>100k`; `halt_code` is a typed code or null.Not built yet

The runner's telemetry module is a lane-E day that has not run yet. The field list beside this row is generated from the schema the engine will validate the payload against, not typed by hand.

Runner — narrative (optional, online, off by default)deferred past v1.0 — no code path existsIf it is ever built: column headers passing the whitelist regex, and a claims JSON of aggregates only, validated against the `proofpack-aggregates/1` branch of the egress schema, which the trust page publishes verbatim (/trust#egress). Cells with n<10, events<5 or non-events<5 suppressed before egress; sites and devices pseudonymised (Site A, Site B…) and mapped back locally; no free text, no dates, no row-level fields. The aggregate rules are already in the schema and already CI-tested, so the rule exists before the feature.Deferred

There is no LLM anywhere in the pack pipeline at launch. Nothing in ProofPack v1.0 sends anything to a language model.

Support — support@only when a person at your company emails us
  • whatever that person chooses to put in the email
We never ask for test-set data, model outputs or patient data in a support ticket. If a support answerer is ever built, it will be tested against a corpus of tickets containing pasted data to prove it makes no model call on them, before it is switched on — no such module or corpus exists today. If you send us data anyway it is in our mailbox, which is the one egress route on this table that your own people control rather than our code.Yes

Our company email is hosted on Google Workspace today, which is why Google is on the sub-processor list (/trust#sub-processors and /legal/sub-processors). The `support@` alias itself has not been created yet, so mail to us reaches the founder’s mailbox. The tested support answerer is a lane-A day that has not run yet.

Site — buying ProofPackwhen you start a checkout or ask for a quote
  • legal entity
  • buyer name and email
  • billing address
  • VAT/EIN
  • company registration number
  • purchase order number
  • plan and model count
  • the model name you type on the form
  • accounts-payable email, if you give one
  • which procurement documents you need (DPA countersignature, security questionnaire, W-8BEN-E, vendor form)
  • on a quote acceptance: the name and role of the person who accepts, their confirmation that they are authorised to bind the company, their IP address, their browser user-agent string, and the time of acceptance
Held by Stripe (payments, tax, invoicing) and in our own database; quote PDFs are stored in a private bucket and served through our own route. The IP address and user-agent are recorded only as the audit record for a quote acceptance, which the acceptance page itself states before you submit it. No test-set data, no model output and no patient data reaches any of it, because none of it is ever asked for.Yes

Built and tested against a Stripe mock. No live Stripe, database or email account exists yet, so nothing has actually been stored anywhere.

--offline opens zero sockets. A continuous-integration job is specified to run the reference image under network capture on every release and publish the capture summary here.That job does not exist yet, and neither does the engine test that runs the suite with the network namespace removed. Both are listed as pending onthe validation page. Until they are green, treat the statement above as a design commitment we have written down, not as a measurement we have taken.

Suppression before anything is serialised

Any aggregate cell with n < 10, fewer than 5 events or fewer than 5 non-events is serialised as suppressed with null values. A customer may tighten those numbers and may not loosen them. Sites, devices and protocols are pseudonymised to “Site A”, “Device A”, “Level A” before egress, and the map back is written only to your own machine.

These are never serialised at all, in any channel:

  • original headers
  • row-level values
  • justification
  • description
  • source
  • raw dates

The schema itself

Published verbatim, because a summary of a schema is not a schema. This is byte-for-byte the file in the engine repository atschema/egress_schema.json; the build fails if this copy and the engine's copy diverge.

egress_schema.json (vendored 2026-09-10, SHA-256 c98b85aec4a1de89…)
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://proofpack.globalphoenix.co.uk/schema/egress_schema.json",
  "title": "ProofPack egress schema (SKELETON, day 1)",
  "description": "Everything that may ever leave the customer's machine. At launch the runner makes at most one outbound call: the telemetry POST. No column names, no counts below bucket level, no metric values, no row-level field, no free-text declaration field. Prose source: D1 section 6. Published verbatim on the trust page.",
  "$defs": {
    "telemetry": {
      "type": "object",
      "properties": {
        "schema": { "type": "string", "const": "proofpack-telemetry/1" },
        "licence_id": { "type": "string", "pattern": "^L-[A-Za-z0-9-]+$" },
        "run_id": { "type": "string", "format": "uuid" },
        "engine_version": { "type": "string" },
        "platform": { "type": "string", "pattern": "^[a-z0-9_]+-[a-z0-9_]+-cp3[0-9]{2}$" },
        "manifest_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "duration_s": { "type": "number", "minimum": 0 },
        "halt_code": { "type": ["string", "null"], "enum": ["H01", "H02", "H03", "H04", "H05", "H06", "H07", "H08", "H09", "H10", "H11", "H12", null] },
        "row_count_bucket": { "type": "string", "enum": ["<1k", "1k-10k", "10k-100k", ">100k"] },
        "timestamp": { "type": "string", "format": "date-time" }
      },
      "required": ["schema", "licence_id", "run_id", "engine_version", "platform", "manifest_sha256", "duration_s", "halt_code", "row_count_bucket", "timestamp"],
      "additionalProperties": false
    },
    "number": {
      "type": "object",
      "description": "Aggregate Number object (deferred narrative call). Suppressed cells carry null values.",
      "properties": {
        "value": { "type": ["number", "null"] },
        "ci_low": { "type": ["number", "null"] },
        "ci_high": { "type": ["number", "null"] },
        "n": { "type": ["integer", "null"], "minimum": 10 },
        "k": { "type": ["integer", "null"] },
        "suppressed": { "type": "boolean" }
      },
      "required": ["value", "suppressed"],
      "additionalProperties": false
    },
    "aggregate_cell": {
      "type": "object",
      "properties": {
        "metric_id": { "$ref": "criteria_schema.json#/$defs/metric_id" },
        "attribute": { "type": ["string", "null"], "pattern": "^[a-z][a-z0-9_]{0,31}$" },
        "level": { "type": ["string", "null"], "pattern": "^(Site|Device|Protocol|Level) [A-Z]+$|^Unknown/missing$|^[a-z][a-z0-9_]{0,31}$" },
        "number": { "$ref": "#/$defs/number" }
      },
      "required": ["metric_id", "number"],
      "additionalProperties": false
    }
  },
  "oneOf": [
    { "$ref": "#/$defs/telemetry" },
    {
      "type": "object",
      "properties": {
        "schema": { "type": "string", "const": "proofpack-aggregates/1" },
        "cells": { "type": "array", "items": { "$ref": "#/$defs/aggregate_cell" } }
      },
      "required": ["schema", "cells"],
      "additionalProperties": false
    }
  ],
  "x-proofpack": {
    "status": "skeleton",
    "suppression_defaults": { "min_n": 10, "min_events": 5, "min_nonevents": 5 },
    "suppression_rule": "Any cell with n < min_n, events < min_events or non-events < min_nonevents is serialised with suppressed=true and null values. Customers may only tighten these.",
    "pseudonymised_attributes": ["site", "device", "protocol", "attr_*"],
    "header_whitelist_pattern": "^[a-z][a-z0-9_]{0,31}$",
    "never_serialised": ["original headers", "row-level values", "justification", "description", "source", "raw dates"]
  }
}

The demo runs in your browser

When you upload a file in the demo, it is parsed and analysed inside your browser tab by the ProofPack engine running under Pyodide. There is no upload endpoint. Date-like columns are coarsened to calendar quarter before analysis. Closing the tab discards the data. Built-in sample results are pre-computed when we build the site and contain no visitor data. You can confirm all of this in your browser's developer tools; a screenshot of what you should see is below.

The browser-only statement, published in full and unedited.

There is no demo yet, and no screenshot. The demo is a later build day. The paragraph above is published now, unedited, as the specification the demo will be built to and checked against — the network-capture test that proves “there is no upload endpoint” does not exist yet either. Read it as a commitment, not as a measurement. What is true today is narrower and checkable: this repository contains no route that accepts a file upload of any kind.

Language models

There is no language model anywhere in the pack pipeline in version 1.0. No part of generating an evidence pack calls one, including the optional narrative, which is deferred past the first release. Nothing on this site calls one either.

The wording below applies to the optional runner narrative if and when it is built. It is published now so the retention position is on the record before the feature exists:

The optional runner narrative uses the Anthropic API. Until a zero-data-retention agreement is granted (requested launch week), Anthropic retains request content for up to 30 days. The request contains only whitelisted headers and k-suppressed aggregates. Default narrative mode needs no network.

No zero-data-retention agreement has been requested or granted, because there is no account and no feature to attach it to. When one is requested, the request date will be published here; when one is granted, the grant date will replace this paragraph.

Security posture, honestly

What runs where

  • A static site, plus five small server endpoints: checkout, quotes, the quote PDF, quote acceptance and the payment webhook.
  • A Postgres database holding orders, licences and quotes. No customer test data, no model output, no patient data.
  • No user accounts and no logins anywhere in the first release. There is no session to steal and no password to leak.
  • Card details are handled entirely on the payment provider's own hosted pages. No card number ever reaches our code or our logs.
  • The ProofPack engine itself runs on your infrastructure, not ours. We never have your data to lose.

Controls that are in the code today

The site is not deployed yet, so none of these has ever served a real request. Each is in the repository and covered by tests that run on every change; none has been exercised against a live account, a live payment provider or a live database. That distinction matters more than the list does.

  • Transport security and security response headers on every route —nosniff, X-Frame-Options: DENY, a referrer policy, a permissions policy and HSTS. The static pages get them from the edge configuration; the five server endpoints set the same five headers in their own code, because the edge configuration does not apply to them. A test asserts the two lists are identical.
  • Payment webhook signatures verified before the request body is parsed, with a replay window and a constant-time comparison; every event id is recorded so a retry cannot issue twice, and a failed delivery is retried rather than silently swallowed.
  • Licence files signed with Ed25519. The signing key is read from an environment variable and exists in no file in the repository. The public half is below, so you verify a licence without us.
  • Quote acceptance links are signed and expire absolutely after 30 days; the quote PDF is served through our own route rather than a public object URL. (The storage account it would use does not exist yet — see sub-processors below.)
  • No third-party script, no web font, no analytics and no cookies on any page of this site. The pages you are reading load nothing from anywhere else.
  • Every dependency in the site is open source and installed from the public registry; there is no paid or proprietary component to be locked out of.
  • A published vulnerability disclosure route: security.txt, 90-day coordinated disclosure.

What we do not have. Said plainly.

This is the part of a trust page that is usually written around. We would rather you read it here than discover it in a questionnaire.

AssuranceStatusWhat we will do
SOC 2Not heldNot planned for year one. It costs money we do not have until customers are paying.
ISO 27001Not heldNot planned for year one, for the same reason.
Cyber EssentialsNot heldWe will start it the first time a customer's procurement requires it, and publish the date we started on this page.
Third-party penetration testNot doneNone commissioned. If you have an internal team and want to test us, we will help and we will publish what you find, with your permission.
Automated security scanning in CINot runningA baseline dynamic scan of the deployed site and a container vulnerability scan are specified and not yet wired up. Both are listed as pending on the validation page. Neither can run until the site is actually deployed.
Software bill of materials per releaseNot producedSpecified, not yet generated.
Professional indemnity or cyber insuranceNot heldNot held today. Ask before you rely on it.
Legal texts reviewed by a solicitorNot reviewedOur terms, privacy notice and data processing agreement are written in plain English by the founder and have not been reviewed by a solicitor. Several are still marked as placeholders on the site and say so on their own pages.
Independent review of the regulatory wordingNot doneNo regulatory-affairs professional has reviewed the guidance mapping or the pack wording yet. The empty slot is shown on the validation page rather than hidden.
Business associate agreementNot applicableNo protected health information reaches us, so there is nothing for a business associate agreement to cover. If you believe otherwise about your deployment, tell us before you buy.

If a control appears on this page it is because it is in the code today. If it is in the table above it is not. We do not list a planned control as an existing one.

Sub-processors

None of these receives customer test rows, model outputs or patient data, because none of that ever leaves your environment. Most of them are not connected yet, which is stated per row.

Sub-processorPurposeRegionIn use today?
CloudflareSite hosting and the five dynamic endpointsGlobal edgeNo account exists yet — the site is not deployed.
StripePayments, invoicing and sales taxUnited States / European UnionNo account connected yet; the commerce code runs against a local mock.
SupabaseDatabase for licences, orders and quote PDFsTo be confirmed when the project is createdNo project exists yet.
ResendTransactional email: licence file, quote, receiptsTo be confirmedNo account exists yet.
GitHubSource control, CI and release artefactsUnited StatesIn use.
jsDelivrPyodide runtime for the in-browser demo onlyGlobal edgeNot in use — the demo is not built.
AnthropicOptional runner narrative (deferred past version 1.0) and, when it is built, the tier-one support answererUnited StatesNot in use. No account exists yet, and nothing in version 1.0 calls a language model.
Google (Workspace / Gmail)Mailbox hosting for our company email, which is where anything you send us by email arrivesTo be confirmed from the Workspace configurationIn use for company email. The support@ alias itself has not been created yet.

The formal list, with the change-notice period, is at/legal/sub-processors. That page is still marked as a placeholder and says so.

If we stop trading

Global Phoenix Solutions Ltd is a company registered in England and Wales, number 14855822. It is one person. You should plan for the possibility that it stops, and the product is built so that this costs you nothing:

  • The container runs on your infrastructure and keeps running. There is no service to switch off.
  • Licence files verify offline against the public key below. No licence server exists, so none can go dark.
  • Outputs are ordinary DOCX, HTML and JSON files that you already hold.
  • An annual licence carries perpetual use of the version you have.
  • The engine source is public, so every formula can be read, inspected and re-run by any statistician without us and without a licence.
  • A standalone methods document — the formulae, their citations and their limits in one place — is not written yet. Until it is, the source above is the only published statement of the arithmetic.

The perpetual-use clause lives in our terms, and our terms are not written yet — /legal/terms is marked as a placeholder and says so on its own page. Until it is written, read this list as what we intend to be bound by, not as something you could currently hold us to.

Retention

WhatKept for
Anything you put into the demoNothing is kept. It never leaves your browser tab, and closing the tab discards it.
Site events13 months, aggregate only. Nothing is collected today.
Runner telemetryManifest hashes for 24 months. Nothing is collected today.
Order, licence and quote recordsAs long as the commercial relationship and our statutory record-keeping require, per our terms.
Support emailIn our mailbox. If you ask us to delete a thread, we delete it.

Verify a licence file yourself

A ProofPack licence is a signed document, not a server response. It isbase64(payload), a full stop, thenbase64(Ed25519 signature), and the signature covers the exact bytes of the first segment. You can check one without contacting us, offline, in about ten lines of Python.

Algorithm
Ed25519 (RFC 8032)
Key id
pp-2026-09
Status
live
Public key (base64, raw 32 bytes)
XYLnaFRnWVOsLobwSmkbo/qy37anOza+aRpunzmrMAA=

The reference verifier is scripts/verify_licence.py in the site repository: standard library plus one cryptography package, and it shares no code with the issuer, so it checks our signing rather than agreeing with it.

Validation of the validator

A tool that computes the evidence a regulator reads has to show its own working. Every fixture, every cross-check against an independent implementation, every determinism check and every human review is listed at /trust/validation, regenerated from the engine's test artefacts. Checks that have not been run are listed as pending, with a reason, rather than left off the page — and today that is all of them.

Reporting a vulnerability

Email joshua.sandhu@globalphoenix.co.uk, or read/.well-known/security.txt. We operate 90-day coordinated disclosure and we will credit you unless you ask us not to. We have no bug bounty: there is no budget for one, and saying so is better than a page that implies there is.

Questions procurement asks

Does our test data leave our network?
No. ProofPack runs inside your environment and reads your table there. In version 1.0 no row-level value, no column name and no free-text field you declare is part of anything that leaves the machine. The one exception is on the record rather than hidden: if the optional runner narrative is ever built — it is deferred past 1.0 and no code path for it exists — it would send column headers that pass the whitelist regex, along with k-suppressed aggregates, and the egress table says so on its own row. The exhaustive list of what may leave is that table, and it is generated from the schema the engine validates its own outbound payload against.
What does --offline do?
It opens zero sockets. The licence file verifies offline against the public key published on this page, so there is no licence server to call, and the telemetry call is skipped. The engine test for this runs the whole suite with the network namespace removed; that test has not been run yet, and the validation page says so.
Do you hold any patient data?
No, so there is no business associate agreement to sign and nothing to breach. We hold your company and billing details for the purchase, and whatever you choose to put in an email to support. Nothing else.
Do you have SOC 2, ISO 27001 or a penetration test?
No, none of them, and we would rather say so here than be asked. We are a one-person company with no external funding; those cost money we do not have until a customer is paying. We will start Cyber Essentials the first time a customer’s procurement asks for it, and we will publish the date we started on this page.
Has a regulator approved ProofPack?
No. No regulator approves, accepts, certifies or endorses a tool of this kind. Evidence gets reviewed; tools do not get accepted. Anyone telling you otherwise about any product in this category is selling you something that does not exist.
What happens to us if you stop trading?
The container keeps working: it runs on your infrastructure, the licence file verifies offline, and the outputs are ordinary DOCX, HTML and JSON files you already hold. The engine source is public, so any statistician can read the arithmetic and re-run it without us; a standalone methods document is not written yet. An annual licence carries a perpetual-use clause for the version you have, and our terms are not written yet either — /legal/terms says so on its own page.

The honesty note

ProofPack is not certified, approved, accredited or endorsed by any regulator, notified body or standards organisation, and no such claim appears anywhere on this site. Evidence submitted to a regulator gets reviewed; the tools used to prepare it do not get accepted.

The FDA's AI-DSF lifecycle guidance, which shapes the structure of the pack ProofPack renders, is a draft issued in January 2025 for comment and expressly not for implementation. It may change or be withdrawn. We report that status in our prose, in this page's structured data and in every document the engine renders, and we will not describe a draft as though it were settled to make a sale.

ProofPack chooses no acceptance criterion, sets no margin and issues no verdict on a model. You author your acceptance criteria, with your name, the date and your justification against them; the engine reports whether each is met, not met, or cannot be assessed, and says which. A tool that told you your model was good would be selling you a conclusion you have to defend yourself.

Where something on this site could not be checked against a primary source, it is marked [unverified] and stays marked. Seewhat ProofPack does not do for the permanent out-of-scope list.