Skip to content
Draft
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
142 changes: 142 additions & 0 deletions .github/workflows/poci-cross-repo-federation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: PoCI Cross-Repository Federation

on:
push:
branches: [main]
paths:
- ".github/workflows/poci-cross-repo-federation.yml"
- "docs/POCI_CROSS_REPO_FEDERATION.md"
- "examples/poci-witness/federation/**"
- "scripts/verify_poci_cross_repo_federation.py"
- "tests/test_poci_cross_repo_federation.py"
pull_request:
paths:
- ".github/workflows/poci-cross-repo-federation.yml"
- "docs/POCI_CROSS_REPO_FEDERATION.md"
- "examples/poci-witness/federation/**"
- "scripts/verify_poci_cross_repo_federation.py"
- "tests/test_poci_cross_repo_federation.py"

concurrency:
group: poci-federation-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
actions: read
id-token: write
attestations: write

jobs:
federation:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Compile and run federation mutations
run: |
python3 -m py_compile \
scripts/verify_poci_cross_repo_federation.py \
tests/test_poci_cross_repo_federation.py
python3 -m unittest tests.test_poci_cross_repo_federation -v

- name: Verify ProofPath producer attestation
env:
GH_TOKEN: ${{ github.token }}
run: |
mkdir -p artifacts/poci/federation/attestation-results
gh attestation verify \
examples/poci-witness/federation/proofpath-attested-quorum-report.json \
--repo safal207/ProofPath \
--signer-workflow \
safal207/ProofPath/.github/workflows/poci-signed-witness-network.yml \
--source-digest 3a5dde912c44e0957204d3df733e712c596455f1 \
--signer-digest 3a5dde912c44e0957204d3df733e712c596455f1 \
--cert-oidc-issuer https://token.actions.githubusercontent.com \
--deny-self-hosted-runners \
--format json \
> artifacts/poci/federation/attestation-results/producer.json

- name: Verify Ibex external-consumer attestation
env:
GH_TOKEN: ${{ github.token }}
run: |
gh attestation verify \
examples/poci-witness/federation/ibex-external-consumer-receipt.json \
--repo safal207/ibex-agent-verification \
--signer-workflow \
safal207/ibex-agent-verification/.github/workflows/proofpath-poci-consumer.yml \
--source-digest 24efa1eadd72275bcc29f0c436e46fb508aac113 \
--signer-digest 24efa1eadd72275bcc29f0c436e46fb508aac113 \
--cert-oidc-issuer https://token.actions.githubusercontent.com \
--deny-self-hosted-runners \
--format json \
> artifacts/poci/federation/attestation-results/external-consumer.json

- name: Build cross-repository federation report
run: |
python3 scripts/verify_poci_cross_repo_federation.py \
examples/poci-witness/federation/policy.json \
--producer-report \
examples/poci-witness/federation/proofpath-attested-quorum-report.json \
--consumer-receipt \
examples/poci-witness/federation/ibex-external-consumer-receipt.json \
--producer-attestation-result \
artifacts/poci/federation/attestation-results/producer.json \
--consumer-attestation-result \
artifacts/poci/federation/attestation-results/external-consumer.json \
--pretty \
--output artifacts/poci/federation/federation-report.json

- name: Guard accepted two-domain federation
run: |
python3 - <<'PY'
import json
from pathlib import Path

report = json.loads(
Path("artifacts/poci/federation/federation-report.json").read_text(
encoding="utf-8"
)
)
if report.get("decision") != "ACCEPT" or report.get("valid") is not True:
raise SystemExit("cross-repository federation did not ACCEPT")
if report.get("domain_count") != 2:
raise SystemExit("federation must contain exactly two domains")
if report.get("external_consumer_required") is not True:
raise SystemExit("external consumer must be mandatory")
domains = report.get("domains", [])
repositories = {item.get("repository") for item in domains}
workflows = {item.get("workflow") for item in domains}
if len(repositories) != 2 or len(workflows) != 2:
raise SystemExit("repository and workflow identities must differ")
verification = report.get("verification", {})
if not verification or any(value is not True for value in verification.values()):
raise SystemExit("all federation verification flags must be true")
if len(report.get("consensus", {}).get("graph_roots", {})) != 6:
raise SystemExit("federation consensus must commit six graph roots")
root = report.get("federation_root")
if not isinstance(root, str) or not root.startswith("sha256:"):
raise SystemExit("federation root is missing")
print("PASS two-domain PoCI federation (ProofPath + Ibex)")
PY

- name: Attest final federation report
uses: actions/attest@v4
with:
subject-path: artifacts/poci/federation/federation-report.json

- name: Upload federation evidence
uses: actions/upload-artifact@v4
with:
name: poci-cross-repo-federation-${{ github.run_id }}
path: artifacts/poci/federation
if-no-files-found: error
retention-days: 14
125 changes: 125 additions & 0 deletions docs/POCI_CROSS_REPO_FEDERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# PoCI cross-repository federation v0.1

Status: executable experimental profile
Profile: `proofpath.poci.cross-repo-federation.v0.1`

## Purpose

A three-runner quorum inside ProofPath proves process and runner separation. An
Ibex consumer receipt proves that a second repository can verify the producer
attestation and independently reproduce the six-graph transition space. The
federation profile closes the loop by verifying both keyless identities and
binding their common consensus into one federation root.

```text
ProofPath three-runner quorum
↓ ProofPath Sigstore identity
Ibex external recomputation
↓ Ibex Sigstore identity
ProofPath federation verifier
two-domain federation root
```

## Required domains

Version 0.1 requires exactly two distinct repository/workflow domains:

1. **Producer domain** — the attested ProofPath quorum report.
2. **External-consumer domain** — the attested Ibex consumer receipt.

Different jobs inside one workflow do not count as different federation
domains. The repository and signer-workflow identities must both differ.

## Verified bindings

The federation verifier checks:

- exact SHA-256 bytes of the producer report and consumer receipt;
- successful keyless attestation verification for both subjects;
- pinned repository, signer workflow, source SHA, signer SHA, GitHub OIDC issuer,
and GitHub-hosted runner boundary;
- accepted producer quorum with three verified witness attestations;
- accepted external consumer receipt;
- the external receipt's own domain-separated integrity root;
- the external receipt's binding back to the exact ProofPath producer report;
- equality of round, consensus root, source digest, graph set, envelope,
six graph roots, transition-cell root, and multi-graph root.

## Decision semantics

```text
CHALLENGE > BLOCK > ACCEPT
```

- `ACCEPT` — both domains are attested and agree exactly.
- `BLOCK` — a required domain, attestation, identity, profile, or verification
flag is absent or invalid.
- `CHALLENGE` — committed bytes, roots, or consensus fields contradict each
other or the pinned policy.

Representative reason codes:

- `FEDERATION_POLICY_INVALID`
- `FEDERATION_DOMAIN_NOT_DISTINCT`
- `FEDERATION_PRODUCER_ATTESTATION_MISSING`
- `FEDERATION_CONSUMER_ATTESTATION_MISSING`
- `FEDERATION_PRODUCER_SUBJECT_MISMATCH`
- `FEDERATION_CONSUMER_SUBJECT_MISMATCH`
- `FEDERATION_PRODUCER_REPORT_INVALID`
- `FEDERATION_CONSUMER_RECEIPT_INVALID`
- `FEDERATION_CONSUMER_RECEIPT_ROOT_MISMATCH`
- `FEDERATION_PRODUCER_CONSENSUS_MISMATCH`
- `FEDERATION_CONSUMER_CONSENSUS_MISMATCH`
- `FEDERATION_CROSS_DOMAIN_MISMATCH`

## Canonical federation root

The complete federation report is copied, `federation_root` is set to `null`,
canonical JSON is encoded, and SHA-256 is computed with domain prefix:

```text
proofpath:poci:cross-repo-federation:v0.1:root\n
```

The root includes digests of the actual `gh attestation verify` result objects,
so it commits to the two provenance-verification executions as well as their
subjects.

## Mutation coverage

The focused corpus covers:

- producer subject substitution;
- external-consumer subject substitution;
- missing producer or consumer attestation;
- same-repository pseudo-federation;
- graph-root substitution;
- external receipt-root tampering;
- external workflow substitution;
- deterministic federation roots.

## Reviewer command

After obtaining both `gh attestation verify --format json` result files:

```bash
python3 scripts/verify_poci_cross_repo_federation.py \
examples/poci-witness/federation/policy.json \
--producer-report \
examples/poci-witness/federation/proofpath-attested-quorum-report.json \
--consumer-receipt \
examples/poci-witness/federation/ibex-external-consumer-receipt.json \
--producer-attestation-result producer-attestation.json \
--consumer-attestation-result consumer-attestation.json \
--pretty
```

## Honest boundary

ProofPath and Ibex now provide different repositories, commits, workflows,
runners, artifacts, and Sigstore identities. Both repositories are currently
controlled by the same GitHub account owner. This proves repository/workflow
federation and independent recomputation, not independent organizational
governance. The federation proves committed evidence consistency, not objective
real-world truth.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"profile_id": "ibex.poci.external-consumer-receipt.v0.1",
"decision": "ACCEPT",
"primary_reason_code": null,
"reason_codes": [],
"findings": [],
"consumer": {
"consumer_id": "ibex-proofpath-poci-consumer",
"repository": "safal207/ibex-agent-verification",
"workflow": "safal207/ibex-agent-verification/.github/workflows/proofpath-poci-consumer.yml",
"commit_sha": "24efa1eadd72275bcc29f0c436e46fb508aac113"
},
"producer": {
"repository": "safal207/ProofPath",
"code_sha": "a726f2a8b3bd9c6c4469be542e30bb54b230d510",
"attestation_source_sha": "3a5dde912c44e0957204d3df733e712c596455f1",
"attestation_signer_sha": "3a5dde912c44e0957204d3df733e712c596455f1",
"workflow": "safal207/ProofPath/.github/workflows/poci-signed-witness-network.yml",
"report_sha256": "sha256:87119740993bc570749542ef4e06a8cf0ce44cebd77e88eb5aa1b432d0228fde",
"attestation_result_sha256": "sha256:eac7008a5dcdfaf0e7c75eed1dfdbaffa633f61d72301818281ee7ca6a13bef0"
},
"accepted_consensus": {
"round_id": "poci-demo-round-001",
"consensus_root": "sha256:f2bc99fe96f24942e5cc9c87f25c48167d875041e85170dbb354c2bc0cd97f5f",
"source_digest": "sha256:807bde72ed45ae1566443dec20c85b02f0d6734e4aa4bf9a9cfe08ce2e4c97fa",
"graph_set_id": "mg_compute_purchase_001",
"poci_envelope_id": "env_valid_action",
"graph_roots": {
"causal": "sha256:482d5076dc3a80dac8f4ed179491b4d3e153ece780fcebdd81289ffbdc6fd7f4",
"intent": "sha256:3a26e5badd5379f69203dfe972143e0f3969b12e5f5c55cd641aa7f2bc41a0b3",
"authority": "sha256:6af348f1245a5a1f3b59b0070653bbf4d512a792e54554918058f9692e33bb0c",
"state_transition": "sha256:41807cd0bacac6908867ce6839114d3028ec62550eb7cee0fdb50006e3887c10",
"evidence": "sha256:1fed70f4f198ce5a993880e283763db8c0dc576824f042619637b37f6d745899",
"time_continuity": "sha256:4b28006fc3a21f6afce98e4e4e661fa204060be976110bed3bb571af3d7e4ccc"
},
"transition_cells_root": "sha256:b5d5fd4ba2638fb685913e621295a1c70b5aff550d14ea5b2d8c0f49bdba7f45",
"computed_multigraph_root": "sha256:98543066cb16c06b5300b56749af43b2fdd48eed47650488ac57987156e38219"
},
"verification": {
"producer_attestation_verified": true,
"producer_report_digest_verified": true,
"producer_code_sha_verified": true,
"source_recomputed": true,
"six_graph_roots_recomputed": true,
"transition_cells_recomputed": true,
"consumer_attestation_required": true
},
"honest_limitations": [
"ProofPath and Ibex use different repositories and workflow identities",
"both repositories are currently controlled by the same GitHub account owner",
"this proves evidence consistency, not objective real-world truth"
],
"receipt_root": "sha256:a810c52ebc8e313d535962b668d5eb608a4fab0e74ce9ef9ba64c313a195aa2d",
"valid": true
}
37 changes: 37 additions & 0 deletions examples/poci-witness/federation/policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"profile_id": "proofpath.poci.cross-repo-federation-policy.v0.1",
"producer": {
"repository": "safal207/ProofPath",
"workflow": "safal207/ProofPath/.github/workflows/poci-signed-witness-network.yml",
"attestation_source_sha": "3a5dde912c44e0957204d3df733e712c596455f1",
"attestation_signer_sha": "3a5dde912c44e0957204d3df733e712c596455f1",
"report_sha256": "sha256:87119740993bc570749542ef4e06a8cf0ce44cebd77e88eb5aa1b432d0228fde"
},
"external_consumer": {
"repository": "safal207/ibex-agent-verification",
"workflow": "safal207/ibex-agent-verification/.github/workflows/proofpath-poci-consumer.yml",
"attestation_source_sha": "24efa1eadd72275bcc29f0c436e46fb508aac113",
"attestation_signer_sha": "24efa1eadd72275bcc29f0c436e46fb508aac113",
"receipt_sha256": "sha256:756a893289f50221194b1e40b2e9fc2f10d5549c15fc9b9c57aa5f02c936d357",
"receipt_root": "sha256:a810c52ebc8e313d535962b668d5eb608a4fab0e74ce9ef9ba64c313a195aa2d"
},
"expected": {
"round_id": "poci-demo-round-001",
"consensus_root": "sha256:f2bc99fe96f24942e5cc9c87f25c48167d875041e85170dbb354c2bc0cd97f5f",
"source_digest": "sha256:807bde72ed45ae1566443dec20c85b02f0d6734e4aa4bf9a9cfe08ce2e4c97fa",
"graph_set_id": "mg_compute_purchase_001",
"poci_envelope_id": "env_valid_action",
"graph_roots": {
"causal": "sha256:482d5076dc3a80dac8f4ed179491b4d3e153ece780fcebdd81289ffbdc6fd7f4",
"intent": "sha256:3a26e5badd5379f69203dfe972143e0f3969b12e5f5c55cd641aa7f2bc41a0b3",
"authority": "sha256:6af348f1245a5a1f3b59b0070653bbf4d512a792e54554918058f9692e33bb0c",
"state_transition": "sha256:41807cd0bacac6908867ce6839114d3028ec62550eb7cee0fdb50006e3887c10",
"evidence": "sha256:1fed70f4f198ce5a993880e283763db8c0dc576824f042619637b37f6d745899",
"time_continuity": "sha256:4b28006fc3a21f6afce98e4e4e661fa204060be976110bed3bb571af3d7e4ccc"
},
"transition_cells_root": "sha256:b5d5fd4ba2638fb685913e621295a1c70b5aff550d14ea5b2d8c0f49bdba7f45",
"computed_multigraph_root": "sha256:98543066cb16c06b5300b56749af43b2fdd48eed47650488ac57987156e38219",
"required_domain_count": 2,
"external_consumer_required": true
}
}
Loading
Loading