aetherx-reprocert 0.2.2a1__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.
- aetherx_reprocert-0.2.2a1/.github/ISSUE_TEMPLATE/adoption.yml +78 -0
- aetherx_reprocert-0.2.2a1/.github/ISSUE_TEMPLATE/bug.yml +71 -0
- aetherx_reprocert-0.2.2a1/.github/ISSUE_TEMPLATE/config.yml +8 -0
- aetherx_reprocert-0.2.2a1/.github/ISSUE_TEMPLATE/feature.yml +45 -0
- aetherx_reprocert-0.2.2a1/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- aetherx_reprocert-0.2.2a1/.github/dependabot.yml +13 -0
- aetherx_reprocert-0.2.2a1/.github/workflows/attested-demo.yml +70 -0
- aetherx_reprocert-0.2.2a1/.github/workflows/ci.yml +217 -0
- aetherx_reprocert-0.2.2a1/.github/workflows/release.yml +73 -0
- aetherx_reprocert-0.2.2a1/.github/workflows/stable-channel-proof.yml +64 -0
- aetherx_reprocert-0.2.2a1/.gitignore +16 -0
- aetherx_reprocert-0.2.2a1/CHANGELOG.md +58 -0
- aetherx_reprocert-0.2.2a1/CODE_OF_CONDUCT.md +16 -0
- aetherx_reprocert-0.2.2a1/CONTRIBUTING.md +41 -0
- aetherx_reprocert-0.2.2a1/GOVERNANCE.md +39 -0
- aetherx_reprocert-0.2.2a1/LICENSE +201 -0
- aetherx_reprocert-0.2.2a1/NOTICE +7 -0
- aetherx_reprocert-0.2.2a1/PKG-INFO +373 -0
- aetherx_reprocert-0.2.2a1/README.md +344 -0
- aetherx_reprocert-0.2.2a1/ROADMAP.md +88 -0
- aetherx_reprocert-0.2.2a1/SECURITY.md +26 -0
- aetherx_reprocert-0.2.2a1/SUPPORT.md +35 -0
- aetherx_reprocert-0.2.2a1/action.yml +85 -0
- aetherx_reprocert-0.2.2a1/docs/ADOPTION.md +102 -0
- aetherx_reprocert-0.2.2a1/docs/ARCHITECTURE.md +44 -0
- aetherx_reprocert-0.2.2a1/docs/ATTESTATION.md +38 -0
- aetherx_reprocert-0.2.2a1/docs/CLAIM_FORMAT.md +55 -0
- aetherx_reprocert-0.2.2a1/docs/CONTAINER_PROFILE.md +59 -0
- aetherx_reprocert-0.2.2a1/docs/INTEGRATION_GUIDE.md +81 -0
- aetherx_reprocert-0.2.2a1/docs/JUNIT.md +30 -0
- aetherx_reprocert-0.2.2a1/docs/POLICY.md +59 -0
- aetherx_reprocert-0.2.2a1/docs/PUBLISHING.md +52 -0
- aetherx_reprocert-0.2.2a1/docs/PYTEST.md +38 -0
- aetherx_reprocert-0.2.2a1/docs/QUICKSTART_5_MIN.md +79 -0
- aetherx_reprocert-0.2.2a1/docs/SUITES.md +51 -0
- aetherx_reprocert-0.2.2a1/docs/THREAT_MODEL.md +51 -0
- aetherx_reprocert-0.2.2a1/docs/TROUBLESHOOTING.md +51 -0
- aetherx_reprocert-0.2.2a1/examples/basic/claim.yml +30 -0
- aetherx_reprocert-0.2.2a1/examples/basic/produce.py +7 -0
- aetherx_reprocert-0.2.2a1/examples/junit/claim.yml +32 -0
- aetherx_reprocert-0.2.2a1/examples/junit/make_report.py +13 -0
- aetherx_reprocert-0.2.2a1/examples/policy/container-required.yml +12 -0
- aetherx_reprocert-0.2.2a1/examples/policy/strict-ci.yml +14 -0
- aetherx_reprocert-0.2.2a1/examples/pytest-native/test_sample.py +6 -0
- aetherx_reprocert-0.2.2a1/examples/suite.yml +9 -0
- aetherx_reprocert-0.2.2a1/pyproject.toml +47 -0
- aetherx_reprocert-0.2.2a1/schemas/attestation-predicate-v1.schema.json +55 -0
- aetherx_reprocert-0.2.2a1/schemas/certificate-v1alpha1.schema.json +14 -0
- aetherx_reprocert-0.2.2a1/schemas/claim-v1alpha1.schema.json +131 -0
- aetherx_reprocert-0.2.2a1/schemas/policy-v1alpha1.schema.json +44 -0
- aetherx_reprocert-0.2.2a1/schemas/suite-v1alpha1.schema.json +33 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/__init__.py +3 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/__main__.py +3 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/attestation.py +60 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/certificate.py +29 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/claim.py +207 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/cli.py +488 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/container.py +138 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/doctor.py +175 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/environment.py +67 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/init_project.py +210 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/junit.py +154 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/policy.py +266 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/pytest_adapter.py +84 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/runner.py +302 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/suite.py +151 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/util.py +46 -0
- aetherx_reprocert-0.2.2a1/src/reprocert/verification.py +158 -0
- aetherx_reprocert-0.2.2a1/tests/test_adoption.py +187 -0
- aetherx_reprocert-0.2.2a1/tests/test_release_workflow.py +7 -0
- aetherx_reprocert-0.2.2a1/tests/test_reprocert.py +77 -0
- aetherx_reprocert-0.2.2a1/tests/test_self_service.py +84 -0
- aetherx_reprocert-0.2.2a1/tests/test_v02.py +218 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: Adoption / Integration Help
|
|
2
|
+
description: Get help adding ReproCert to a real repository or CI workflow.
|
|
3
|
+
title: "[Adoption] "
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
ReproCert can be added as a small evidence layer on top of an existing test, benchmark, build, or research workflow. Keep this issue non-sensitive: do not include credentials, private source code, customer data, or confidential artifacts.
|
|
9
|
+
|
|
10
|
+
- type: input
|
|
11
|
+
id: repository
|
|
12
|
+
attributes:
|
|
13
|
+
label: Repository URL
|
|
14
|
+
description: Public repository URL if available. For private projects, describe the stack without sharing confidential details.
|
|
15
|
+
placeholder: https://github.com/owner/repository
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: claim
|
|
21
|
+
attributes:
|
|
22
|
+
label: What claim do you want to verify?
|
|
23
|
+
description: State one concrete technical claim.
|
|
24
|
+
placeholder: "Example: the benchmark median stays below 250 ms, or all pytest checks complete with zero failures."
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: current_workflow
|
|
30
|
+
attributes:
|
|
31
|
+
label: Current command or CI workflow
|
|
32
|
+
description: Show the existing command or a small non-sensitive workflow excerpt.
|
|
33
|
+
render: shell
|
|
34
|
+
validations:
|
|
35
|
+
required: true
|
|
36
|
+
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: evidence
|
|
39
|
+
attributes:
|
|
40
|
+
label: Evidence already produced
|
|
41
|
+
description: Examples include JUnit XML, benchmark JSON, build artifacts, hashes, or logs.
|
|
42
|
+
placeholder: junit.xml, benchmark.json, dist/package.whl
|
|
43
|
+
validations:
|
|
44
|
+
required: false
|
|
45
|
+
|
|
46
|
+
- type: dropdown
|
|
47
|
+
id: integration
|
|
48
|
+
attributes:
|
|
49
|
+
label: Preferred integration
|
|
50
|
+
options:
|
|
51
|
+
- GitHub Action
|
|
52
|
+
- ReproCert CLI
|
|
53
|
+
- Pytest-native adapter
|
|
54
|
+
- JUnit integration
|
|
55
|
+
- Multi-claim suite
|
|
56
|
+
- Policy gate
|
|
57
|
+
- Signed attestation
|
|
58
|
+
- Not sure — recommend the smallest useful integration
|
|
59
|
+
validations:
|
|
60
|
+
required: true
|
|
61
|
+
|
|
62
|
+
- type: textarea
|
|
63
|
+
id: constraints
|
|
64
|
+
attributes:
|
|
65
|
+
label: Constraints
|
|
66
|
+
description: Note OS, Python version, CI provider, security restrictions, or "no product-code changes" requirements.
|
|
67
|
+
validations:
|
|
68
|
+
required: false
|
|
69
|
+
|
|
70
|
+
- type: checkboxes
|
|
71
|
+
id: boundaries
|
|
72
|
+
attributes:
|
|
73
|
+
label: Public issue boundaries
|
|
74
|
+
options:
|
|
75
|
+
- label: I confirm this issue contains no credentials, private customer data, confidential source code, or sensitive exploit details.
|
|
76
|
+
required: true
|
|
77
|
+
- label: I understand a ReproCert PASS result does not by itself establish security certification, scientific truth, or benchmark fairness.
|
|
78
|
+
required: true
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a reproducible defect in ReproCert.
|
|
3
|
+
title: "[Bug] "
|
|
4
|
+
labels: []
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for helping improve ReproCert. Do not include credentials, private source code, customer data, or sensitive vulnerability details.
|
|
10
|
+
|
|
11
|
+
- type: input
|
|
12
|
+
id: version
|
|
13
|
+
attributes:
|
|
14
|
+
label: ReproCert version or commit
|
|
15
|
+
placeholder: 0.1.0a1 or commit SHA
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: dropdown
|
|
20
|
+
id: surface
|
|
21
|
+
attributes:
|
|
22
|
+
label: Affected surface
|
|
23
|
+
options:
|
|
24
|
+
- CLI
|
|
25
|
+
- GitHub Action
|
|
26
|
+
- Claim schema
|
|
27
|
+
- Certificate verification
|
|
28
|
+
- Evidence collection
|
|
29
|
+
- Packaging / installation
|
|
30
|
+
- Documentation
|
|
31
|
+
- Other
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
|
|
35
|
+
- type: textarea
|
|
36
|
+
id: reproduction
|
|
37
|
+
attributes:
|
|
38
|
+
label: Minimal reproduction
|
|
39
|
+
description: Provide the smallest non-sensitive example that reproduces the issue.
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
|
|
43
|
+
- type: textarea
|
|
44
|
+
id: expected
|
|
45
|
+
attributes:
|
|
46
|
+
label: Expected behavior
|
|
47
|
+
validations:
|
|
48
|
+
required: true
|
|
49
|
+
|
|
50
|
+
- type: textarea
|
|
51
|
+
id: observed
|
|
52
|
+
attributes:
|
|
53
|
+
label: Observed behavior
|
|
54
|
+
validations:
|
|
55
|
+
required: true
|
|
56
|
+
|
|
57
|
+
- type: input
|
|
58
|
+
id: platform
|
|
59
|
+
attributes:
|
|
60
|
+
label: Platform and Python version
|
|
61
|
+
placeholder: Ubuntu 24.04 / Python 3.13
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
|
|
65
|
+
- type: checkboxes
|
|
66
|
+
id: safety
|
|
67
|
+
attributes:
|
|
68
|
+
label: Public issue safety
|
|
69
|
+
options:
|
|
70
|
+
- label: I confirm this report contains no credentials, confidential data, private source code, or sensitive exploit details.
|
|
71
|
+
required: true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security guidance
|
|
4
|
+
url: https://github.com/AETHERXGLOBAL/reprocert/blob/main/SECURITY.md
|
|
5
|
+
about: Do not publish sensitive vulnerability details in a public issue.
|
|
6
|
+
- name: Support guidance
|
|
7
|
+
url: https://github.com/AETHERXGLOBAL/reprocert/blob/main/SUPPORT.md
|
|
8
|
+
about: Read the support boundary before opening a public issue.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Feature proposal
|
|
2
|
+
description: Propose a developer-facing capability for ReproCert.
|
|
3
|
+
title: "[Feature] "
|
|
4
|
+
labels: []
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Strong proposals start from a concrete developer problem and explain the evidence/trust semantics before implementation detail.
|
|
10
|
+
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: problem
|
|
13
|
+
attributes:
|
|
14
|
+
label: Developer problem
|
|
15
|
+
description: What workflow is difficult, ambiguous, or unreliable today?
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: proposal
|
|
21
|
+
attributes:
|
|
22
|
+
label: Proposed capability
|
|
23
|
+
description: Describe the smallest useful capability.
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: semantics
|
|
29
|
+
attributes:
|
|
30
|
+
label: Evidence and verdict semantics
|
|
31
|
+
description: How should PASS, FAIL, INCONCLUSIVE, or ERROR behave if relevant?
|
|
32
|
+
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: trust
|
|
35
|
+
attributes:
|
|
36
|
+
label: Trust-boundary impact
|
|
37
|
+
description: Does this affect signing, producer identity, evidence trust, remote execution, secrets, or code execution?
|
|
38
|
+
validations:
|
|
39
|
+
required: true
|
|
40
|
+
|
|
41
|
+
- type: textarea
|
|
42
|
+
id: alternatives
|
|
43
|
+
attributes:
|
|
44
|
+
label: Existing tools or alternatives
|
|
45
|
+
description: Which adjacent tools or standards already solve part of the problem?
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## What changes?
|
|
2
|
+
|
|
3
|
+
Describe the smallest coherent change and the developer problem it addresses.
|
|
4
|
+
|
|
5
|
+
## Evidence
|
|
6
|
+
|
|
7
|
+
- [ ] Tests added or updated where behavior changed.
|
|
8
|
+
- [ ] `pytest` passes locally or CI evidence is expected to establish it.
|
|
9
|
+
- [ ] Documentation updated where public behavior changed.
|
|
10
|
+
- [ ] Claim/verdict semantics remain explicit.
|
|
11
|
+
|
|
12
|
+
## Trust-boundary review
|
|
13
|
+
|
|
14
|
+
- [ ] This change does not silently expand command execution, secret access, evidence trust, signing authority, or producer-authentication claims.
|
|
15
|
+
- [ ] Any new trust assumption is documented.
|
|
16
|
+
- [ ] No credentials, private customer data, or confidential implementation material is included.
|
|
17
|
+
|
|
18
|
+
## Claim discipline
|
|
19
|
+
|
|
20
|
+
- [ ] No novelty, superiority, security-certification, scientific-validity, or production-readiness claim is introduced without evidence.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Attested Demo
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'src/**'
|
|
8
|
+
- 'examples/**'
|
|
9
|
+
- 'schemas/**'
|
|
10
|
+
- 'pyproject.toml'
|
|
11
|
+
- 'action.yml'
|
|
12
|
+
- '.github/workflows/attested-demo.yml'
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
id-token: write
|
|
18
|
+
attestations: write
|
|
19
|
+
artifact-metadata: write
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
certificate:
|
|
23
|
+
name: Produce and attest reference certificate
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout
|
|
28
|
+
uses: actions/checkout@v7
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@v7
|
|
32
|
+
with:
|
|
33
|
+
python-version: '3.13'
|
|
34
|
+
|
|
35
|
+
- name: Install ReproCert
|
|
36
|
+
run: python -m pip install .
|
|
37
|
+
|
|
38
|
+
- name: Produce reference certificate
|
|
39
|
+
working-directory: examples/basic
|
|
40
|
+
run: reprocert run claim.yml --output reprocert-certificate.json
|
|
41
|
+
|
|
42
|
+
- name: Verify certificate and evidence locally
|
|
43
|
+
working-directory: examples/basic
|
|
44
|
+
run: reprocert verify reprocert-certificate.json --claim claim.yml --evidence-root .
|
|
45
|
+
|
|
46
|
+
- name: Build ReproCert custom predicate
|
|
47
|
+
working-directory: examples/basic
|
|
48
|
+
run: |
|
|
49
|
+
reprocert predicate reprocert-certificate.json --output reprocert-predicate.json --json
|
|
50
|
+
|
|
51
|
+
- name: Attest general producer provenance
|
|
52
|
+
uses: actions/attest@v4
|
|
53
|
+
with:
|
|
54
|
+
subject-path: examples/basic/reprocert-certificate.json
|
|
55
|
+
|
|
56
|
+
- name: Attest ReproCert predicate
|
|
57
|
+
uses: actions/attest@v4
|
|
58
|
+
with:
|
|
59
|
+
subject-path: examples/basic/reprocert-certificate.json
|
|
60
|
+
predicate-type: https://raw.githubusercontent.com/AETHERXGLOBAL/reprocert/main/schemas/attestation-predicate-v1.schema.json
|
|
61
|
+
predicate-path: examples/basic/reprocert-predicate.json
|
|
62
|
+
|
|
63
|
+
- name: Upload certificate and predicate
|
|
64
|
+
uses: actions/upload-artifact@v7
|
|
65
|
+
with:
|
|
66
|
+
name: reprocert-reference-evidence
|
|
67
|
+
path: |
|
|
68
|
+
examples/basic/reprocert-certificate.json
|
|
69
|
+
examples/basic/reprocert-predicate.json
|
|
70
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: ${{ matrix.os }} / Python ${{ matrix.python }}
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
20
|
+
python: ['3.11', '3.13', '3.14']
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v7
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
uses: actions/setup-python@v7
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python }}
|
|
30
|
+
|
|
31
|
+
- name: Install
|
|
32
|
+
run: python -m pip install -e ".[dev]"
|
|
33
|
+
|
|
34
|
+
- name: Unit and adversarial tests
|
|
35
|
+
run: pytest
|
|
36
|
+
|
|
37
|
+
- name: Reference claim round-trip
|
|
38
|
+
working-directory: examples/basic
|
|
39
|
+
shell: bash
|
|
40
|
+
run: |
|
|
41
|
+
reprocert run claim.yml --output certificate.json
|
|
42
|
+
reprocert verify certificate.json --claim claim.yml --evidence-root .
|
|
43
|
+
reprocert inspect certificate.json --json
|
|
44
|
+
|
|
45
|
+
- name: Policy gate round-trip
|
|
46
|
+
working-directory: examples/basic
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
reprocert policy certificate.json ../policy/strict-ci.yml --output policy-result.json --json
|
|
50
|
+
|
|
51
|
+
- name: JUnit adapter round-trip
|
|
52
|
+
working-directory: examples/junit
|
|
53
|
+
shell: bash
|
|
54
|
+
run: |
|
|
55
|
+
reprocert run claim.yml --output certificate.json
|
|
56
|
+
reprocert verify certificate.json --claim claim.yml --evidence-root .
|
|
57
|
+
|
|
58
|
+
- name: Pytest-native adapter round-trip
|
|
59
|
+
shell: bash
|
|
60
|
+
run: |
|
|
61
|
+
reprocert pytest --workdir examples/pytest-native --output pytest-native-certificate.json -- -q test_sample.py
|
|
62
|
+
reprocert verify pytest-native-certificate.json --claim examples/pytest-native/.reprocert-pytest-claim.json --evidence-root examples/pytest-native
|
|
63
|
+
|
|
64
|
+
- name: Multi-claim suite round-trip
|
|
65
|
+
working-directory: examples
|
|
66
|
+
shell: bash
|
|
67
|
+
run: |
|
|
68
|
+
reprocert suite suite.yml --output suite-report.json --certificate-dir .reprocert/certificates --json
|
|
69
|
+
|
|
70
|
+
action-smoke:
|
|
71
|
+
name: Reusable Action smoke test
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
steps:
|
|
74
|
+
- name: Checkout
|
|
75
|
+
uses: actions/checkout@v7
|
|
76
|
+
|
|
77
|
+
- name: Execute ReproCert Action
|
|
78
|
+
id: reprocert
|
|
79
|
+
uses: ./
|
|
80
|
+
with:
|
|
81
|
+
claim: examples/basic/claim.yml
|
|
82
|
+
certificate: reprocert-action-certificate.json
|
|
83
|
+
|
|
84
|
+
- name: Assert exported verdict and digest
|
|
85
|
+
shell: bash
|
|
86
|
+
run: |
|
|
87
|
+
test "${{ steps.reprocert.outputs.verdict }}" = "PASS"
|
|
88
|
+
test -n "${{ steps.reprocert.outputs.certificate-digest }}"
|
|
89
|
+
|
|
90
|
+
container-profile:
|
|
91
|
+
name: Hardened container profile / Ubuntu
|
|
92
|
+
runs-on: ubuntu-latest
|
|
93
|
+
steps:
|
|
94
|
+
- name: Checkout
|
|
95
|
+
uses: actions/checkout@v7
|
|
96
|
+
|
|
97
|
+
- name: Set up Python
|
|
98
|
+
uses: actions/setup-python@v7
|
|
99
|
+
with:
|
|
100
|
+
python-version: '3.13'
|
|
101
|
+
|
|
102
|
+
- name: Install
|
|
103
|
+
run: python -m pip install -e ".[dev]"
|
|
104
|
+
|
|
105
|
+
- name: Resolve immutable Alpine image identity
|
|
106
|
+
shell: bash
|
|
107
|
+
run: |
|
|
108
|
+
docker pull alpine:3.20
|
|
109
|
+
image="$(docker image inspect alpine:3.20 --format '{{index .RepoDigests 0}}')"
|
|
110
|
+
echo "REPROCERT_TEST_IMAGE=$image" >> "$GITHUB_ENV"
|
|
111
|
+
|
|
112
|
+
- name: Create digest-pinned container claim
|
|
113
|
+
shell: bash
|
|
114
|
+
run: |
|
|
115
|
+
python - <<'PY'
|
|
116
|
+
import json
|
|
117
|
+
import os
|
|
118
|
+
from pathlib import Path
|
|
119
|
+
|
|
120
|
+
claim = {
|
|
121
|
+
"apiVersion": "reprocert.dev/v1alpha1",
|
|
122
|
+
"kind": "ReproducibilityClaim",
|
|
123
|
+
"metadata": {
|
|
124
|
+
"id": "container-profile-smoke",
|
|
125
|
+
"title": "Hardened container execution profile",
|
|
126
|
+
},
|
|
127
|
+
"spec": {
|
|
128
|
+
"command": ["sh", "-c", "printf ok > result.txt"],
|
|
129
|
+
"container": {
|
|
130
|
+
"engine": "docker",
|
|
131
|
+
"image": os.environ["REPROCERT_TEST_IMAGE"],
|
|
132
|
+
"network": "none",
|
|
133
|
+
"read_only_root": True,
|
|
134
|
+
"drop_capabilities": True,
|
|
135
|
+
"no_new_privileges": True,
|
|
136
|
+
"pids_limit": 128,
|
|
137
|
+
},
|
|
138
|
+
"evidence": ["result.txt"],
|
|
139
|
+
"checks": [
|
|
140
|
+
{
|
|
141
|
+
"id": "container-result",
|
|
142
|
+
"source": {"type": "text", "path": "result.txt"},
|
|
143
|
+
"op": "eq",
|
|
144
|
+
"expected": "ok",
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
Path("container-claim.json").write_text(
|
|
150
|
+
json.dumps(claim, indent=2) + "\n",
|
|
151
|
+
encoding="utf-8",
|
|
152
|
+
)
|
|
153
|
+
PY
|
|
154
|
+
|
|
155
|
+
- name: Execute digest-pinned container claim
|
|
156
|
+
shell: bash
|
|
157
|
+
run: |
|
|
158
|
+
set +e
|
|
159
|
+
reprocert run container-claim.json --output container-certificate.json
|
|
160
|
+
rc=$?
|
|
161
|
+
python - <<'PY'
|
|
162
|
+
import json
|
|
163
|
+
from pathlib import Path
|
|
164
|
+
cert = json.loads(Path("container-certificate.json").read_text())
|
|
165
|
+
print(json.dumps({
|
|
166
|
+
"verdict": cert["verdict"],
|
|
167
|
+
"exit_code": cert["run"]["exit_code"],
|
|
168
|
+
"execution_error": cert["run"]["execution_error"],
|
|
169
|
+
"stderr_excerpt": cert["run"]["stderr_excerpt"],
|
|
170
|
+
"container": cert["run"].get("container"),
|
|
171
|
+
}, indent=2))
|
|
172
|
+
PY
|
|
173
|
+
if [ "$rc" -ne 0 ]; then
|
|
174
|
+
exit "$rc"
|
|
175
|
+
fi
|
|
176
|
+
reprocert policy container-certificate.json examples/policy/container-required.yml --output container-policy-result.json
|
|
177
|
+
reprocert inspect container-certificate.json --json
|
|
178
|
+
|
|
179
|
+
- name: Assert hardened profile evidence
|
|
180
|
+
shell: python
|
|
181
|
+
run: |
|
|
182
|
+
import json
|
|
183
|
+
import os
|
|
184
|
+
from pathlib import Path
|
|
185
|
+
|
|
186
|
+
cert = json.loads(Path("container-certificate.json").read_text())
|
|
187
|
+
profile = cert["run"]["container"]
|
|
188
|
+
assert profile["image"] == os.environ["REPROCERT_TEST_IMAGE"]
|
|
189
|
+
assert profile["network"] == "none"
|
|
190
|
+
assert profile["read_only_root"] is True
|
|
191
|
+
assert profile["drop_capabilities"] is True
|
|
192
|
+
assert profile["no_new_privileges"] is True
|
|
193
|
+
assert cert["verdict"] == "PASS"
|
|
194
|
+
|
|
195
|
+
package:
|
|
196
|
+
name: Build package
|
|
197
|
+
runs-on: ubuntu-latest
|
|
198
|
+
steps:
|
|
199
|
+
- name: Checkout
|
|
200
|
+
uses: actions/checkout@v7
|
|
201
|
+
|
|
202
|
+
- name: Set up Python
|
|
203
|
+
uses: actions/setup-python@v7
|
|
204
|
+
with:
|
|
205
|
+
python-version: '3.13'
|
|
206
|
+
|
|
207
|
+
- name: Build isolated package
|
|
208
|
+
run: |
|
|
209
|
+
python -m pip install build
|
|
210
|
+
python -m build
|
|
211
|
+
|
|
212
|
+
- name: Upload package artifact
|
|
213
|
+
uses: actions/upload-artifact@v7
|
|
214
|
+
with:
|
|
215
|
+
name: reprocert-dist
|
|
216
|
+
path: dist/*
|
|
217
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
name: Build release distributions
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout released source
|
|
17
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.13'
|
|
23
|
+
|
|
24
|
+
- name: Verify release tag matches package version
|
|
25
|
+
shell: python
|
|
26
|
+
env:
|
|
27
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
28
|
+
run: |
|
|
29
|
+
import os
|
|
30
|
+
import tomllib
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
34
|
+
version = data["project"]["version"]
|
|
35
|
+
expected = f"v{version}"
|
|
36
|
+
actual = os.environ["RELEASE_TAG"]
|
|
37
|
+
if actual != expected:
|
|
38
|
+
raise SystemExit(
|
|
39
|
+
f"Release tag {actual!r} does not match package version {expected!r}"
|
|
40
|
+
)
|
|
41
|
+
print(f"release identity verified: {actual}")
|
|
42
|
+
|
|
43
|
+
- name: Build distributions
|
|
44
|
+
run: |
|
|
45
|
+
python -m pip install build
|
|
46
|
+
python -m build
|
|
47
|
+
|
|
48
|
+
- name: Upload release distributions
|
|
49
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
|
|
50
|
+
with:
|
|
51
|
+
name: python-package-distributions
|
|
52
|
+
path: dist/*
|
|
53
|
+
if-no-files-found: error
|
|
54
|
+
|
|
55
|
+
publish-pypi:
|
|
56
|
+
name: Publish to PyPI
|
|
57
|
+
needs: build
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
environment:
|
|
60
|
+
name: pypi
|
|
61
|
+
url: https://pypi.org/project/aetherx-reprocert/
|
|
62
|
+
permissions:
|
|
63
|
+
id-token: write
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- name: Download release distributions
|
|
67
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
|
68
|
+
with:
|
|
69
|
+
name: python-package-distributions
|
|
70
|
+
path: dist
|
|
71
|
+
|
|
72
|
+
- name: Publish package
|
|
73
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Stable v0.2 Channel Proof
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'action.yml'
|
|
8
|
+
- 'src/**'
|
|
9
|
+
- 'pyproject.toml'
|
|
10
|
+
- '.github/workflows/stable-channel-proof.yml'
|
|
11
|
+
pull_request:
|
|
12
|
+
paths:
|
|
13
|
+
- '.github/workflows/stable-channel-proof.yml'
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
action-channel:
|
|
21
|
+
name: Consume AETHERXGLOBAL/reprocert@v0.2
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout consumer fixture
|
|
25
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
|
26
|
+
|
|
27
|
+
- name: Consume stable ReproCert action channel
|
|
28
|
+
id: reprocert
|
|
29
|
+
uses: AETHERXGLOBAL/reprocert@v0.2
|
|
30
|
+
with:
|
|
31
|
+
claim: examples/basic/claim.yml
|
|
32
|
+
certificate: stable-channel-certificate.json
|
|
33
|
+
|
|
34
|
+
- name: Assert stable action result
|
|
35
|
+
shell: bash
|
|
36
|
+
run: |
|
|
37
|
+
test "${{ steps.reprocert.outputs.verdict }}" = "PASS"
|
|
38
|
+
test -n "${{ steps.reprocert.outputs.certificate-digest }}"
|
|
39
|
+
test -f stable-channel-certificate.json
|
|
40
|
+
|
|
41
|
+
git-install-channel:
|
|
42
|
+
name: Self-service install from public v0.2 channel
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
steps:
|
|
45
|
+
- name: Set up Python
|
|
46
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
|
|
47
|
+
with:
|
|
48
|
+
python-version: '3.13'
|
|
49
|
+
|
|
50
|
+
- name: Install directly from public stable channel
|
|
51
|
+
run: |
|
|
52
|
+
python -m pip install "git+https://github.com/AETHERXGLOBAL/reprocert.git@v0.2"
|
|
53
|
+
reprocert --version
|
|
54
|
+
|
|
55
|
+
- name: Zero-contact self-service round-trip
|
|
56
|
+
shell: bash
|
|
57
|
+
run: |
|
|
58
|
+
mkdir consumer
|
|
59
|
+
cd consumer
|
|
60
|
+
reprocert init command --github-actions
|
|
61
|
+
reprocert doctor
|
|
62
|
+
reprocert run reprocert.yml -o certificate.json
|
|
63
|
+
reprocert verify certificate.json --claim reprocert.yml --evidence-root .
|
|
64
|
+
grep -q "AETHERXGLOBAL/reprocert@v0.2" .github/workflows/reprocert.yml
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
.pytest_cache/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
certificate.json
|
|
8
|
+
reprocert-certificate.json
|
|
9
|
+
reprocert-pytest-certificate.json
|
|
10
|
+
reprocert-policy-result.json
|
|
11
|
+
reprocert-predicate.json
|
|
12
|
+
reprocert-suite-report.json
|
|
13
|
+
result.json
|
|
14
|
+
.reprocert/
|
|
15
|
+
.reprocert-pytest-claim.json
|
|
16
|
+
.reprocert-pytest-junit.xml
|