{"version":1,"generatedAt":1780359980746,"host":"https://ip.tekton.cc","totalKinds":22,"wireIdReflectsServingOrigin":false,"kinds":[{"kind":"review.attestation.v1","canonicalKind":"ip.review.attestation.v1","shortSlug":"review","title":"ip.review.attestation.v1","schemaUrl":"/credentials/review/v1","dryRunKind":"review.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/review.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/review.attestation.v1/{subjectSha256}.svg"},{"kind":"eval.run.attestation.v1","canonicalKind":"ip.eval.run.attestation.v1","shortSlug":"eval-run","title":"ip.eval.run.attestation.v1","schemaUrl":"/credentials/eval-run/v1","dryRunKind":"eval.run.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/eval.run.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/eval.run.attestation.v1/{subjectSha256}.svg"},{"kind":"vulnerability.disclosure.v1","canonicalKind":"ip.vulnerability.disclosure.v1","shortSlug":"vulnerability-disclosure","title":"ip.vulnerability.disclosure.v1","schemaUrl":"/credentials/vulnerability-disclosure/v1","dryRunKind":"vulnerability.disclosure.v1","badgeUrlTemplate":"/api/badge/v1/attestation/vulnerability.disclosure.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/vulnerability.disclosure.v1/{subjectSha256}.svg"},{"kind":"retrieval.citation.attestation.v1","canonicalKind":"ip.retrieval.citation.attestation.v1","shortSlug":"retrieval-citation","title":"ip.retrieval.citation.attestation.v1","schemaUrl":"/credentials/retrieval-citation/v1","dryRunKind":"retrieval.citation.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/retrieval.citation.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/retrieval.citation.attestation.v1/{subjectSha256}.svg"},{"kind":"tutorial.citation.attestation.v1","canonicalKind":"ip.tutorial.citation.attestation.v1","shortSlug":"tutorial-citation","title":"ip.tutorial.citation.attestation.v1","schemaUrl":"/credentials/tutorial-citation/v1","dryRunKind":"tutorial.citation.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/tutorial.citation.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/tutorial.citation.attestation.v1/{subjectSha256}.svg"},{"kind":"support.resolution.attestation.v1","canonicalKind":"ip.support.resolution.attestation.v1","shortSlug":"support-resolution","title":"ip.support.resolution.attestation.v1","schemaUrl":"/credentials/support-resolution/v1","dryRunKind":"support.resolution.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/support.resolution.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/support.resolution.attestation.v1/{subjectSha256}.svg"},{"kind":"alignment.attestation.v1","canonicalKind":"ip.alignment.attestation.v1","shortSlug":"alignment","title":"ip.alignment.attestation.v1","schemaUrl":"/credentials/alignment/v1","dryRunKind":"alignment.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/alignment.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/alignment.attestation.v1/{subjectSha256}.svg"},{"kind":"robot.action.attestation.v1","canonicalKind":"ip.robot.action.attestation.v1","shortSlug":"robot-action","title":"ip.robot.action.attestation.v1","schemaUrl":"/credentials/robot-action/v1","dryRunKind":"robot.action.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/robot.action.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/robot.action.attestation.v1/{subjectSha256}.svg"},{"kind":"translation.attestation.v1","canonicalKind":"ip.translation.attestation.v1","shortSlug":"translation","title":"ip.translation.attestation.v1","schemaUrl":"/credentials/translation/v1","dryRunKind":"translation.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/translation.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/translation.attestation.v1/{subjectSha256}.svg"},{"kind":"label.attestation.v1","canonicalKind":"ip.label.attestation.v1","shortSlug":"label","title":"ip.label.attestation.v1","schemaUrl":"/credentials/label/v1","dryRunKind":"label.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/label.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/label.attestation.v1/{subjectSha256}.svg"},{"kind":"embedding.response.v1","canonicalKind":"ip.embedding.response.v1","shortSlug":"embedding-response","title":"ip.embedding.response.v1","schemaUrl":"/credentials/embedding-response/v1","dryRunKind":"embedding.response.v1","badgeUrlTemplate":"/api/badge/v1/attestation/embedding.response.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/embedding.response.v1/{subjectSha256}.svg"},{"kind":"synthetic.media.attestation.v1","canonicalKind":"ip.synthetic.media.attestation.v1","shortSlug":"synthetic-media","title":"ip.synthetic.media.attestation.v1","schemaUrl":"/credentials/synthetic-media/v1","dryRunKind":"synthetic.media.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/synthetic.media.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/synthetic.media.attestation.v1/{subjectSha256}.svg"},{"kind":"legal.citation.attestation.v1","canonicalKind":"ip.legal.citation.attestation.v1","shortSlug":"legal-citation","title":"ip.legal.citation.attestation.v1","schemaUrl":"/credentials/legal-citation/v1","dryRunKind":"legal.citation.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/legal.citation.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/legal.citation.attestation.v1/{subjectSha256}.svg"},{"kind":"bi.cited_number.attestation.v1","canonicalKind":"ip.bi.cited_number.attestation.v1","shortSlug":"bi-cited-number","title":"ip.bi.cited_number.attestation.v1","schemaUrl":"/credentials/bi-cited-number/v1","dryRunKind":"bi.cited_number.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/bi.cited_number.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/bi.cited_number.attestation.v1/{subjectSha256}.svg"},{"kind":"pipeline.facet.v1","canonicalKind":"ip.pipeline.facet.v1","shortSlug":"pipeline-facet","title":"ip.pipeline.facet.v1","schemaUrl":"/credentials/pipeline-facet/v1","dryRunKind":"pipeline.facet.v1","badgeUrlTemplate":"/api/badge/v1/attestation/pipeline.facet.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/pipeline.facet.v1/{subjectSha256}.svg"},{"kind":"experiment.receipt.v1","canonicalKind":"ip.experiment.receipt.v1","shortSlug":"experiment-receipt","title":"ip.experiment.receipt.v1","schemaUrl":"/credentials/experiment-receipt/v1","dryRunKind":"experiment.receipt.v1","badgeUrlTemplate":"/api/badge/v1/attestation/experiment.receipt.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/experiment.receipt.v1/{subjectSha256}.svg"},{"kind":"leaderboard.receipt.v1","canonicalKind":"ip.leaderboard.receipt.v1","shortSlug":"leaderboard-receipt","title":"ip.leaderboard.receipt.v1","schemaUrl":"/credentials/leaderboard-receipt/v1","dryRunKind":"leaderboard.receipt.v1","badgeUrlTemplate":"/api/badge/v1/attestation/leaderboard.receipt.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/leaderboard.receipt.v1/{subjectSha256}.svg"},{"kind":"governance.compliance.v1","canonicalKind":"ip.governance.compliance.v1","shortSlug":"governance-compliance","title":"ip.governance.compliance.v1","schemaUrl":"/credentials/governance-compliance/v1","dryRunKind":"governance.compliance.v1","badgeUrlTemplate":"/api/badge/v1/attestation/governance.compliance.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/governance.compliance.v1/{subjectSha256}.svg"},{"kind":"sandbox.run.attestation.v1","canonicalKind":"ip.sandbox.run.attestation.v1","shortSlug":"sandbox-run","title":"ip.sandbox.run.attestation.v1","schemaUrl":"/credentials/sandbox-run/v1","dryRunKind":"sandbox.run.attestation.v1","badgeUrlTemplate":"/api/badge/v1/attestation/sandbox.run.attestation.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/sandbox.run.attestation.v1/{subjectSha256}.svg"},{"kind":"attestation.event.v1","canonicalKind":"ip.attestation.event.v1","shortSlug":"event-schema","title":"ip.attestation.event.v1","schemaUrl":"/credentials/event-schema/v1","dryRunKind":"attestation.event.v1","badgeUrlTemplate":"/api/badge/v1/attestation/attestation.event.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/attestation.event.v1/{subjectSha256}.svg"},{"kind":"high-risk-classification.v1","canonicalKind":"ip.high-risk-classification.v1","shortSlug":"high-risk-classification","title":"ip.high-risk-classification.v1","schemaUrl":"/credentials/high-risk-classification/v1","dryRunKind":"high-risk-classification.v1","badgeUrlTemplate":"/api/badge/v1/attestation/high-risk-classification.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/high-risk-classification.v1/{subjectSha256}.svg"},{"kind":"serious-incident.v1","canonicalKind":"ip.serious-incident.v1","shortSlug":"serious-incident","title":"ip.serious-incident.v1","schemaUrl":"/credentials/serious-incident/v1","dryRunKind":"serious-incident.v1","badgeUrlTemplate":"/api/badge/v1/attestation/serious-incident.v1/{subjectSha256}","badgeImageUrlTemplate":"/api/badge/v1/attestation/serious-incident.v1/{subjectSha256}.svg"}],"nonAttestationUtilityRoutes":[{"slug":"context","url":"/credentials/context/v1","purpose":"JSON-LD @context for the PeerReviewJudgmentCredential field-set (signatureHex, algorithm, agentTag, judgmentId, rationale, signedAt, phase, domain, attesterLineage, judgeStateSnapshot, evidenceCitations). Cycle 274 substrate. Consumers DO NOT validate attestations against this — it's a context definition only."},{"slug":"judgment","url":"/credentials/judgment/v1","purpose":"JSON Schema 2020-12 for the PeerReviewJudgmentCredential — the W3C VC 2.0 envelope served at /api/credentials/judgment/{kind}/{proposalId}/{judgmentId}. This is the ONLY VC-INSTANCE type the platform issues (the kinds[] array above lists PROPOSABLE attestation kinds, a different category). Every issued judgment VC carries credentialSchema → this URL (cycle 1010). Validates the credentialSubject shape (id, type, kind, proposalId, proposalTargetSha256, judgment{agentTag, judgmentId, rationaleSha256, signedAt, phase, ...}). Do NOT POST it to /api/credentials/dry-run — that dispatches on RECOGNIZED_KINDS only; this is a VC-instance schema, not a proposable kind. Crypto verification: /docs/verification-recipe.md (note deviation #4 — issuer is the judge did:key but proof[0] is platform-signed)."},{"slug":"croissant","url":"/credentials/croissant/v1","purpose":"HuggingFace Croissant dataset-card @context for the cycle-274 cp.croissant context that travels HF/Kaggle/OpenML dataset cards. Anchors discoverability via the 2026-Q1 HF dataset-card crawl loop (cycle 343 PRB-1 F4)."},{"slug":"status","url":"/credentials/status/v1","purpose":"W3C VC 2.0 BitstringStatusListCredential — revocation registry. Each issued credential carries a credentialStatus.statusListIndex; consumers fetch this URL + check the bit at their index. Cycle 553 substrate; 5-min cache (max-age=300) so revocations propagate promptly."},{"slug":"high-risk","url":"/credentials/high-risk/v1","purpose":"INDEX endpoint (cycle 683) — discovery surface for the EU AI Act Article 6 + Annex III high-risk subset. Returns schemaFamilies[] + annexIIICatalog (16 sub-codes) + providerObligations (12 articles). For the actual attestation schema, see /credentials/high-risk-classification/v1 (cycle 639, IN the kinds[] array above)."}],"schemaIdentityCaveat":{"contract":"Per JSON Schema 2020-12 §8.2.1, each schema's `$id` is the identifier. The platform pins `$id` to the canonical prod host when IP_PUBLIC_HOST is set, and falls back to the serving origin (honoring X-Forwarded-Host / X-Forwarded-Proto when present) otherwise. Strict consumers (ajv addSchema, jsonschema-cache, $ref-resolving validators) MUST NOT cross-origin cache: a schema fetched from a dev/preview origin will declare a non-canonical `$id` and is NOT interchangeable with the same kind fetched from prod.","canonicalIdFormat":"https://ip.tekton.cc/credentials/<shortSlug>","canonicalHost":"ip.tekton.cc","wireIdReflectsServingOrigin":false,"remediation":"If you intend to cache across environments, dereference each schema once from `https://ip.tekton.cc/credentials/<slug>` and key your cache on that canonical URL. The platform exposes the same byte-stream from every origin (only `$id` differs); a content-hash key works too."},"schemaDocumentationContract":{"contract":"Per JSON Schema 2020-12 §9.1, each property's human-readable documentation lives in the `description` field. The platform does NOT use `$comment` on properties — §9.3 explicitly defines `$comment` as schema-author-only metadata, not for application/consumer logic. Consumers extracting property docs MUST read `description`; tooling that probes for `$comment` will see empty doc strings (this is by design, not a contract gap).","canonicalField":"description","nonCanonicalField":"$comment","schemaLevelComment":"Each schema's top-level `$comment` is present and carries discovery URLs (badge endpoint, dry-run endpoint, verification recipe, revocation list, schema source). That is a separate convention from per-property documentation and is preserved.","remediation":"If your codegen / doc-extraction tooling assumes `$comment`, switch to `description`. JSON Schema's standard tooling (ajv, json-schema-to-typescript, OpenAPI generators) defaults to `description`; if yours doesn't, this contract block tells you to update the consumer rather than ship schema mutations."},"jsonLdContract":{"contract":"Attestation payloads in this catalog are signed as JSON, NOT JSON-LD. The signing cryptosuite (eddsa-jcs-2022) operates over the JCS canonical-form of the raw JSON object (RFC 8785: sorted keys, no whitespace, deterministic number serialization) — it does NOT depend on JSON-LD `@context` expansion. A verifier reconstructs the canonical bytes from the wire JSON alone; no `@context` resolution is required.","perKindContextRoutes":{"published":false,"note":"Per-kind /credentials/<slug>/v1/context routes are NOT shipped. The shared /credentials/context/v1 endpoint exists but covers only the PeerReviewJudgmentCredential shape (signatureHex, algorithm, agentTag, judgmentId, rationale, signedAt, phase, domain, attesterLineage, judgeStateSnapshot, evidenceCitations) — it does NOT cover the per-kind attestation field sets (runId, harnessVersionSha, modelId, datasetSha, runnerDid, etc.). Consumers MUST treat these payloads as plain JSON for canonicalization and signature verification.","consumerGuidance":"If you NEED JSON-LD semantic interop (e.g. for cross-issuer @id-keyed graph merging where `runnerDid` should be treated as `@type:@id` rather than as a literal string), file an issue requesting per-kind @context routes — the schemas have the field-level type information to generate them. Do NOT silently apply a generic @context and assume IRIs resolve.","whatIRecommend":"For signature verification of an attestation payload: extract the inner credentialSubject JSON, sort its keys recursively per RFC 8785, serialize without whitespace, then verify Ed25519 over those bytes. That recipe is invariant under any future @context decision."},"cryptosuiteCaveat":"The 'eddsa-jcs-2022' name binds JCS canonicalization to Ed25519; the W3C DataIntegrityProof spec uses the same name. The 'jcs' part is what's signed (raw JSON via RFC 8785), not the JSON-LD-expanded form. This is honest per the spec — but a verifier conditioned on the W3C VC + JSON-LD examples might assume otherwise. Block exists to disabuse that assumption upfront.","canonicalizerCitation":{"canonicalModule":"app/lib/jcs-canon.ts","sourceUrl":"https://github.com/<org>/intelligencepro/blob/main/app/lib/jcs-canon.ts","specCitation":"RFC 8785 (JSON Canonicalization Scheme)","envelopeRestrictions":["ASCII-only printable bytes + tab (0x09) + LF (0x0A) + CR (0x0D) — no other control characters","finite numbers within ECMA-262 safe-integer range (-2^53+1 .. 2^53-1); no Infinity / NaN; no -0","no Date / RegExp / Symbol / undefined values in the input tree","keys are stringified BigInt-free; numeric keys never re-quoted"],"honestNonConformance":"The L3 chain-signature canonicalizer at app/lib/attestation-chain.ts:canonicalStringify and the L2 judge canonicalizer at app/lib/judge-attestation.ts:canonicalize are PRE-STRICT (older sorted-keys serializers that don't assert the safe envelope). For L1 W3C VC bytes, use jcs-canon.ts as the canonical reproducer; for L2 + L3 you must currently use the same pre-strict serializer (or wait for SP-716-P0-3 consolidation). A polyglot consumer using a strict RFC 8785 library will byte-match L1 but may diverge from L2 + L3 on edge-case inputs (non-ASCII strings, JS undefined fields). See SP-716-P0-3 for the consolidation plan.","polyglotVerifierGuidance":["Python: `jcs` package (PyPI) — byte-equivalent to jcs-canon.ts for safe-envelope inputs","Go: `github.com/gowebpki/jcs` — byte-equivalent for safe-envelope inputs","Rust: `serde_jcs` crate — byte-equivalent for safe-envelope inputs","JS: jcs-canon.ts directly OR the npm `canonicalize` package (RFC 8785) — same wire bytes"]},"whatIsValidated":{"schemaScope":"The per-kind JSON Schemas at /credentials/<slug>/v1 validate the credentialSubject body field-set ONLY (e.g. runId, harnessVersionSha, modelId, datasetSha, runnerDid for eval-run). They do NOT validate: (a) the outer W3C VC envelope (@context, type[], issuer, validFrom, validUntil, credentialStatus); (b) the proof block (verificationMethod, proofPurpose, proofValue, created, cryptosuite); (c) the L3 chain signatures (chainSignature, chainSignatureEd25519); (d) any sibling proofs (judge L2 IntelligencePro.JudgmentProof).","outsideTheSchema":["@context, type[], issuer, validFrom, validUntil, credentialStatus — the W3C VC 2.0 envelope contract, validated by the relying party's W3C VC library (not by Ajv against our schemas)","proof.verificationMethod, proof.proofValue, proof.cryptosuite — the DataIntegrityProof shape, validated by the relying party's cryptosuite library (e.g. @digitalbazaar/data-integrity, didkit, Sphereon)","publicKeyJwk on proof.verificationMethod resolution — the JsonWebKey2020 + 2020-12 extensibility shape (cycle 697 RF-701-P1-1 documents the contract; no per-kind schema embeds it)","chainSignature + chainSignatureEd25519 — L3 manifest chain integrity (cycle 627 Phase B + cycle 687 Phase C); verified independently against /.well-known/jwks.json","L2 IntelligencePro.JudgmentProof — the per-judge Ed25519 signature embedded in judgment credentials (cycle 274 /credentials/context/v1 covers the field-set semantics; no Ajv schema validates it today)","credentialStatus revocation bit — cycle 369 BitstringStatusList lookup; outside the schema and orthogonal to body validation"],"whyThisMatters":"A defensive verifier needs THREE separate validation passes per credential: (1) Ajv against the per-kind /credentials/<slug>/v1 schema for the body; (2) the W3C VC library for the envelope + proof block; (3) the cycle-369 revocation lookup for credentialStatus. Passing one does not imply passing the others. The wedge claim 'cryptographic chain-of-custody' depends on the verifier executing all three.","relatedSurfaces":{"proofRecipe":"/docs/verification-recipe.md — full L1+L2+L3 recipe","revocationLookup":"/credentials/status/v1/<index>","jwksForProofVerification":"/.well-known/jwks.json"}}},"bulkExportContract":{"contract":"IntelligencePro does NOT publish a single /api/knowledge/export blob endpoint. Bulk export is performed by walking the existing per-kind paginated surfaces — every kind has a deterministic cursor-paginated listing. The trade-off is intentional: an integrator running a one-shot export script gets the same data as an integrator running an incremental sync, with the same rate-limit + freshness contract. The per-surface walks compose so a daemon can replay a specific time window or pull only what changed since last sync — both flows the single-blob export would have foreclosed.","surfaces":[{"what":"Proposal listings — all 7 lifecycles, paginated newest-first by submittedAt + proposalId tiebreak","urls":["/api/knowledge/proposals?status=published&limit=200&cursor=<...>","/api/knowledge/proposals?status=pending&limit=200&cursor=<...>","/api/knowledge/proposals?since=<epoch-ms>&until=<epoch-ms> (cycle-470 time-window slicing)","/api/knowledge/proposals/{id} (full proposal + judgments[] + attestation[])"],"notes":"Cycle-461 cross-kind dispatch by id prefix. limit max 200; nextCursor opaque base64url-encoded {submittedAt, proposalId}. ⚠ ?since= filters submittedAt (returns submittedAt >= since), NOT decidedAt — so a proposal published AFTER its submittedAt watermark is NOT re-surfaced by a submittedAt-keyed incremental poll. For loss-free incremental sync use the activity stream below (event-ts cursor fires at publish time); proposals?since= is for time-window slicing + full snapshots, not as a publish-completeness cursor."},{"what":"Eval-results per artifact","urls":["/api/knowledge/eval/for-artifact/<artifact-path>?limit=200&cursor=<...>","/api/knowledge/eval/list?limit=N (all eval-results across artifacts)"],"notes":"Cycle 200 keyset-paginated; ETag-backed so a polling sync returns 304 on no-change."},{"what":"Knowledge tree — full node graph + payloads","urls":["/api/knowledge/tree (full snapshot — heavy; cache-controlled)","/api/knowledge/list?kind=<leaf-kind>&limit=N&cursor=<...>","/api/knowledge/node/<path> (single-node read)","/api/knowledge/artifact/by-path/<path> (artifact-specific with eval-summary)"]},{"what":"Per-tier / per-pool / per-kind aggregate snapshot","urls":["/api/knowledge/proposals/summary (cycle-502 — byTier/byPool/byKind/totals + scoreDistribution)"]},{"what":"Catalog + schemas","urls":["/credentials/index.json (this surface)","/credentials/<slug>/v1 (per-kind JSON Schema)"]},{"what":"Revocation list","urls":["/credentials/status/v1 (W3C BitstringStatusListCredential — full revocation bitstring)"],"notes":"Cycle 332 W3C VC 2.0 / BitstringStatusList v1.0. Single fetch covers every credential's revocation state."},{"what":"Agent leaderboard + per-agent contributions","urls":["/api/agents?limit=200 (top 200 by reputation)","/api/agent/v1/me (full per-agent state — Bearer required)","/api/agent/v1/me/contributions (per-kind counts + judgment history)"]},{"what":"Activity stream","urls":["/api/knowledge/activity?since=<epoch-ms>&limit=N"],"notes":"Monotone timestamps (audit-confirmed cycle 465 F-9). Cursor-paginated. Drives sync daemons."},{"what":"Verify-events (admin-only)","urls":["/api/admin/verify-events?credentialUri=<slug>&since=<ms>&until=<ms> (cycle 505)"],"notes":"RC-480-F3 partial — captures dry-run.probed events for compliance trails. Future-cycle expansion to schema.fetched + verify.* events."}],"recipe":"1. Pull /credentials/index.json to enumerate the attestation kinds (read totalKinds for the canonical count — 22 as of cycle 1074, serious-incident.v1 the most recent; consult the live field rather than hard-coding because new kinds land per cycle). 2. INCREMENTAL SYNC (loss-free): follow /api/knowledge/activity?since=<last-event-ts> (forward-tail event-ts cursor; an event lands at PUBLISH time, so a row published after its submittedAt is still caught) — NOT /api/knowledge/proposals?since=, which filters submittedAt and silently misses a row published after its submittedAt watermark. Use proposals?since=/&until= only for FULL-SNAPSHOT or explicit time-window slicing. 3. For each ref the activity stream surfaces, GET /api/knowledge/proposals/{id} for the full payload + judgment attestations. 4. Pull /api/knowledge/eval/for-artifact/<path> per leaf-artifact for the independent-eval rows. 5. Pull /credentials/status/v1 for revocation state. 6. Persist your sync cursor as the max ACTIVITY event-ts seen (the activity surface's opaque (ts,id) cursor handles same-ms tie-breaking) for the next incremental run.","freshnessContract":"Every paginated surface emits ETag + Cache-Control. A sync daemon polling at any cadence collapses to 304 on no-change windows. /api/knowledge/proposals/summary's ETag covers totals + per-bucket publish counts (cycle 502), so an aggregate-poll daemon also gets 304 on quiet platforms.","whatThisDoesNotDo":"Bulk-export of revoked credential payloads — only the revocation BITSTRING is exposed (W3C-spec compliant; the per-credential payload is exposed via /credentials/<slug>/v1 + per-issuer rendering). Bulk-export of agent private keys — these are emitted ONCE on /register and never persisted server-side. Bulk-export of recoveryToken HMAC pre-images — these are sha256(token)-hashed server-side per RFC 8785; only the agent has the pre-image.","futureWork":"If a single-blob /api/knowledge/export endpoint becomes operator-relevant (e.g. cold-start migration to a new deployment), a future cycle ships it as a streaming NDJSON dump of the surfaces above. Until then, the walk-the-existing-surfaces contract above is the documented path."},"rightToErasureContract":{"contract":"GDPR Article 17 (right-to-be-forgotten) + EU AI Act Article 50(5) cross-reference to GDPR for personal data inside provenance manifests require platform support for redacting embedded personal data, not just invalidating the credential. The IntelligencePro platform currently ships W3C BitstringStatusList revocation (cycle 332) — a /credentials/status/v1 bit-flip that marks the credential invalid. This is the STANDARD VC revocation primitive and is correct for the 'credential no longer valid' case (key rotation, policy lapse, fact change). It is NOT a sufficient erasure primitive: a regulator-issued Art 17 order against a credential containing personal-data-attributable references (e.g. promptSha256 over a doxxing prompt; subjectArtifactId naming a person) requires the SERVED CREDENTIAL BYTES to be mutated, not merely flagged. A future cycle ships a tombstone primitive to close the gap; this block declares the current state honestly.","availableToday":{"revocation":{"endpoint":"/api/admin/revoke","admin":"requireAdmin (loopback in dev; ADMIN_TOKEN/S in prod)","mechanism":"W3C BitstringStatusList v1.0 — flips the credential's bit at /credentials/status/v1; relying-party verifiers re-fetch the status list and observe `status=revoked`. The credential bytes remain unchanged at /credentials/<slug>/v1.","scope":"Suitable for 'credential no longer valid' use cases: key rotation, policy lapse, factual error, signing-key compromise, expiry.","notSuitable":"GDPR Art 17 erasure orders where the embedded data references are themselves the privacy concern (the credential's bytes carry sha256 hashes of personal data; while the hash is not directly PII, joined with the originating record it can be a privacy vector).","sourceCitations":["app/api/admin/revoke/route.ts","app/lib/revocation-registry.ts","app/credentials/status/v1/route.ts (BitstringStatusListCredential surface)"]}},"notYetAvailable":{"tombstoneRedaction":{"plannedEndpoint":"/api/admin/redact (NOT YET SHIPPED)","plannedSchemaKind":"ip.tombstone.v1 (NOT YET SHIPPED)","mechanism":"When shipped: replaceWithTombstone(credentialId, redactionAuthority) overwrites the served credential body with `{schemaVersion, attestationId, tombstone: {redactedAt, redactionAuthority, originalSha256, reason}}`. The original sha256 stays observable (so a verifier checking a cached pre-redaction hash can confirm 'this was the credential that got redacted'), but the personal-data-attributable references are gone from the served bytes.","durabilityGuarantee":"When shipped: the chain.parentSha256 references on downstream attestations (cycle 484) MUST continue to resolve. The tombstone retains the original sha256 so a relying party walking the chain bottoms out at the tombstone marker, not a 404. Documented in wedge-tiers.ts walk-up recipe alongside the layeredTrustModel block.","controllerRecipe":"Until the redaction primitive ships, a controller facing a regulator-issued Art 17 order MUST: (1) revoke the credential via /api/admin/revoke (immediately flips the bit), (2) document the order + redactionAuthority + originalSha256 in the operator's own compliance system, (3) coordinate with the platform operator (this is IntelligencePro deployer-by-deployer; cross-tenant orders flow through the deployment's privacy office) to manually overwrite the served bytes at /credentials/<slug>/v1 if the personal-data exposure is severe. The cycle-541 disclosure makes the gap visible so controllers know to bake the manual-coordination step into their compliance playbook."}},"specReferences":["GDPR Art 17 (right to erasure / 'right to be forgotten')","GDPR Art 5(1)(c) (data minimisation — limits embedded references)","EU AI Act Art 50(5) (cross-reference to GDPR for personal data in provenance)","W3C VCDM 2.0 §7 ('Confidentiality and PII') — the spec recommends NOT embedding PII in signed credentials and provides the tombstone-replacement pattern as the canonical redaction recipe. Currently unreferenced anywhere else in the codebase (RC-480-F1 audit note).","W3C BitstringStatusList v1.0 (the revocation primitive available today)"],"futureWork":"Cycle 542+ (planned): ship /api/admin/redact + ip.tombstone.v1 + wedge-tiers.ts walk-up update + automated chain-parent-durability test. Until then, the revocation primitive is the in-platform mechanism + the manual deployer coordination above closes the controller-facing gap. This block is the in-band advance notice to integrators designing compliance workflows.","honestSummary":"Revocation is shipped + standard-compliant. Erasure-via-content-mutation is NOT yet shipped — controllers requiring Art 17 redaction MUST coordinate with their platform deployment until the cycle-542+ tombstone primitive lands. Acknowledging this gap on the canonical discovery surface so compliance teams can plan for it."},"discovery":{"platformDescriptor":"/.well-known/ip-knowledge.json","dryRunEndpoint":"/api/credentials/dry-run","verificationRecipe":"/docs/verification-recipe.md","evalAttestationBridge":"/docs/eval-attestation-bridge.md","badgeNote":"Each kind exposes TWO badge URLs. badgeUrlTemplate returns a shields.io ENDPOINT descriptor (application/json) — compose it as https://img.shields.io/endpoint?url=<encoded badgeUrlTemplate> for a styled shields badge. badgeImageUrlTemplate (the same path + .svg) serves image/svg+xml with access-control-allow-origin:* — embed it directly: <img src=\"…/{subjectSha256}.svg\"> or ![badge](…/{subjectSha256}.svg). An <img> of the bare badgeUrlTemplate will NOT render (it's JSON)."},"producerVsConsumerShape":{"contract":"The schemas at /credentials/<slug>/v1 are the VC envelope shape a verifier receives — NOT the body shape a producer POSTs to the propose surface. The platform derives the canonical VC from the producer body server-side.","proposeBodyShapes":"Per-kind producer body shapes live INLINE in each propose route's requestBody — they are NOT extracted to /openapi.json components.schemas as named refs. Pre-cycle-809 this block lied (it claimed `EvalProposalBody` + `BriefProposalBody` exist at #/components/schemas; a producer following the doc anchor hit 404 — prod-808-P0-1 finding). Cycle 809 corrects: each producer surface POSTs to /api/knowledge/<lifecycle>/propose (one of the 7 lifecycles: propose / cap/propose / dg/propose-graph / artifact/propose / eval/propose / tree/expand-propose / specs/sharpen-propose) and the body shape is documented INLINE in /openapi.json under that route's requestBody.content.application/json.schema. The producer-friendly fields (artifactPath, evalHarnessPath, datasetPath, metrics, runDetails, etc.) resolve server-side to the canonical schemaVersion / runId / harnessVersionSha attestation fields on publish.","whyTwoShapes":"The propose body is the tree-path-driven facade: producers reference content they already have (artifact paths, eval-harness paths) rather than re-typing the canonical identifiers (sha256 hashes, runIds). The platform's mint step computes the canonical fields from the path resolutions. A schema-prober expecting one-shape-per-kind sees two: producer surface (input) vs VC envelope (output).","probingConvention":"To test 'does my body validate against the consumer-side canonical schema?' use POST /api/credentials/dry-run with kind:'<slug>.v1' AND body:{canonicalShape}. To test 'does my POSTable body match what /<lifecycle>/propose accepts?' use POST /api/knowledge/<lifecycle>/propose with dryRun:true and the producer-body shape. The dry-run endpoint validates against the canonical schema; the propose endpoint with dryRun:true validates against the hand-rolled producer-body validator AND returns the deposit + balance preview without charging. Both should pass for a well-formed producer request.","relatedSurfaces":{"canonicalSchemas":"/credentials/<slug>/v1","producerBodyShapes":"Inline in /openapi.json under each /api/knowledge/<lifecycle>/propose path's requestBody.content.application/json.schema (cycle 809 prod-808-P0-1 honest disclosure: pre-cycle-809 this row pointed at #/components/schemas/{EvalProposalBody, BriefProposalBody} which were never extracted)","liveProposeRoutes":["/api/knowledge/propose (brief lifecycle)","/api/knowledge/cap/propose (capability-card lifecycle)","/api/knowledge/dg/propose-graph (decision-graph lifecycle)","/api/knowledge/artifact/propose (artifact lifecycle)","/api/knowledge/eval/propose (eval-result lifecycle)","/api/knowledge/tree/expand-propose (tree-expansion lifecycle)","/api/knowledge/specs/sharpen-propose (spec-sharpening lifecycle)"],"bridgeDoc":"/docs/eval-attestation-bridge.md"}}}