Skip to content
  • FDA AI-DSF lifecycle guidance: DRAFT (Jan 2025) — not for implementation
  • PCCP guidance: final (Dec 2024, updated Aug 2025)
  • FDA Statistical Guidance on diagnostic tests: final (2007)
  • Guidance map v1

Egress and --offline

ProofPack runs inside your environment and reads your table there. The table below lists every channel by which anything can leave when our code runs it (the support mailbox is the one route on it your own people operate), and the field list beside each channel is generated at build time from the engine’s own schema/egress_schema.json — vendored into this site, hashed against a provenance record, compared against the engine repository in CI. The rows are read by the same loader the trust page reads; the site’s build test parses this page’s table and holds every row to the manifest, the schema and the trust page’s rows.

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 engine's egress schema.

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.

At launch the runner makes at most one outbound call: the telemetry POST. It carries a licence id, a run id, the engine version, the platform, the manifest hash, the duration, a coarse row-count bucket and the HALT code if one fired — no column names, no counts below bucket level, no metric values, no row-level field, no free-text declaration field. Its module is not in engine 0.1.0.dev1, and the row above says so.

--offline opens zero sockets. No licence check (a licence is an Ed25519-signed file verified locally against the public key published on the trust page), no telemetry, no narrative call. doctor, map, run and compare all accept it, before or after the subcommand.

The claim is tested as: the engine’s whole test suite run with the network namespace removed (unshare -rn, fixture F19), and a continuous-integration job that runs the reference image under network capture on every release and publishes the capture summary on the trust page. Neither exists yet; both are listed as pending on the validation page, and until they are green the sentence “zero sockets” is a design commitment we have written down, not a measurement we have taken.

egress.telemetry: false in criteria.yaml switches the telemetry call off for every run without the flag.

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.

The engine’s defaults are min_n = 10, min_events = 5, min_nonevents = 5, read here from the schema; the egress.suppression block in criteria.yaml may raise them and the schema refuses a lower value. Suppression applies to egress only: a suppressed cell is still reported in your local pack, annotated with the tier it fell into.

These attribute levels are pseudonymised (Site A, Device A, Level A) before egress, with the map back written only to your machine:

site device protocol attr_*

Only canonical column names matching ^[a-z][a-z0-9_]{0,31}$ could ever be serialised, and only by the deferred narrative channel; an original header never is.

These are never serialised at all, in any channel:

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

The browser demo, when it ships, parses and analyses an uploaded file inside your browser tab under Pyodide. There is no upload endpoint. The trust page carries the browser-only statement verbatim and, once the demo exists, a screenshot of what your browser’s developer tools should show.

Before a first run on real data, check two things against the agreements that govern your test set:

  1. Derived aggregates. A ProofPack pack is a document of aggregates — counts, rates, intervals, curves — computed from the table. Confirm that your data-use agreement permits derived aggregates to be created and filed; a pack contains no row.
  2. Telemetry. The one outbound call carries no data about the table beyond a row-count bucket, but it is an outbound call from the environment the data sits in. If the agreement, or your information-security policy, does not permit it, run with --offline or set egress.telemetry: false. Nothing in the pack changes.

ProofPack does not need, and never asks for, a business associate agreement, because no protected health information reaches Global Phoenix Solutions Ltd by any channel our code operates. The one route on the table that your own people control is the support mailbox, and support asks you never to put data in it. The pricing FAQ says the same.

The trust page publishes egress_schema.json byte for byte, with the commit of the engine repository it was vendored from. Read it there: a summary of a schema is not a schema.