PoQ Report
A PoQ Report is the durable artifact a PoQ project produces once all required validator inputs are in. It answers: what was reviewed, by whom, against what criteria, and with what level of agreement.
It is produced in the Attest step as one canonical JSON payload (schema poq.attestation/v1), signed once with Ed25519 and delivered as text, HTML, JSON, or JWS — see Formats. Text and HTML are self-verifying: content and signature travel in one file, verifiable offline.
The two headline numbers
Quality Rating is how good the quorums judged the work, on your rubric. Consensus Strength is how strongly they agreed — confidence in the rating, not a property of the work. Any label (for example Verified · customer band) is a customer-defined band over these two numbers; PoQ produces no verdict of its own.
How they're computed: How quality is measured · How consensus works.
What it asserts — and what it does not
The report certifies that a Validator Pool was assembled per your Assurance Policy, and that a quorum drawn from it — one per datapoint — evaluated the enumerated datapoints against your rubric, reaching the numbers shown. Datapoints added after issuance are not covered.
It is a record of how the work was validated — not an assertion that the work is objectively correct, safe, complete, or fit for any purpose. The Quality Rating is relative to the rubric you authored.
Getting a report
In the Portal, open the project's report page and pick a format from the download menu (originators and admins, once the project has finalized data).
Verifying a report
Anyone can verify a report offline, without trusting Sapien at read time:
Verify one right now
The panel below runs the real verifier — the same Go code as poq verify, compiled to WebAssembly — entirely in your browser. Verify the example report, then tamper with its Quality Rating and watch the fidelity check fail and name the field. You can also drop in any PoQ report of your own — it checks against Sapien's live published keys automatically.
poq CLI. Nothing you verify leaves this page; the example and your own reports alike check against Sapien’s live published keys, fetched from poq.sapien.io/.well-known.The signed payload
The payload is canonicalized with JCS (RFC 8785) before signing, so the bytes are deterministic; all numerics are carried as strings; the JWS header's kid names the signing key. Any change to a covered value — in the JSON, the text, or the HTML — breaks verification.
The readable formats declare an envelope version so a verifier knows the carrier before applying any grammar:
| Envelope | Carrier |
|---|---|
poq.envelope/text-v1 | Readable render followed by the fenced JWS |
poq.envelope/html-v1 | The designed HTML page, embedding the text artefact and tagging visible values |
In text, the compact JWS sits between -----BEGIN POQ SIGNED PAYLOAD----- / -----END POQ SIGNED PAYLOAD----- fences after the render. In HTML, the same text artefact is embedded in a <script type="application/poq-attestation+text"> element, and every payload-derived value shown on the page is tagged data-poq.
poq verify
The poq binary (make poq in the server) verifies any text or HTML artefact:
poq verify report.html
poq verify report.txt --jwks report.jwks.json
It exits 0 verified / 1 failed / 2 usage — so it drops straight into CI. The checks:
| 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; fidelity binds every displayed value to the signature — tamper with a visible number and verification fails, naming the field.
Try it on the example report:
curl -sO https://docs.sapien.io/example-report/poq-report.html
curl -s https://poq.sapien.io/.well-known/poq-attestation-keys.json -o sapien-keys.json
poq verify --jwks sapien-keys.json poq-report.html
envelope OK poq.envelope/html-v1 carrying poq.envelope/text-v1
authenticity OK Ed25519 by poq-signing-key over canonical bytes sha256:243a4aaa…
information OK parse(text) == signed payload — byte-identical
presentation OK render(parse(text)) == text
fidelity OK 28 displayed values match the signed payload
VERIFIED — the readable text provably carries exactly the signed information
Trusted keys
A key is trusted if it is pinned into the poq binary or supplied at verify time (--jwks, or --key for a single public key). Each deployment publishes its attestation key as a JWKS over TLS at /.well-known/poq-attestation-keys.json, keyed by kid. The official Sapien keys:
https://poq.sapien.io/.well-known/poq-attestation-keys.json
Fetching the key independently of the report closes the loop — after that, verification is entirely offline.
Rendering a sample
poq render produces a report artefact locally in any format, with 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. The example report on this page is exactly this output.
Reference
Formats
One signed payload, 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 |
Report sections
For the exhaustive field-by-field payload, see the PoQ Report spec.
| 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.
See also
| Page | Description |
|---|---|
| PoQ Report spec | The field-by-field reference for the report payload |
| PoQ workflow | Where the report fits: Define → Validate → Attest |
| How quality is measured | What the Quality Rating means and how to read it with Consensus Strength |
| How consensus works | How agreement is measured and how split panels escalate |
| Developer API - REST | The public HTTP integration surface |