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.
| Channel | When | Fields (exhaustive) | Limits and suppression | Exists today? |
|---|---|---|---|---|
| Demo — upload | never | — | No 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 — event | on run completion, unless opted out |
| 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 check | never (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 — telemetry | run end; skipped entirely with `--offline` or `egress.telemetry: false` |
Generated from | 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 exists | — | If 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 |
| 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 ProofPack | when you start a checkout or ask for a quote |
| 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 headersrow-level valuesjustificationdescriptionsourceraw 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.
| Assurance | Status | What we will do |
|---|---|---|
| SOC 2 | Not held | Not planned for year one. It costs money we do not have until customers are paying. |
| ISO 27001 | Not held | Not planned for year one, for the same reason. |
| Cyber Essentials | Not held | We will start it the first time a customer's procurement requires it, and publish the date we started on this page. |
| Third-party penetration test | Not done | None 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 CI | Not running | A 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 release | Not produced | Specified, not yet generated. |
| Professional indemnity or cyber insurance | Not held | Not held today. Ask before you rely on it. |
| Legal texts reviewed by a solicitor | Not reviewed | Our 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 wording | Not done | No 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 agreement | Not applicable | No 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-processor | Purpose | Region | In use today? |
|---|---|---|---|
| Cloudflare | Site hosting and the five dynamic endpoints | Global edge | No account exists yet — the site is not deployed. |
| Stripe | Payments, invoicing and sales tax | United States / European Union | No account connected yet; the commerce code runs against a local mock. |
| Supabase | Database for licences, orders and quote PDFs | To be confirmed when the project is created | No project exists yet. |
| Resend | Transactional email: licence file, quote, receipts | To be confirmed | No account exists yet. |
| GitHub | Source control, CI and release artefacts | United States | In use. |
| jsDelivr | Pyodide runtime for the in-browser demo only | Global edge | Not in use — the demo is not built. |
| Anthropic | Optional runner narrative (deferred past version 1.0) and, when it is built, the tier-one support answerer | United States | Not 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 arrives | To be confirmed from the Workspace configuration | In 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
| What | Kept for |
|---|---|
| Anything you put into the demo | Nothing is kept. It never leaves your browser tab, and closing the tab discards it. |
| Site events | 13 months, aggregate only. Nothing is collected today. |
| Runner telemetry | Manifest hashes for 24 months. Nothing is collected today. |
| Order, licence and quote records | As long as the commercial relationship and our statutory record-keeping require, per our terms. |
| Support email | In 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.