Translation pending — read in English.
Voir la référence API →Translation pending — read in English.
Translation pending — read in English.
Translation pending — read in English.
Translation pending — read in English.
| Translation pending — read in English. | Translation pending — read in English. | Translation pending — read in English. |
|---|---|---|
| public.compliance:read | Read the VTR record metadata and the canonical pack hash for verification. | None — required. |
Translation pending — read in English.
bash
┌──────────────────┐ ┌────────────────────┐
│ candidate uploads│ ──▶ │ your verifier UI │
│ VTR pack to you │ │ extracts pack hash │
└──────────────────┘ └─────────┬──────────┘
│
▼
┌────────────────────────┐
│ GET compliance record │
│ by VTR ID │
└───────────┬────────────┘
│
▼
┌────────────────────────┐
│ compare published hash │
│ vs uploaded pack hash │
└───────────┬────────────┘
│
▼
┌────────────────────────┐
│ return ✓ / ✗ to your │
│ verifier UI │
└────────────────────────┘Translation pending — read in English.
Translation pending — read in English.
bash
# Fetch the published VTR metadata curl "https://api.gaflight.io/api/v1/public/compliance?type=vtr&vtrId=vtr_01HZ..." \ -H "Authorization: Bearer gaf_pk_<token>" \ -H "X-Org-Id: <issuing-org-uuid>"
Translation pending — read in English.
js
// Pseudo-code — compare uploaded pack vs published hash.
import { createHash } from "node:crypto";
export async function verifyVtr(uploadedPackBytes, vtrId, issuingOrgId) {
const published = await fetchVtrMetadata(vtrId, issuingOrgId);
if (!published || published.revoked) return { ok: false, reason: "revoked-or-missing" };
const localHash = "sha256:" + createHash("sha256").update(uploadedPackBytes).digest("hex");
if (localHash !== published.canonicalPackHash) {
return { ok: false, reason: "hash-mismatch" };
}
return { ok: true, issuedAt: published.issuedAt, candidate: published.subject };
}Translation pending — read in English.
js
// In the verifier UI, echo only the fields the candidate authorised: // candidate name, issuing org, issued-at, pack hash, and the result. // Do NOT echo deep training history fields — those live in the pack // and only the candidate decides who reads them.
Translation pending — read in English.
- VTR scope-token expiry: scope tokens are short-lived; refresh ahead of long verifier sessions.
- Revoked VTRs: the metadata response includes a revoked_at field; treat any non-null value as ✗.
- Multi-page packs: the canonical hash covers the whole pack; partial uploads cannot verify.
- Pack-format version drift: refer to docs/superpowers/specs/2026-...-canonical-pack-format-spec.md for the format contract; reject unknown versions rather than guess.
- Candidate consent boundary: never echo more fields than the candidate explicitly authorised in the upload step.
- Re-verification: caching the hash result is fine; cache the metadata response only as long as your worst-case revocation latency tolerates.
- Cross-issuer corroboration: this recipe verifies a single pack — corroborating signoffs against a separate authority is a separate flow.
Translation pending — read in English.
- Declare the single scope above on your developer app with a ≥40-char justification.
- Stand up your verifier UI and pack-hashing service BEFORE submitting your listing.
- Submit your listing for review (see /developers/review-policy).
- Publish under your org and share the install URL with verifier-customer organizations (CAAs, employers, ATOs).
- Document your privacy posture explicitly — verifier UIs handle candidate PII.
Translation pending — read in English.
Translation pending — read in English.