fkyh 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fkyh-0.1.0/.github/workflows/ci.yml +376 -0
- fkyh-0.1.0/ATTESTATION.md +944 -0
- fkyh-0.1.0/CONTRIBUTING.md +635 -0
- fkyh-0.1.0/LICENSE +202 -0
- fkyh-0.1.0/MANIFEST.in +58 -0
- fkyh-0.1.0/PKG-INFO +485 -0
- fkyh-0.1.0/PLAN.md +247 -0
- fkyh-0.1.0/PROVE-IT.md +469 -0
- fkyh-0.1.0/README.md +457 -0
- fkyh-0.1.0/ROADMAP.md +245 -0
- fkyh-0.1.0/SECURITY.md +390 -0
- fkyh-0.1.0/SPEC.md +1327 -0
- fkyh-0.1.0/STATUS.md +268 -0
- fkyh-0.1.0/audit/workerA.md +268 -0
- fkyh-0.1.0/audit/workerB.md +459 -0
- fkyh-0.1.0/audit/workerC.md +622 -0
- fkyh-0.1.0/audit/workerD.md +712 -0
- fkyh-0.1.0/audit/workerE.md +824 -0
- fkyh-0.1.0/audit/workerF.md +946 -0
- fkyh-0.1.0/audit/workerG.md +1042 -0
- fkyh-0.1.0/audit/workerH.md +818 -0
- fkyh-0.1.0/contracts/fkyh-registry/.cargo/config.toml +6 -0
- fkyh-0.1.0/contracts/fkyh-registry/Cargo.lock +2120 -0
- fkyh-0.1.0/contracts/fkyh-registry/Cargo.toml +15 -0
- fkyh-0.1.0/contracts/fkyh-registry/src/lib.rs +558 -0
- fkyh-0.1.0/contracts/fkyh-registry/src/test.rs +569 -0
- fkyh-0.1.0/examples/attestation-consumer-go/README.md +132 -0
- fkyh-0.1.0/examples/attestation-consumer-go/attestation/consumer.go +648 -0
- fkyh-0.1.0/examples/attestation-consumer-go/attestation/consumer_test.go +337 -0
- fkyh-0.1.0/examples/attestation-consumer-go/attestation/jcs.go +215 -0
- fkyh-0.1.0/examples/attestation-consumer-go/go.mod +3 -0
- fkyh-0.1.0/examples/attestation-consumer-go/main.go +203 -0
- fkyh-0.1.0/examples/fk-yh-node/README.md +125 -0
- fkyh-0.1.0/examples/fk-yh-node/node.py +260 -0
- fkyh-0.1.0/examples/fk-yh-node/run_demo.sh +51 -0
- fkyh-0.1.0/examples/fk-yh-node/run_independent_loop.sh +101 -0
- fkyh-0.1.0/examples/fk-yh-node/verifier.py +155 -0
- fkyh-0.1.0/examples/go-reference/README.md +102 -0
- fkyh-0.1.0/examples/go-reference/build_oracle.sh +34 -0
- fkyh-0.1.0/examples/go-reference/go.mod +3 -0
- fkyh-0.1.0/examples/go-reference/main.go +227 -0
- fkyh-0.1.0/examples/go-reference/oracle.go +213 -0
- fkyh-0.1.0/examples/grafana/README.md +168 -0
- fkyh-0.1.0/examples/grafana/dashboard.json +842 -0
- fkyh-0.1.0/examples/grafana/docker-compose.yml +98 -0
- fkyh-0.1.0/examples/grafana/prometheus.yml +37 -0
- fkyh-0.1.0/examples/grafana/provisioning/dashboards/fkyh.yaml +26 -0
- fkyh-0.1.0/examples/grafana/provisioning/datasources/fkyh-prometheus.yaml +27 -0
- fkyh-0.1.0/examples/hello-world.py +123 -0
- fkyh-0.1.0/examples/independent-consumer/README.md +109 -0
- fkyh-0.1.0/examples/independent-consumer/run_conformance.py +79 -0
- fkyh-0.1.0/examples/independent-consumer/thirdparty_consumer.py +371 -0
- fkyh-0.1.0/fixtures/ORACLES.json +191 -0
- fkyh-0.1.0/fixtures/attestations/MANIFEST-COVERAGE.md +48 -0
- fkyh-0.1.0/fixtures/attestations/README.md +178 -0
- fkyh-0.1.0/fixtures/attestations/TEST-ONLY-README.md +11 -0
- fkyh-0.1.0/fixtures/attestations/TEST-ONLY-private-key.hex +1 -0
- fkyh-0.1.0/fixtures/attestations/TEST-ONLY-revoked-private-key.hex +1 -0
- fkyh-0.1.0/fixtures/attestations/evidence/payments.conf +2 -0
- fkyh-0.1.0/fixtures/attestations/evidence-digest-mismatch.json +22 -0
- fkyh-0.1.0/fixtures/attestations/evidence-missing.json +22 -0
- fkyh-0.1.0/fixtures/attestations/evidence-no-digest.json +21 -0
- fkyh-0.1.0/fixtures/attestations/evidence-null-digest.json +22 -0
- fkyh-0.1.0/fixtures/attestations/evidence-unreadable.json +22 -0
- fkyh-0.1.0/fixtures/attestations/expired.json +22 -0
- fkyh-0.1.0/fixtures/attestations/manifest.json +162 -0
- fkyh-0.1.0/fixtures/attestations/missing-signature.json +21 -0
- fkyh-0.1.0/fixtures/attestations/not-yet-valid.json +22 -0
- fkyh-0.1.0/fixtures/attestations/revoked-verifier.json +22 -0
- fkyh-0.1.0/fixtures/attestations/section-4-3-worked-example.json +22 -0
- fkyh-0.1.0/fixtures/attestations/tampered.json +22 -0
- fkyh-0.1.0/fixtures/attestations/trust.json +21 -0
- fkyh-0.1.0/fixtures/attestations/unauthorized-policy.json +22 -0
- fkyh-0.1.0/fixtures/attestations/unauthorized-verifier.json +22 -0
- fkyh-0.1.0/fixtures/attestations/unsupported-version.json +22 -0
- fkyh-0.1.0/fixtures/attestations/valid-failed.json +22 -0
- fkyh-0.1.0/fixtures/attestations/valid-inconclusive.json +16 -0
- fkyh-0.1.0/fixtures/attestations/valid-verified.json +22 -0
- fkyh-0.1.0/fixtures/attestations/wrong-attempt.json +22 -0
- fkyh-0.1.0/fixtures/attestations/wrong-task.json +22 -0
- fkyh-0.1.0/fixtures/executor/conformance.json +121 -0
- fkyh-0.1.0/fixtures/jcs/input/arrays.json +8 -0
- fkyh-0.1.0/fixtures/jcs/input/french.json +6 -0
- fkyh-0.1.0/fixtures/jcs/input/structures.json +8 -0
- fkyh-0.1.0/fixtures/jcs/input/unicode.json +3 -0
- fkyh-0.1.0/fixtures/jcs/input/values.json +5 -0
- fkyh-0.1.0/fixtures/jcs/input/weird.json +11 -0
- fkyh-0.1.0/fixtures/jcs/output/arrays.json +1 -0
- fkyh-0.1.0/fixtures/jcs/output/french.json +1 -0
- fkyh-0.1.0/fixtures/jcs/output/structures.json +1 -0
- fkyh-0.1.0/fixtures/jcs/output/unicode.json +1 -0
- fkyh-0.1.0/fixtures/jcs/output/values.json +1 -0
- fkyh-0.1.0/fixtures/jcs/output/weird.json +1 -0
- fkyh-0.1.0/fixtures/rfc/rfc8259.txt +899 -0
- fkyh-0.1.0/fixtures/rfc/rfc8785.txt +984 -0
- fkyh-0.1.0/fixtures/stellar/caip-2.md +111 -0
- fkyh-0.1.0/fixtures/stellar/cap-0046-08.md +109 -0
- fkyh-0.1.0/fixtures/stellar/cap-0046-11.md +605 -0
- fkyh-0.1.0/fixtures/stellar/cap-0046-12.md +600 -0
- fkyh-0.1.0/fixtures/stellar/cap-0071.md +149 -0
- fkyh-0.1.0/fixtures/stellar/sep-0041.md +352 -0
- fkyh-0.1.0/fixtures/stellar/soroban-sdk-crypto.rs +509 -0
- fkyh-0.1.0/fixtures/x402/core-v2.md +729 -0
- fkyh-0.1.0/fixtures/x402/scheme-exact-stellar.md +231 -0
- fkyh-0.1.0/fixtures/x402/scheme-exact.md +100 -0
- fkyh-0.1.0/fixtures/x402/transport-http-v1.md +160 -0
- fkyh-0.1.0/fixtures/x402/transport-http-v2.md +192 -0
- fkyh-0.1.0/fkyh/__init__.py +37 -0
- fkyh-0.1.0/fkyh/__main__.py +199 -0
- fkyh-0.1.0/fkyh/attestation.py +623 -0
- fkyh-0.1.0/fkyh/discovery.py +802 -0
- fkyh-0.1.0/fkyh/gossip.py +377 -0
- fkyh-0.1.0/fkyh/jcs.py +236 -0
- fkyh-0.1.0/fkyh/keys.py +233 -0
- fkyh-0.1.0/fkyh/metrics.py +216 -0
- fkyh-0.1.0/fkyh/node.py +349 -0
- fkyh-0.1.0/fkyh/servicetype.py +399 -0
- fkyh-0.1.0/fkyh/signer.py +163 -0
- fkyh-0.1.0/fkyh/signing.py +598 -0
- fkyh-0.1.0/fkyh/state.py +269 -0
- fkyh-0.1.0/fkyh.egg-info/PKG-INFO +485 -0
- fkyh-0.1.0/fkyh.egg-info/SOURCES.txt +169 -0
- fkyh-0.1.0/fkyh.egg-info/dependency_links.txt +1 -0
- fkyh-0.1.0/fkyh.egg-info/entry_points.txt +2 -0
- fkyh-0.1.0/fkyh.egg-info/requires.txt +9 -0
- fkyh-0.1.0/fkyh.egg-info/top_level.txt +1 -0
- fkyh-0.1.0/pyproject.toml +58 -0
- fkyh-0.1.0/pytest.ini +8 -0
- fkyh-0.1.0/scripts/publish-gate.sh +925 -0
- fkyh-0.1.0/setup.cfg +4 -0
- fkyh-0.1.0/tests/conftest.py +32 -0
- fkyh-0.1.0/tests/oracle_headers.py +294 -0
- fkyh-0.1.0/tests/test_attestation.py +423 -0
- fkyh-0.1.0/tests/test_audit_attestation_canonicalisation.py +743 -0
- fkyh-0.1.0/tests/test_audit_attestation_in_toto.py +1202 -0
- fkyh-0.1.0/tests/test_audit_attestation_trust_replay.py +829 -0
- fkyh-0.1.0/tests/test_audit_comparison_participation.py +734 -0
- fkyh-0.1.0/tests/test_audit_discovery_gossip.py +708 -0
- fkyh-0.1.0/tests/test_audit_key_id_derivation.py +228 -0
- fkyh-0.1.0/tests/test_audit_metrics_dashboard.py +425 -0
- fkyh-0.1.0/tests/test_audit_payments_security.py +612 -0
- fkyh-0.1.0/tests/test_audit_section_references.py +381 -0
- fkyh-0.1.0/tests/test_audit_signed_headers.py +707 -0
- fkyh-0.1.0/tests/test_ci_contract.py +653 -0
- fkyh-0.1.0/tests/test_discovery.py +192 -0
- fkyh-0.1.0/tests/test_discovery_live.py +159 -0
- fkyh-0.1.0/tests/test_discovery_live_servicetype.py +368 -0
- fkyh-0.1.0/tests/test_doc_claims.py +1334 -0
- fkyh-0.1.0/tests/test_go_consumer.py +134 -0
- fkyh-0.1.0/tests/test_go_oracle.py +156 -0
- fkyh-0.1.0/tests/test_gossip.py +187 -0
- fkyh-0.1.0/tests/test_gossip_signing.py +262 -0
- fkyh-0.1.0/tests/test_grafana_dashboard.py +237 -0
- fkyh-0.1.0/tests/test_independent_consumer.py +201 -0
- fkyh-0.1.0/tests/test_independent_verification.py +307 -0
- fkyh-0.1.0/tests/test_keys.py +177 -0
- fkyh-0.1.0/tests/test_metrics.py +130 -0
- fkyh-0.1.0/tests/test_node.py +174 -0
- fkyh-0.1.0/tests/test_oracle_headers.py +237 -0
- fkyh-0.1.0/tests/test_oracle_pins.py +804 -0
- fkyh-0.1.0/tests/test_prove_it.py +474 -0
- fkyh-0.1.0/tests/test_publication_truth.py +484 -0
- fkyh-0.1.0/tests/test_publish_gate.py +593 -0
- fkyh-0.1.0/tests/test_service_type_freeze.py +155 -0
- fkyh-0.1.0/tests/test_servicetype.py +401 -0
- fkyh-0.1.0/tests/test_signing.py +727 -0
- fkyh-0.1.0/tests/test_spec_conformance.py +567 -0
- fkyh-0.1.0/tests/test_spec_examples.py +294 -0
- fkyh-0.1.0/tests/test_spec_signed_gossip.py +238 -0
- fkyh-0.1.0/tests/test_state.py +194 -0
- fkyh-0.1.0/tests/test_verify_cli.py +223 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
python:
|
|
11
|
+
name: Python package and tests
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
# The floor `pyproject.toml` declares must be TESTED, not merely
|
|
15
|
+
# stated. A `requires-python` nobody ever runs is a promise with
|
|
16
|
+
# no evidence behind it, and this repository's rule is that a
|
|
17
|
+
# document describing a thing is not the same as a check on the
|
|
18
|
+
# thing. A matrix is the cheapest way to make the promise real.
|
|
19
|
+
#
|
|
20
|
+
# This is also the only job that runs the whole suite
|
|
21
|
+
# (`python -m pytest tests/`), which is why the declared floor is
|
|
22
|
+
# tested HERE and nowhere else. Every other job checks a slice of
|
|
23
|
+
# the repository, and each one says what it checks, and why it
|
|
24
|
+
# pins a single interpreter, beside its own `setup-python` step.
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
python-version: ["3.11", "3.12"]
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
32
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
33
|
+
# the gate skips everything and the suite fails for a reason that
|
|
34
|
+
# has nothing to do with the code. Full history, always.
|
|
35
|
+
fetch-depth: 0
|
|
36
|
+
|
|
37
|
+
- uses: actions/setup-python@v5
|
|
38
|
+
with:
|
|
39
|
+
python-version: ${{ matrix.python-version }}
|
|
40
|
+
|
|
41
|
+
# Two tests in the suite build Go binaries (the attestation consumer
|
|
42
|
+
# and the executor oracle). They skip when Go is missing, which
|
|
43
|
+
# silently turned them into no-ops. Install Go here so they really
|
|
44
|
+
# run in the main job, not just in the Go-specific jobs.
|
|
45
|
+
- uses: actions/setup-go@v5
|
|
46
|
+
with:
|
|
47
|
+
go-version: "1.22"
|
|
48
|
+
|
|
49
|
+
# Installing Go is not the same as the Go code building. Both
|
|
50
|
+
# builders inside the suite call `pytest.skip` when `go build`
|
|
51
|
+
# fails (tests/test_go_consumer.py:38, tests/test_go_oracle.py:46),
|
|
52
|
+
# so a Go source change that does not compile turns four
|
|
53
|
+
# cross-language pins into four SKIPS and leaves this job GREEN --
|
|
54
|
+
# a gate that inspects less than it governs, which is the exact
|
|
55
|
+
# failure this repository has already been bitten by. Measured: with
|
|
56
|
+
# a deliberate syntax error in examples/go-reference/oracle.go the
|
|
57
|
+
# suite reported "4 skipped" and exited 0. Build both binaries HERE,
|
|
58
|
+
# where a compile error is a failed step, so the suite's own skip can
|
|
59
|
+
# never be the only thing that notices.
|
|
60
|
+
- name: The Go cross-language pins must not degrade into skips
|
|
61
|
+
run: |
|
|
62
|
+
set -euo pipefail
|
|
63
|
+
cd examples/attestation-consumer-go
|
|
64
|
+
go build -o /tmp/attestation-consumer .
|
|
65
|
+
go build ./...
|
|
66
|
+
cd ../go-reference
|
|
67
|
+
go build -tags oracle -o /tmp/fk-yh-oracle .
|
|
68
|
+
|
|
69
|
+
- name: Install dependencies
|
|
70
|
+
# `.[test]` is the single source of truth for what the suite
|
|
71
|
+
# needs: the optional `prometheus_client` and `pyyaml` packages
|
|
72
|
+
# are not decoration, they are what lets the metrics and the
|
|
73
|
+
# Grafana dashboard tests actually assert. Without them those
|
|
74
|
+
# tests skip, and a test that skips is a gate that inspects
|
|
75
|
+
# less than it governs.
|
|
76
|
+
run: |
|
|
77
|
+
python -m pip install --upgrade pip
|
|
78
|
+
python -m pip install -e '.[test]'
|
|
79
|
+
|
|
80
|
+
- name: Run the test suite
|
|
81
|
+
run: python -m pytest tests/ -q
|
|
82
|
+
|
|
83
|
+
- name: The hello-world example must actually run
|
|
84
|
+
run: python examples/hello-world.py
|
|
85
|
+
|
|
86
|
+
mDNS:
|
|
87
|
+
name: Live mDNS round trip
|
|
88
|
+
# The live discovery tests need the platform's dns-sd tool, which is
|
|
89
|
+
# macOS only. This job exists because the unit tests could not catch
|
|
90
|
+
# the TXT format bug -- they passed while the implementation could not
|
|
91
|
+
# talk to the network at all.
|
|
92
|
+
# The label matters, and so does the measurement. macos-14 is
|
|
93
|
+
# DEPRECATED (actions/runner-images), and bare macos-15 also never
|
|
94
|
+
# acquired a runner: the job queued and was cancelled with
|
|
95
|
+
# runner_name="" and steps=0, four attempts running, while the six
|
|
96
|
+
# ubuntu-latest jobs in the SAME run took runners within two seconds.
|
|
97
|
+
# At the same moment, macos-latest jobs in other repos were landing
|
|
98
|
+
# on real runners (setup-python 5/5, pypa/pip 4/4, Homebrew
|
|
99
|
+
# macos-26 2/2) -- so this was never a macOS capacity shortage, it
|
|
100
|
+
# is this label not being served. macos-latest resolves to the
|
|
101
|
+
# current GA macOS, which is the version the live suite is verified
|
|
102
|
+
# against (macOS 26.4.1: 10/10 passing locally).
|
|
103
|
+
runs-on: macos-latest
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/checkout@v4
|
|
106
|
+
with:
|
|
107
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
108
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
109
|
+
# the gate skips everything and the suite fails for a reason that
|
|
110
|
+
# has nothing to do with the code. Full history, always.
|
|
111
|
+
fetch-depth: 0
|
|
112
|
+
|
|
113
|
+
# One Python version (3.12), deliberately, not a matrix. What this
|
|
114
|
+
# job checks is a live-network round trip that needs the platform's
|
|
115
|
+
# dns-sd tool, and dns-sd is macOS only by nature -- so the
|
|
116
|
+
# interpreter version is incidental to the thing being checked.
|
|
117
|
+
# The declared floor is still exercised where it can be: the
|
|
118
|
+
# `python` job's matrix runs the whole suite on the floor,
|
|
119
|
+
# including the discovery unit tests. The live discovery files
|
|
120
|
+
# skip there, because dns-sd is missing on that runner -- which is
|
|
121
|
+
# exactly why this job exists.
|
|
122
|
+
- uses: actions/setup-python@v5
|
|
123
|
+
with:
|
|
124
|
+
python-version: "3.12"
|
|
125
|
+
|
|
126
|
+
- name: Install dependencies
|
|
127
|
+
run: |
|
|
128
|
+
python -m pip install --upgrade pip
|
|
129
|
+
python -m pip install pytest cryptography
|
|
130
|
+
|
|
131
|
+
- name: Advertise and resolve over a real network
|
|
132
|
+
# The glob, not a filename: a new live test file that is not
|
|
133
|
+
# listed here silently never runs, which is the same failure as
|
|
134
|
+
# not writing the test at all. The TXT format bug was invisible
|
|
135
|
+
# because the unit tests could not talk to the network.
|
|
136
|
+
run: python3 -m pytest tests/test_discovery_live*.py -v
|
|
137
|
+
|
|
138
|
+
- name: The audit live pins must run on a runner too
|
|
139
|
+
# These pins read the wire back -- the TXT record as a conforming
|
|
140
|
+
# reader sees it, and whether a derived service type really is a
|
|
141
|
+
# separate registration. They had never executed on a runner,
|
|
142
|
+
# because the glob above does not match this file AND the pins
|
|
143
|
+
# are gated behind FKYH_AUDIT_LIVE=1.
|
|
144
|
+
#
|
|
145
|
+
# A pin that never runs is a pin that cannot fail, and these
|
|
146
|
+
# proved it: one of them was found RED the first time it was
|
|
147
|
+
# actually executed (2026-10-22), still asserting the behaviour
|
|
148
|
+
# the fix had already removed. The ports are disjoint from the
|
|
149
|
+
# tests above (19990-19997 against 19873/19880-19884) and the
|
|
150
|
+
# instance names differ, so the two groups do not collide; this
|
|
151
|
+
# step runs after the one above rather than beside it.
|
|
152
|
+
#
|
|
153
|
+
# The gate is set for this step only. Without it the four live
|
|
154
|
+
# pins SKIP, and a skip in CI is indistinguishable from a pass.
|
|
155
|
+
env:
|
|
156
|
+
FKYH_AUDIT_LIVE: "1"
|
|
157
|
+
run: python3 -m pytest tests/test_audit_discovery_gossip.py -v
|
|
158
|
+
|
|
159
|
+
goAttestation:
|
|
160
|
+
name: Go attestation consumer (cross-language)
|
|
161
|
+
# The attestation protocol is implemented twice in Python and once in Go.
|
|
162
|
+
# The Go one is the interesting one: two Python implementations can share
|
|
163
|
+
# a misunderstanding and never find it, because they share a language, a
|
|
164
|
+
# JSON library and a set of habits. This job proves the protocol
|
|
165
|
+
# interoperates ACROSS languages, not merely across implementations.
|
|
166
|
+
runs-on: ubuntu-latest
|
|
167
|
+
steps:
|
|
168
|
+
- uses: actions/checkout@v4
|
|
169
|
+
with:
|
|
170
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
171
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
172
|
+
# the gate skips everything and the suite fails for a reason that
|
|
173
|
+
# has nothing to do with the code. Full history, always.
|
|
174
|
+
fetch-depth: 0
|
|
175
|
+
|
|
176
|
+
- uses: actions/setup-go@v5
|
|
177
|
+
with:
|
|
178
|
+
go-version: "1.22"
|
|
179
|
+
|
|
180
|
+
- name: The Go consumer must satisfy the published manifest
|
|
181
|
+
run: |
|
|
182
|
+
cd examples/attestation-consumer-go
|
|
183
|
+
go build -o /tmp/attestation-consumer .
|
|
184
|
+
/tmp/attestation-consumer --conformance ../../fixtures/attestations
|
|
185
|
+
|
|
186
|
+
- name: The Go test suite must pass
|
|
187
|
+
run: cd examples/attestation-consumer-go && go test ./...
|
|
188
|
+
|
|
189
|
+
conformance:
|
|
190
|
+
name: Go executor oracle (pinned contract)
|
|
191
|
+
# The Go oracle implements the same 5-stage guarded executor as the
|
|
192
|
+
# Python reference. The Python side lives in the LAM repository, which
|
|
193
|
+
# this repository cannot reach, so what is checked here is the oracle
|
|
194
|
+
# against the pinned contract in fixtures/executor/conformance.json.
|
|
195
|
+
#
|
|
196
|
+
# The previous version of this job parsed the oracle's stdout as a
|
|
197
|
+
# single JSON array. The oracle emits one JSON object per line, so
|
|
198
|
+
# `out[0]` raised KeyError and the job failed on every run from the
|
|
199
|
+
# repository's first commit. The check now lives in a test, which runs
|
|
200
|
+
# locally as well as here.
|
|
201
|
+
runs-on: ubuntu-latest
|
|
202
|
+
steps:
|
|
203
|
+
- uses: actions/checkout@v4
|
|
204
|
+
with:
|
|
205
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
206
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
207
|
+
# the gate skips everything and the suite fails for a reason that
|
|
208
|
+
# has nothing to do with the code. Full history, always.
|
|
209
|
+
fetch-depth: 0
|
|
210
|
+
|
|
211
|
+
- uses: actions/setup-go@v5
|
|
212
|
+
with:
|
|
213
|
+
go-version: "1.22"
|
|
214
|
+
|
|
215
|
+
# One Python version (3.12), deliberately, not a matrix. What this
|
|
216
|
+
# job checks is the Go oracle against the pinned contract, and the
|
|
217
|
+
# Go version is pinned separately at 1.22. The Python step here
|
|
218
|
+
# only parses a JSON fixture, so the interpreter version cannot
|
|
219
|
+
# change the oracle's verdict. The declared floor is exercised for
|
|
220
|
+
# the suite by the `python` job's matrix.
|
|
221
|
+
- uses: actions/setup-python@v5
|
|
222
|
+
with:
|
|
223
|
+
python-version: "3.12"
|
|
224
|
+
|
|
225
|
+
- name: Install dependencies
|
|
226
|
+
run: |
|
|
227
|
+
python -m pip install --upgrade pip
|
|
228
|
+
python -m pip install pytest
|
|
229
|
+
|
|
230
|
+
- name: Build the Go oracle
|
|
231
|
+
run: |
|
|
232
|
+
chmod +x examples/go-reference/build_oracle.sh
|
|
233
|
+
./examples/go-reference/build_oracle.sh /tmp/fk-yh-oracle
|
|
234
|
+
|
|
235
|
+
- name: The oracle must agree with the pinned contract
|
|
236
|
+
run: python -m pytest tests/test_go_oracle.py -v
|
|
237
|
+
|
|
238
|
+
- name: The conformance fixture must be internally consistent
|
|
239
|
+
# The contract is the shared document both implementations are
|
|
240
|
+
# pinned to. If it is malformed, every check against it is
|
|
241
|
+
# meaningless, so validate it on its own.
|
|
242
|
+
run: |
|
|
243
|
+
python3 - <<'PY'
|
|
244
|
+
import json, sys
|
|
245
|
+
with open("fixtures/executor/conformance.json") as fh:
|
|
246
|
+
doc = json.load(fh)
|
|
247
|
+
cases = doc["cases"]
|
|
248
|
+
if not cases:
|
|
249
|
+
print("the conformance fixture has no cases")
|
|
250
|
+
sys.exit(1)
|
|
251
|
+
stages = {c["expect"]["stage"] for c in cases}
|
|
252
|
+
wanted = {"prepare", "authorize", "execute", "commit"}
|
|
253
|
+
missing = wanted - stages
|
|
254
|
+
if missing:
|
|
255
|
+
print("the conformance fixture never exercises:", sorted(missing))
|
|
256
|
+
sys.exit(1)
|
|
257
|
+
print(f"{len(cases)} conformance cases, stages covered: {sorted(stages)}")
|
|
258
|
+
PY
|
|
259
|
+
|
|
260
|
+
attestation:
|
|
261
|
+
name: Attestation conformance fixtures
|
|
262
|
+
runs-on: ubuntu-latest
|
|
263
|
+
steps:
|
|
264
|
+
- uses: actions/checkout@v4
|
|
265
|
+
with:
|
|
266
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
267
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
268
|
+
# the gate skips everything and the suite fails for a reason that
|
|
269
|
+
# has nothing to do with the code. Full history, always.
|
|
270
|
+
fetch-depth: 0
|
|
271
|
+
|
|
272
|
+
# One Python version (3.12), deliberately, not a matrix. What this
|
|
273
|
+
# job checks is the published conformance consumer, run as a
|
|
274
|
+
# SCRIPT, so what is under test is the consumer's own output and
|
|
275
|
+
# not the interpreter underneath it. The floor is covered for the
|
|
276
|
+
# consumer as well: the suite runs that same script as a
|
|
277
|
+
# subprocess on the interpreter that runs the suite
|
|
278
|
+
# (tests/test_independent_consumer.py), so the `python` job's
|
|
279
|
+
# matrix exercises the consumer on the declared floor too.
|
|
280
|
+
- uses: actions/setup-python@v5
|
|
281
|
+
with:
|
|
282
|
+
python-version: "3.12"
|
|
283
|
+
|
|
284
|
+
- name: Install dependencies
|
|
285
|
+
run: |
|
|
286
|
+
python -m pip install --upgrade pip
|
|
287
|
+
python -m pip install pytest cryptography
|
|
288
|
+
|
|
289
|
+
- name: The independent consumer must satisfy the published manifest
|
|
290
|
+
# examples/independent-consumer/ is a second implementation written
|
|
291
|
+
# from ATTESTATION.md alone, importing nothing from the package. It is
|
|
292
|
+
# the artefact that proves the specification is implementable from the
|
|
293
|
+
# document rather than only by someone who has read the reference
|
|
294
|
+
# code. If it and the package ever disagree, the specification is
|
|
295
|
+
# ambiguous and the fixtures are not trustworthy.
|
|
296
|
+
run: |
|
|
297
|
+
python3 examples/independent-consumer/run_conformance.py
|
|
298
|
+
|
|
299
|
+
- name: The published fixtures must satisfy their own manifest
|
|
300
|
+
# An independent consumer, implemented from ATTESTATION.md alone,
|
|
301
|
+
# validates the published fixture set. If the corpus and the spec
|
|
302
|
+
# ever drift apart, this fails.
|
|
303
|
+
run: |
|
|
304
|
+
python3 - <<'PY'
|
|
305
|
+
import json, os, sys
|
|
306
|
+
sys.path.insert(0, ".")
|
|
307
|
+
from fkyh.attestation import Consumer, TrustConfig
|
|
308
|
+
|
|
309
|
+
fx = "fixtures/attestations"
|
|
310
|
+
manifest = json.load(open(os.path.join(fx, "manifest.json")))
|
|
311
|
+
trust = TrustConfig.load(os.path.join(fx, "trust.json"))
|
|
312
|
+
# The published evidence directory, so the consumer re-derives
|
|
313
|
+
# the digests as section 10 instructs. Without it the evidence
|
|
314
|
+
# codes of section 7 step 9 are never reached.
|
|
315
|
+
evidence = os.path.join(fx, "evidence")
|
|
316
|
+
ok = bad = 0
|
|
317
|
+
for name, expected in sorted(manifest["fixtures"].items()):
|
|
318
|
+
att = json.load(open(os.path.join(fx, expected["file"])))
|
|
319
|
+
result = Consumer(trust, evidence_root=evidence).validate(
|
|
320
|
+
att, expected_task_id=manifest["task_id"],
|
|
321
|
+
expected_attempt_id=manifest["attempt_id"])
|
|
322
|
+
good = (result.code == expected["expected_code"]
|
|
323
|
+
and result.result == expected["expected_result"])
|
|
324
|
+
ok += good
|
|
325
|
+
bad += not good
|
|
326
|
+
if not good:
|
|
327
|
+
print(f"FAIL {name}: {result.code}/{result.result} "
|
|
328
|
+
f"expected {expected['expected_code']}/"
|
|
329
|
+
f"{expected['expected_result']}")
|
|
330
|
+
for seq in manifest.get("sequences", []):
|
|
331
|
+
spent = set()
|
|
332
|
+
for step in seq["steps"]:
|
|
333
|
+
att = json.load(open(os.path.join(fx, step["file"])))
|
|
334
|
+
result = Consumer(trust, evidence_root=evidence,
|
|
335
|
+
spent=spent).validate(
|
|
336
|
+
att, expected_task_id=manifest["task_id"],
|
|
337
|
+
expected_attempt_id=manifest["attempt_id"])
|
|
338
|
+
good = (result.code == step["expected_code"]
|
|
339
|
+
and result.result == step["expected_result"])
|
|
340
|
+
ok += good
|
|
341
|
+
bad += not good
|
|
342
|
+
print(f"{ok}/{ok + bad} conformance checks passed")
|
|
343
|
+
sys.exit(0 if bad == 0 else 1)
|
|
344
|
+
PY
|
|
345
|
+
|
|
346
|
+
soroban-registry:
|
|
347
|
+
name: Soroban registry contract
|
|
348
|
+
# The contract is native-testable: cargo test needs no stellar-cli and
|
|
349
|
+
# no wasm target. The wasm BUILD is deliberately not in CI -- the SDK's
|
|
350
|
+
# build script requires stellar-cli v25.2.0+ for spec shaking, and
|
|
351
|
+
# claiming the contract builds in CI without that toolchain would be
|
|
352
|
+
# the same class of claim this repository keeps deleting.
|
|
353
|
+
runs-on: ubuntu-latest
|
|
354
|
+
steps:
|
|
355
|
+
- uses: actions/checkout@v4
|
|
356
|
+
with:
|
|
357
|
+
# The publish gate audits the DEFAULT BRANCH's tree, and the
|
|
358
|
+
# test suite runs it. A shallow checkout has no origin/main, so
|
|
359
|
+
# the gate skips everything and the suite fails for a reason that
|
|
360
|
+
# has nothing to do with the code. Full history, always.
|
|
361
|
+
fetch-depth: 0
|
|
362
|
+
# Pinned, not `@stable`. The Go job pins 1.22 and the Python job
|
|
363
|
+
# pins 3.11 and 3.12, because a toolchain that moves under a green
|
|
364
|
+
# run is a promise nobody tested. `@stable` means this job is
|
|
365
|
+
# decided by whatever Rust was released that morning: `Cargo.lock`
|
|
366
|
+
# pins the CRATES, but never the COMPILER that builds them, so a
|
|
367
|
+
# stranger who clones this repository in six months would be the
|
|
368
|
+
# first person ever to run the contract against a Rust nobody has
|
|
369
|
+
# run it against. 1.99.1 is the toolchain this contract is built
|
|
370
|
+
# and tested against -- it is the current stable today
|
|
371
|
+
# (rustc 1.99.1, 58cf8f9c3) and `cargo test --locked` passes 21/21
|
|
372
|
+
# on it from a clean checkout with no `target/` directory.
|
|
373
|
+
- uses: dtolnay/rust-toolchain@1.99.1
|
|
374
|
+
- name: Contract tests
|
|
375
|
+
working-directory: contracts/fkyh-registry
|
|
376
|
+
run: cargo test --locked
|