PoQ Report
A PoQ Report is the durable artifact a PoQ project produces once its datapoints have received all required validator inputs. It is the thing a customer, auditor, or downstream system inspects later to answer: what was reviewed, by whom, against what criteria, and with what level of agreement.
It is produced in the Attest step of the workflow, and it is the same report regardless of how you read it — a plain-text file, a designed HTML page, the raw JSON, or the bare signature.
What it is
Every PoQ Report is one canonical JSON payload (schema poq.attestation/v1), signed once as a single Ed25519 signature. That one signed payload is then delivered in whichever format you ask for:
| Format | What you get | Best for |
|---|---|---|
Text (.txt) | A readable render followed by the signature, in one file | The default — human-readable and verifiable |
| HTML | The designed, styled report page | Sharing and reading in a browser or PDF |
| JSON | The canonical signed payload | Machine consumption |
| JWS | The bare compact signature | Verifying against your own copy of the payload |
The text and HTML formats are self-verifying: the readable content and the signature travel together in the same file, so anyone can confirm the report is authentic and unaltered offline, without calling Sapien. See Verifying a report below for how.
What a report contains
The report is organized into sections. Each one answers a specific question about how the work was validated:
| Section | Answers |
|---|---|
| Scope | Which project and how many datapoints were covered, and how much of the manifest was reviewed |
| Result | The headline Quality Rating, Consensus Strength, and label |
| Scorecard | Per-dimension quality and consensus, with rubric weights |
| Distribution | How quality and consensus scores were spread across datapoints |
| PoQ Record excerpt | A signed, per-datapoint slice showing one datapoint's full quorum and dimension detail |
| Quorum routing | The validator rounds — who reviewed, escalation targets, and where each datapoint settled |
| Configuration | The rubric and the locked poq.toml config hash |
| Pool & provenance | Validator pool size and churn, participation, credentials, and independence |
| Chain of custody | Timestamps for config lock, manifest confirmation, the review window, and issuance |
| Attestation | The attestation root, signing key, registry, and how to verify |
| What this asserts | The plain-language statement of what the report certifies |
The Validator Pool size counts every validator class eligible for the work, including agentic (AI) validators; Participation is reported separately as human and agentic counts.
What it asserts — and what it does not
The report certifies that a Validator Pool was assembled in accordance with the customer's Assurance Policy, and that a quorum drawn from it — one per datapoint — evaluated the referenced datapoints against the customer's rubric, reaching the Quality Rating and Consensus Strength shown. It covers only the datapoints enumerated in the report; datapoints added after issuance are not covered.
It is a record of how the work was validated: by whom, over what, against what criteria, and with what level of agreement.
It is not an assertion that the work is objectively correct, safe, complete, or fit for any particular purpose. The Quality Rating is relative to the rubric the customer authored.
Getting a report
Originators and admins can download a report for any project from the Portal once it has finalized data. Open the project's report page, use the report download menu, and pick a format — text, HTML, JSON, or JWS.
Verifying a report
A PoQ Report is designed to be verified offline, by anyone, without trusting Sapien at read time.
The signed payload
The report is one canonical JSON payload (schema poq.attestation/v1), signed once:
| Property | Detail |
|---|---|
| Signature | A single Ed25519 signature, delivered as a compact JWS |
| Canonicalization | The payload is canonicalized with JCS (RFC 8785) before signing, so the bytes are deterministic |
| Numerics | All numeric values are carried as strings — there are no floats in the signed bytes |
| Key id | The JWS header carries a kid identifying the signing key |
Because the signature is over the canonical bytes, any change to a covered value — in the JSON, the readable text, or the HTML — breaks verification.
The readable formats declare an envelope version so a verifier knows how to interpret the carrier before applying any grammar:
| Envelope | Carrier |
|---|---|
poq.envelope/text-v1 | The two-layer text artefact: a readable render followed by the fenced JWS |
poq.envelope/html-v1 | The designed HTML page, which embeds the text artefact and tags visible values |
In the text artefact, the readable render is followed by the compact JWS between -----BEGIN POQ SIGNED PAYLOAD----- / -----END POQ SIGNED PAYLOAD----- fences. In the HTML, the same text artefact is embedded in a <script type="application/poq-attestation+text"> element, and every visible value that comes from the payload is tagged with a data-poq attribute so it can be diffed against the signature.
poq verify
The poq binary (make poq in the server) provides an offline verifier. Point it at any text or HTML artefact:
poq verify report.html
poq verify report.txt --jwks report.jwks.json
It prints each check and a final verdict, and exits 0 when verified, 1 when a check fails, and 2 on usage errors — so it drops straight into CI. The checks are:
| Check | What it confirms |
|---|---|
envelope | The artefact declares an envelope version this build supports |
authenticity | The fenced JWS verifies against a trusted published key |
information | Parsing the readable render reproduces exactly the signed payload bytes |
presentation | Re-rendering the parsed payload reproduces the readable body byte-for-byte |
fidelity (HTML only) | Every data-poq-tagged value shown in the page matches the signed payload |
information and presentation together prove the readable layer carries exactly the signed information — no more, no less. For HTML, fidelity additionally binds every displayed value to the signature, so tampering with a visible number (for example a Quality Rating) fails verification and names the offending field.
Trusted keys
A key is trusted if it is pinned into the poq binary or supplied at verify time (--jwks path/to/keys.jwks.json for a JWKS file, or --key for a single public key).
Each deployment publishes its attestation public key as a JWKS over TLS, keyed by kid:
GET /.well-known/poq-attestation-keys.json
Fetching that endpoint over HTTPS closes the verification loop — a recipient obtains the key independently of the report and can then verify entirely offline.
Rendering a sample
poq render produces a report artefact locally in any format, writing a sidecar JWKS so you can verify it immediately:
poq render # sample report → report.html (+ report.html.jwks.json)
poq render --format txt # the text artefact instead
poq render --out - --format json # canonical payload to stdout
poq verify report.html --jwks report.html.jwks.json
--format accepts html | txt | jws | json; --out accepts a file path or - for stdout.
See also
| Page | Description |
|---|---|
| PoQ workflow | Where the report fits: Define → Validate → Attest |
| How consensus works | The mechanics behind the Quality Rating and Consensus Strength |
| Developer API - REST | The public HTTP integration surface |