Skip to content
Open
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
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,33 @@ jobs:
curl -fsS http://127.0.0.1:8877/data/reality_cases.json | grep -q "async-rithmic-53"
kill "$(cat /tmp/counterproof-demo.pid)"


external-measurement-capsule-replay:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install CounterProof
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Fetch pinned CSOAI claim-watch capsule batch
run: |
curl -fsSL --retry 3 --retry-delay 1 \
-o /tmp/csoai-claim-watch-capsules.jsonl.gz \
https://raw.githubusercontent.com/CSOAI-ORG/councilof-ai/85df6bc2ed76450c171d6982bfd39e94d80982d2/public/measurement-capsules/v0.2/claim_watch/capsules.jsonl.gz

- name: Independently replay public capsule ids and Merkle root
run: |
python scripts/interop/replay_csoai_claim_watch.py \
/tmp/csoai-claim-watch-capsules.jsonl.gz


validate-example-skills:
runs-on: ubuntu-latest
steps:
Expand Down
27 changes: 27 additions & 0 deletions docs/interop/CSOAI_CLAIM_WATCH_REPLAY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# CSOAI claim_watch external Merkle replay

CounterProof pins one public external batch from:

- repository: `CSOAI-ORG/councilof-ai`
- commit: `85df6bc2ed76450c171d6982bfd39e94d80982d2`
- path: `public/measurement-capsules/v0.2/claim_watch/leaves.json`

The published batch contains one capsule id:

`007b0e5ccbb3f86ac587d645dd8df74c689765267eadc09736eb58bf8be95314`

Applying the draft's RFC 6962/9162 leaf rule:

`SHA-256(0x00 || capsule_id_bytes)`

reproduces the published Merkle root:

`5e6440b6f9fbccdc2dca66aff3c79c02f649ccb56cd795d0f043b651dd50c32e`

This is a **real external Merkle replay**, not a synthetic fixture.

It is still only a partial result. The gzip capsule bytes are published in the
same upstream directory, but the current connector cannot decode binary
repository content. Until CounterProof recomputes the capsule id from those
published capsule bytes, it must not claim the Measurement Capsule draft's full
independent-batch-reproduction success condition.
53 changes: 53 additions & 0 deletions docs/interop/MEASUREMENT_CAPSULE_INDEPENDENT_VERIFIER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Independent SCITT Measurement Capsule verifier

Status: experimental.

This module implements the identifier and batch-integrity parts of
`draft-templeman-scitt-measurement-capsule-00` from the public text.

It does **not** import or call the CSOAI prototype builder/verifier.

Implemented:

- RFC 8785 JCS canonicalization using the independent Trail of Bits
`rfc8785` package;
- `capsule_id = SHA-256(JCS(capsule without capsule_id))`;
- exact-JCS stored-line verification;
- draft Section 7.1 no-decision/no-authority surface checks;
- digest-only `sources` admission;
- preservation of `UNCHECKABLE` as a measurement state;
- RFC 9162 Merkle Tree Hash using:
- leaf hash `SHA-256(0x00 || capsule_id_bytes)`;
- node hash `SHA-256(0x01 || left || right)`;
- capsule ids sorted in ascending byte order;
- duplicate refusal;
- expected root/count verification for a published batch.

Not implemented:

- COSE_Sign1;
- SCITT Transparency Service registration/Receipt verification;
- OpenTimestamps or Rekor verification;
- measurement-instrument correctness;
- CSOAI-specific per-kind semantic vocabularies beyond the generic draft rules.

## External experiment target

The draft's Section 13 defines a success outcome where an implementation by
another party, written from the text, recomputes identifiers and roots of a
published batch.

This verifier is intended to attempt exactly that outcome.

At the time this code was added, the public draft/index were readable but the
raw `capsules.jsonl.gz` / `leaves.json` batch bytes were not retrievable
through the current automation environment. Therefore this repository must not
claim the Section 13 outcome until a real published batch is supplied and the
root matches.

## Claim boundary

A successful Merkle recomputation proves only that the supplied capsule bytes
bind to the supplied root under the draft algorithm. It does not prove that the
measurements are true, independent, unbiased, authorised, or endorsed by SCITT
or the IETF.
17 changes: 17 additions & 0 deletions examples/interop/csoai-claim-watch-leaves-2026-10-01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"source_repository": "CSOAI-ORG/councilof-ai",
"source_commit": "85df6bc2ed76450c171d6982bfd39e94d80982d2",
"source_path": "public/measurement-capsules/v0.2/claim_watch/leaves.json",
"batch": "claim_watch",
"kind": "measurement.claim_watch",
"n": 1,
"leaves": [
"007b0e5ccbb3f86ac587d645dd8df74c689765267eadc09736eb58bf8be95314"
],
"expected_merkle_root": "5e6440b6f9fbccdc2dca66aff3c79c02f649ccb56cd795d0f043b651dd50c32e",
"claim_boundary": [
"This fixture pins public CSOAI leaf/root data.",
"Matching this root does not prove the capsule_id was independently recomputed from capsule bytes.",
"Full draft experiment success still requires replay of the published capsule bytes."
]
}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies = [
"click>=8.1",
"rich>=13.0",
"pydantic>=2.0",
"rfc8785>=0.1.4",
]

[project.urls]
Expand Down
55 changes: 55 additions & 0 deletions scripts/interop/replay_csoai_claim_watch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Replay one pinned public CSOAI Measurement Capsule batch.

This script is intentionally small and network-agnostic: CI fetches the exact
commit-pinned gzip bytes, this script verifies the bytes and draft-level
identifier/root semantics.

It does not claim CSOAI or IETF endorsement.
"""

from __future__ import annotations

import argparse
import gzip
import hashlib
from pathlib import Path

from skill_factory.evolution.measurement_capsule_verify import verify_jsonl_batch


EXPECTED_GZIP_SHA256 = "70451eda2d8166b9a61084f5c01b8ff57210a7016d97ab0320b4c730f2b827ed"
EXPECTED_ROOT = "5e6440b6f9fbccdc2dca66aff3c79c02f649ccb56cd795d0f043b651dd50c32e"
EXPECTED_COUNT = 1


def replay(path: Path) -> None:
raw = path.read_bytes()
digest = hashlib.sha256(raw).hexdigest()
if digest != EXPECTED_GZIP_SHA256:
raise SystemExit(
f"gzip sha256 mismatch: got={digest} expected={EXPECTED_GZIP_SHA256}"
)

data = gzip.decompress(raw)
lines = data.splitlines(keepends=True)
result = verify_jsonl_batch(
lines,
expected_merkle_root=EXPECTED_ROOT,
expected_n_capsules=EXPECTED_COUNT,
)

print("CSOAI claim_watch replay: PASS")
print(f"capsules={result.n_capsules}")
print(f"merkle_root={result.merkle_root}")
print(f"capsule_id={result.capsule_ids[0]}")


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("capsules_gz", type=Path)
args = parser.parse_args()
replay(args.capsules_gz)


if __name__ == "__main__":
main()
Loading
Loading