Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 77 additions & 2 deletions graqle/pct/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
"""Vendored OPSF PCT schema + example scenarios.
"""Vendored OPSF PCT schema + GraQle's own frozen proof spec.

The artefacts in this directory are byte-identical copies of files in
This package holds artefacts from two distinct provenances. Keeping them
straight matters: one is upstream content that must stay byte-identical, the
other is GraQle-authored and versioned on its own cadence.

=========================== ==========================================
``pct_v0_1.json``, VENDORED from ``opsf-org/pct-spec`` at
``opsf_examples/`` :data:`VENDORED_OPSF_SHA`. Byte-identical —
never edit in place; re-vendor instead.
``proof-spec/v{N.M}/``, GRAQLE-AUTHORED (CR-010.R1). The frozen proof
``conformance/`` spec + its conformance corpus. Versioned by
directory, independent of both the OPSF SHA
and the GraQle SDK version. A re-vendor must
NOT touch these.
=========================== ==========================================

The artefacts in the vendored set are byte-identical copies of files in
``opsf-org/pct-spec`` pinned to the commit SHA below. The OPSF default
branch ``develop`` is floating; the SHA pin gives reproducible builds
per sentinel pass 3 MINOR-S3 (CR-010 PR-010b-1).
Expand All @@ -20,6 +35,62 @@

from __future__ import annotations

import json
from typing import Any

#: Version of GraQle's own frozen proof spec (CR-010.R1). Deliberately
#: DECOUPLED from ``graqle.__version__``: an SDK release never implies a spec
#: change, and a spec change never forces an SDK major bump. Third parties pin
#: to this, not to the SDK version.
SPEC_VERSION: str = "1.0"

#: Schema names published at :data:`SPEC_VERSION`.
PROOF_SPEC_SCHEMAS: tuple[str, ...] = ("bundle", "keyring", "verify-result")


def proof_schema_text(name: str, version: str | None = None) -> str:
"""Return the raw JSON text of a published proof-spec schema.

Read via ``importlib.resources`` rather than ``__file__`` so the schemas
resolve correctly when the package is imported from a zipped wheel.

Parameters
----------
name:
One of :data:`PROOF_SPEC_SCHEMAS` (e.g. ``"bundle"``).
version:
Spec version directory, defaulting to :data:`SPEC_VERSION`. Pass an
explicit value to read a superseded spec.

Raises
------
FileNotFoundError
If no such schema/version is published. The message names what was
looked for, so a typo is obvious rather than silent.
"""
from importlib.resources import files

version = version or SPEC_VERSION
relative = f"proof-spec/v{version}/{name}.schema.json"
resource = files(__name__).joinpath(relative)
if not resource.is_file():
raise FileNotFoundError(
f"no proof-spec schema {name!r} at spec version {version!r} "
f"(looked for {relative}); published schemas at "
f"v{SPEC_VERSION}: {', '.join(PROOF_SPEC_SCHEMAS)}"
)
return resource.read_text(encoding="utf-8")


def load_proof_schema(name: str, version: str | None = None) -> dict[str, Any]:
"""Return a published proof-spec schema parsed as a dict.

Thin wrapper over :func:`proof_schema_text`; see it for parameters and
the raised :class:`FileNotFoundError`.
"""
return json.loads(proof_schema_text(name, version))


#: Pinned commit SHA in ``opsf-org/pct-spec`` from which the vendored
#: artefacts in this directory were fetched. Sentinel pass 3 MINOR-S3
#: fix (CR-010 PR-010b-1, 2026-05-23). Verifiable via
Expand All @@ -33,6 +104,10 @@
VENDORED_OPSF_COMMIT_MESSAGE: str = "remove banner image from README (#60)"

__all__ = [
"SPEC_VERSION",
"PROOF_SPEC_SCHEMAS",
"proof_schema_text",
"load_proof_schema",
"VENDORED_OPSF_SHA",
"VENDORED_OPSF_COMMIT_DATE",
"VENDORED_OPSF_COMMIT_MESSAGE",
Expand Down
13 changes: 13 additions & 0 deletions graqle/pct/schema/conformance/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""CR-010.R1 conformance corpus — static fixtures + declarative case manifest.

The corpus is an **interop artifact**, not a GraQle-internal test helper. Every
case is a committed static JSON file plus a declarative expectation in
``corpus-manifest.json``. A third-party verifier implementation consumes those
files over a subprocess/JSON boundary and must classify every case identically
to be called conformant — it never imports GraQle code.

See ``../proof-spec/v1.0/SPEC.md`` for the normative envelope and the
conformance procedure.
"""

from __future__ import annotations
147 changes: 147 additions & 0 deletions graqle/pct/schema/conformance/corpus-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{
"corpus_version": "1.0",
"spec_version": "1.0",
"description": "CR-010.R1 conformance corpus. Every case below MUST be classified identically by any conformant GraQle proof-bundle verifier. Expectations are empirically derived from the reference implementation, not hand-authored. A verifier that reproduces all cases is conformant at spec v1.0.",
"runner_contract": {
"invocation": "<verifier> verify <bundle> --keys <keyring> --format json",
"assert_order": [
"process exit_code",
"stdout parses as JSON and validates against ../proof-spec/v1.0/verify-result.schema.json",
"failure equals expect.failure",
"every key in expect.checks_present is present in checks",
"every key in expect.checks_absent is ABSENT from checks (absent, NOT false)"
],
"exit_codes": {
"0": "bundle verified",
"1": "bundle did not verify (a typed failure)",
"2": "usage error - unreadable or malformed input, distinct from a failed proof"
},
"absent_vs_false": "A check that did not run is ABSENT from the checks object. A check that ran and failed is present with value false (see TC-007 rekor). Treating absent as false is a conformance failure.",
"short_circuit": "Checks run in order leaf -> merkle -> signature -> rekor and the FIRST failure stops evaluation, because a later check is not meaningful once an earlier invariant is broken."
},
"cases": [
{
"id": "TC-001",
"description": "Valid bundle, trusted ACTIVE key. The happy path.",
"bundle": "fixtures/tc001_valid.json",
"keyring": "fixtures/keyring_default.json",
"expect": {
"ok": true,
"failure": "OK",
"exit_code": 0,
"checks_present": ["leaf", "merkle", "signature"],
"checks_absent": ["rekor"],
"rekor_checked": false
}
},
{
"id": "TC-002",
"description": "Malformed bundle - the required merkle block is missing. Shape validation runs before any cryptographic check, so no check key is recorded.",
"bundle": "fixtures/tc002_malformed.json",
"keyring": "fixtures/keyring_default.json",
"expect": {
"ok": false,
"failure": "MALFORMED_BUNDLE",
"exit_code": 1,
"checks_present": [],
"checks_absent": ["leaf", "merkle", "signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-003",
"description": "Tampered leaf - a leaf-committed record field (content_hash) was mutated while leaf/merkle/signature were left as signed. Leaf recompute disagrees with the stated leaf_hash.",
"bundle": "fixtures/tc003_tampered_leaf.json",
"keyring": "fixtures/keyring_default.json",
"expect": {
"ok": false,
"failure": "TAMPERED_LEAF",
"exit_code": 1,
"checks_present": [],
"checks_absent": ["leaf", "merkle", "signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-004",
"description": "Wrong root - the stated merkle_root was altered, so inclusion recompute does not reproduce it. Leaf recompute still passes and is recorded.",
"bundle": "fixtures/tc004_wrong_root.json",
"keyring": "fixtures/keyring_default.json",
"expect": {
"ok": false,
"failure": "WRONG_ROOT",
"exit_code": 1,
"checks_present": ["leaf"],
"checks_absent": ["merkle", "signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-005",
"description": "Rotated key - the bundle is untouched and internally valid, but the keyring knows only a DIFFERENT kid, so the signing kid is unknown to the trust store.",
"bundle": "fixtures/tc001_valid.json",
"keyring": "fixtures/keyring_rotated.json",
"expect": {
"ok": false,
"failure": "UNKNOWN_KID",
"exit_code": 1,
"checks_present": ["leaf", "merkle"],
"checks_absent": ["signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-006",
"description": "Revoked key - same valid bundle, but the kid is present in the keyring with lifecycle state REVOKED. Trust state alone decides the outcome.",
"bundle": "fixtures/tc001_valid.json",
"keyring": "fixtures/keyring_revoked.json",
"expect": {
"ok": false,
"failure": "UNTRUSTED_KID",
"exit_code": 1,
"checks_present": ["leaf", "merkle"],
"checks_absent": ["signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-006b",
"description": "Key outside its validity window - same valid bundle and an ACTIVE kid, but signed_at falls outside valid_from/valid_until. Distinct code path from TC-006 that must reach the same classification.",
"bundle": "fixtures/tc001_valid.json",
"keyring": "fixtures/keyring_expired.json",
"expect": {
"ok": false,
"failure": "UNTRUSTED_KID",
"exit_code": 1,
"checks_present": ["leaf", "merkle"],
"checks_absent": ["signature", "rekor"],
"rekor_checked": false
}
},
{
"id": "TC-007",
"description": "Receipt mismatch - an offline Rekor receipt is present but its signed_tree_head does not bind the bundle's merkle_root. This is the only case where a check key is present with value false rather than absent.",
"bundle": "fixtures/tc007_rekor_mismatch.json",
"keyring": "fixtures/keyring_default.json",
"expect": {
"ok": false,
"failure": "REKOR_MISMATCH",
"exit_code": 1,
"checks_present": ["leaf", "merkle", "signature", "rekor"],
"checks_absent": [],
"rekor_checked": false
}
},
{
"id": "TC-008",
"description": "Usage error - the input file is not JSON at all. The verifier cannot even attempt verification, which is distinct from a proof that fails to verify. No VerifyResult is produced: the payload is {ok:false, error:...} with no failure/checks keys, and it deliberately does NOT validate against verify-result.schema.json. The exit code is the contract here; the error message text is not normative.",
"bundle": "fixtures/tc008_not_json.txt",
"keyring": "fixtures/keyring_default.json",
"expect": {
"usage_error": true,
"exit_code": 2,
"payload_shape": { "ok": false, "has_error_field": true, "has_failure_field": false }
}
}
]
}
11 changes: 11 additions & 0 deletions graqle/pct/schema/conformance/fixtures/keyring_default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"_test_only": true,
"_warning": "CONFORMANCE TEST DATA \u2014 NOT FOR PRODUCTION. The matching private key is derived from a fixed, publicly-known seed and can be reproduced by anyone. Never add this key to a real trust store.",
"keys": [
{
"kid": "graqle-conformance-test-key",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAA6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg=\n-----END PUBLIC KEY-----\n",
"state": "ACTIVE"
}
]
}
13 changes: 13 additions & 0 deletions graqle/pct/schema/conformance/fixtures/keyring_expired.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"_test_only": true,
"_warning": "CONFORMANCE TEST DATA \u2014 NOT FOR PRODUCTION. The matching private key is derived from a fixed, publicly-known seed and can be reproduced by anyone. Never add this key to a real trust store.",
"keys": [
{
"kid": "graqle-conformance-test-key",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAA6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg=\n-----END PUBLIC KEY-----\n",
"state": "ACTIVE",
"valid_from": "2020-01-01T00:00:00Z",
"valid_until": "2020-12-31T23:59:59Z"
}
]
}
11 changes: 11 additions & 0 deletions graqle/pct/schema/conformance/fixtures/keyring_revoked.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"_test_only": true,
"_warning": "CONFORMANCE TEST DATA \u2014 NOT FOR PRODUCTION. The matching private key is derived from a fixed, publicly-known seed and can be reproduced by anyone. Never add this key to a real trust store.",
"keys": [
{
"kid": "graqle-conformance-test-key",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAA6EHv/POEL4dcN0Y50vAmWfk1jCbpQ1fHdyGZBJVMbg=\n-----END PUBLIC KEY-----\n",
"state": "REVOKED"
}
]
}
11 changes: 11 additions & 0 deletions graqle/pct/schema/conformance/fixtures/keyring_rotated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"_test_only": true,
"_warning": "CONFORMANCE TEST DATA \u2014 NOT FOR PRODUCTION. The matching private key is derived from a fixed, publicly-known seed and can be reproduced by anyone. Never add this key to a real trust store.",
"keys": [
{
"kid": "graqle-conformance-rotated-key",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAKay64UG8yvCyLhqU000LxzYeUm0L/hLIl5S8kyKWbdc=\n-----END PUBLIC KEY-----\n",
"state": "ACTIVE"
}
]
}
34 changes: 34 additions & 0 deletions graqle/pct/schema/conformance/fixtures/tc001_valid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"leaf": {
"leaf_hash": "7980bb39c78cbf14f82b8c816b0854778d331ab65821a8d6db5dba5731b5eb75",
"leaf_index": 1,
"tree_size": 4
},
"merkle": {
"merkle_path": [
"f22a101587baa042702e5d7166d5db85c271479f49027495e3556c61a32f650c",
"1a8c1704c341b9cabcc21898de4a22f353e030af49f8fe6a80c74986a57a940c"
],
"merkle_path_directions": [
0,
1
],
"merkle_root": "1ea1b958ad15d8d0511e0312feab351cd14fa839c6dbeab96f30f5b806f62e2f"
},
"proof_format_version": "1",
"record": {
"content_hash": "0000000000000000000000000000000000000000000000000000000000000001",
"governance_metadata": {
"decision": "DENY"
},
"proof_format_version": "1",
"record_id": "conformance-record-1",
"timestamp_unix": 1767225601
},
"signature": {
"alg": "ed25519",
"kid": "graqle-conformance-test-key",
"sig": "be8e60a0e9ebb7ccacae83e067f0096b855f3ec9c2f5f85ce82f5c0ac143f51b11d3afc8b9b4e9ae0cf85e7f3b234f8ed120132732f70b9f09689a21f184ca05",
"signed_at": "2026-01-01T00:00:00Z"
}
}
23 changes: 23 additions & 0 deletions graqle/pct/schema/conformance/fixtures/tc002_malformed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"leaf": {
"leaf_hash": "7980bb39c78cbf14f82b8c816b0854778d331ab65821a8d6db5dba5731b5eb75",
"leaf_index": 1,
"tree_size": 4
},
"proof_format_version": "1",
"record": {
"content_hash": "0000000000000000000000000000000000000000000000000000000000000001",
"governance_metadata": {
"decision": "DENY"
},
"proof_format_version": "1",
"record_id": "conformance-record-1",
"timestamp_unix": 1767225601
},
"signature": {
"alg": "ed25519",
"kid": "graqle-conformance-test-key",
"sig": "be8e60a0e9ebb7ccacae83e067f0096b855f3ec9c2f5f85ce82f5c0ac143f51b11d3afc8b9b4e9ae0cf85e7f3b234f8ed120132732f70b9f09689a21f184ca05",
"signed_at": "2026-01-01T00:00:00Z"
}
}
Loading
Loading