interlock-fiduciary 1.0.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.
- interlock_fiduciary-1.0.0/.github/workflows/ci.yml +159 -0
- interlock_fiduciary-1.0.0/.github/workflows/release.yml +128 -0
- interlock_fiduciary-1.0.0/.gitignore +38 -0
- interlock_fiduciary-1.0.0/CHANGELOG.md +505 -0
- interlock_fiduciary-1.0.0/LICENSE +191 -0
- interlock_fiduciary-1.0.0/PKG-INFO +504 -0
- interlock_fiduciary-1.0.0/README.md +474 -0
- interlock_fiduciary-1.0.0/docs/BUNDLE_FORMAT.md +283 -0
- interlock_fiduciary-1.0.0/docs/FIDUCIARY_SPEC.md +2316 -0
- interlock_fiduciary-1.0.0/docs/MUTATION_PASS.md +91 -0
- interlock_fiduciary-1.0.0/pyproject.toml +103 -0
- interlock_fiduciary-1.0.0/scripts/ilok1_sizes.py +183 -0
- interlock_fiduciary-1.0.0/scripts/live_acceptance.py +798 -0
- interlock_fiduciary-1.0.0/scripts/live_stress_test.py +1080 -0
- interlock_fiduciary-1.0.0/scripts/make_bundles.py +283 -0
- interlock_fiduciary-1.0.0/scripts/make_upgrade_stores.py +103 -0
- interlock_fiduciary-1.0.0/scripts/make_vectors.py +424 -0
- interlock_fiduciary-1.0.0/scripts/security_audit.py +572 -0
- interlock_fiduciary-1.0.0/scripts/upgrade_scenario.py +169 -0
- interlock_fiduciary-1.0.0/src/fiduciary/__init__.py +38 -0
- interlock_fiduciary-1.0.0/src/fiduciary/_upstream.py +38 -0
- interlock_fiduciary-1.0.0/src/fiduciary/authority.py +1402 -0
- interlock_fiduciary-1.0.0/src/fiduciary/binding.py +629 -0
- interlock_fiduciary-1.0.0/src/fiduciary/bridge.py +1522 -0
- interlock_fiduciary-1.0.0/src/fiduciary/bundle/__init__.py +24 -0
- interlock_fiduciary-1.0.0/src/fiduciary/bundle/export.py +579 -0
- interlock_fiduciary-1.0.0/src/fiduciary/bundle/format.py +164 -0
- interlock_fiduciary-1.0.0/src/fiduciary/bundle/verify.py +1169 -0
- interlock_fiduciary-1.0.0/src/fiduciary/checkers.py +160 -0
- interlock_fiduciary-1.0.0/src/fiduciary/cli.py +1465 -0
- interlock_fiduciary-1.0.0/src/fiduciary/compiler.py +733 -0
- interlock_fiduciary-1.0.0/src/fiduciary/config.py +920 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/__init__.py +95 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/_base.py +149 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/approval.py +114 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/charter.py +158 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/mandate.py +1373 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/record.py +138 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/ticket.py +1021 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/tool.py +391 -0
- interlock_fiduciary-1.0.0/src/fiduciary/documents/warrant.py +256 -0
- interlock_fiduciary-1.0.0/src/fiduciary/escalation.py +706 -0
- interlock_fiduciary-1.0.0/src/fiduciary/exceptions.py +85 -0
- interlock_fiduciary-1.0.0/src/fiduciary/executor.py +975 -0
- interlock_fiduciary-1.0.0/src/fiduciary/fidu1.py +432 -0
- interlock_fiduciary-1.0.0/src/fiduciary/keys.py +130 -0
- interlock_fiduciary-1.0.0/src/fiduciary/log.py +273 -0
- interlock_fiduciary-1.0.0/src/fiduciary/mcp.py +749 -0
- interlock_fiduciary-1.0.0/src/fiduciary/postgres.py +372 -0
- interlock_fiduciary-1.0.0/src/fiduciary/py.typed +0 -0
- interlock_fiduciary-1.0.0/src/fiduciary/refines.py +508 -0
- interlock_fiduciary-1.0.0/src/fiduciary/service.py +955 -0
- interlock_fiduciary-1.0.0/src/fiduciary/sqlite.py +303 -0
- interlock_fiduciary-1.0.0/src/fiduciary/store.py +787 -0
- interlock_fiduciary-1.0.0/src/fiduciary/tools.py +182 -0
- interlock_fiduciary-1.0.0/src/fiduciary/verify.py +252 -0
- interlock_fiduciary-1.0.0/tests/__init__.py +0 -0
- interlock_fiduciary-1.0.0/tests/bound.py +385 -0
- interlock_fiduciary-1.0.0/tests/bridge_kit.py +178 -0
- interlock_fiduciary-1.0.0/tests/bundle_kit.py +136 -0
- interlock_fiduciary-1.0.0/tests/compiled_digests.py +30 -0
- interlock_fiduciary-1.0.0/tests/conftest.py +218 -0
- interlock_fiduciary-1.0.0/tests/contention_child.py +57 -0
- interlock_fiduciary-1.0.0/tests/crash_child.py +44 -0
- interlock_fiduciary-1.0.0/tests/crash_env.py +425 -0
- interlock_fiduciary-1.0.0/tests/deploy.py +55 -0
- interlock_fiduciary-1.0.0/tests/examples.py +518 -0
- interlock_fiduciary-1.0.0/tests/fakes.py +130 -0
- interlock_fiduciary-1.0.0/tests/serve_kit.py +248 -0
- interlock_fiduciary-1.0.0/tests/test_adversarial_agent.py +234 -0
- interlock_fiduciary-1.0.0/tests/test_authority.py +468 -0
- interlock_fiduciary-1.0.0/tests/test_binding.py +731 -0
- interlock_fiduciary-1.0.0/tests/test_bridge.py +456 -0
- interlock_fiduciary-1.0.0/tests/test_bridge_edges.py +370 -0
- interlock_fiduciary-1.0.0/tests/test_bridge_lifecycle.py +227 -0
- interlock_fiduciary-1.0.0/tests/test_bundle.py +84 -0
- interlock_fiduciary-1.0.0/tests/test_bundle_checks.py +724 -0
- interlock_fiduciary-1.0.0/tests/test_bundle_export.py +128 -0
- interlock_fiduciary-1.0.0/tests/test_bundle_tamper.py +269 -0
- interlock_fiduciary-1.0.0/tests/test_bundle_vectors.py +52 -0
- interlock_fiduciary-1.0.0/tests/test_cli.py +512 -0
- interlock_fiduciary-1.0.0/tests/test_cli_binding.py +375 -0
- interlock_fiduciary-1.0.0/tests/test_cli_bundle.py +182 -0
- interlock_fiduciary-1.0.0/tests/test_cli_mcp.py +359 -0
- interlock_fiduciary-1.0.0/tests/test_cli_tickets.py +127 -0
- interlock_fiduciary-1.0.0/tests/test_cluster.py +292 -0
- interlock_fiduciary-1.0.0/tests/test_compiler.py +453 -0
- interlock_fiduciary-1.0.0/tests/test_config.py +359 -0
- interlock_fiduciary-1.0.0/tests/test_contention.py +218 -0
- interlock_fiduciary-1.0.0/tests/test_crash_recovery.py +271 -0
- interlock_fiduciary-1.0.0/tests/test_decide.py +491 -0
- interlock_fiduciary-1.0.0/tests/test_determinism.py +64 -0
- interlock_fiduciary-1.0.0/tests/test_documents.py +633 -0
- interlock_fiduciary-1.0.0/tests/test_escalation_quorum.py +950 -0
- interlock_fiduciary-1.0.0/tests/test_executor.py +1293 -0
- interlock_fiduciary-1.0.0/tests/test_fidu1.py +315 -0
- interlock_fiduciary-1.0.0/tests/test_ilok1_sizes.py +74 -0
- interlock_fiduciary-1.0.0/tests/test_live_acceptance.py +221 -0
- interlock_fiduciary-1.0.0/tests/test_mcp.py +572 -0
- interlock_fiduciary-1.0.0/tests/test_monotonicity.py +345 -0
- interlock_fiduciary-1.0.0/tests/test_postgres.py +178 -0
- interlock_fiduciary-1.0.0/tests/test_readme.py +42 -0
- interlock_fiduciary-1.0.0/tests/test_refines.py +1211 -0
- interlock_fiduciary-1.0.0/tests/test_resolve.py +523 -0
- interlock_fiduciary-1.0.0/tests/test_security_audit.py +68 -0
- interlock_fiduciary-1.0.0/tests/test_service.py +382 -0
- interlock_fiduciary-1.0.0/tests/test_sessions.py +182 -0
- interlock_fiduciary-1.0.0/tests/test_signers.py +97 -0
- interlock_fiduciary-1.0.0/tests/test_soak.py +51 -0
- interlock_fiduciary-1.0.0/tests/test_state.py +236 -0
- interlock_fiduciary-1.0.0/tests/test_store.py +395 -0
- interlock_fiduciary-1.0.0/tests/test_tamper.py +409 -0
- interlock_fiduciary-1.0.0/tests/test_tamper_escalation.py +322 -0
- interlock_fiduciary-1.0.0/tests/test_tickets_warrants.py +387 -0
- interlock_fiduciary-1.0.0/tests/test_tools.py +89 -0
- interlock_fiduciary-1.0.0/tests/test_upgrade.py +223 -0
- interlock_fiduciary-1.0.0/tests/test_vectors.py +248 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.1.0/fiduciary.sql +48 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.1.0/ledger.sql +86 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.1.0/manifest.json +5 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.1.0/postgres.json +39 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/chains/24115ee4-600f-462b-b58d-d57309c62ad5.chain +0 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/chains/2d0b5f7e-8a43-4c2b-b1a4-0c4e2f9a7d31.chain +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/fiduciary.sql +66 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/ledger.sql +106 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/manifest.json +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/postgres.json +40 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/receipts.jsonl +1 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/tools/675784cb90ac4a1e109e487781a9db86c87d5aed2886a8a43baaf60f5d1a74f6.json +29 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.2.0/tools/da3867841890b66c16218628550d133c2ad3a270a7283eefab80110679d87d41.json +83 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/chains/0f7222eb-e65e-4832-939b-a1a7126a44f0.chain +0 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/chains/2d0b5f7e-8a43-4c2b-b1a4-0c4e2f9a7d31.chain +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/fiduciary.sql +88 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/ledger.sql +112 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/manifest.json +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/operators.jsonl +2 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/postgres.json +43 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/receipts.jsonl +1 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/tools/675784cb90ac4a1e109e487781a9db86c87d5aed2886a8a43baaf60f5d1a74f6.json +29 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.3.0/tools/da3867841890b66c16218628550d133c2ad3a270a7283eefab80110679d87d41.json +83 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/chains/2d0b5f7e-8a43-4c2b-b1a4-0c4e2f9a7d31.chain +12 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/chains/4ecba1eb-7db4-45c2-8324-f73940563e09.chain +0 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/fiduciary.sql +93 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/ledger.sql +120 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/manifest.json +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/operators.jsonl +2 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/postgres.json +44 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/receipts.jsonl +2 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/tools/675784cb90ac4a1e109e487781a9db86c87d5aed2886a8a43baaf60f5d1a74f6.json +29 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/tools/9595bcef244b5c75b978983e33c746b9df31895acde67551b9e70edd32ad8888.json +66 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/tools/b06cf07de22be069688bd2816074439ad46e03e0d63d8a971a6a5da1de16135e.json +81 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.4.0/tools/da3867841890b66c16218628550d133c2ad3a270a7283eefab80110679d87d41.json +83 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/chains/2d0b5f7e-8a43-4c2b-b1a4-0c4e2f9a7d31.chain +12 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/chains/77b04b25-c6b3-4348-ab04-1345e061027a.chain +0 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/fiduciary.sql +93 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/ledger.sql +120 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/manifest.json +6 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/operators.jsonl +2 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/postgres.json +44 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/receipts.jsonl +2 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/tools/675784cb90ac4a1e109e487781a9db86c87d5aed2886a8a43baaf60f5d1a74f6.json +29 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/tools/9595bcef244b5c75b978983e33c746b9df31895acde67551b9e70edd32ad8888.json +66 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/tools/b06cf07de22be069688bd2816074439ad46e03e0d63d8a971a6a5da1de16135e.json +81 -0
- interlock_fiduciary-1.0.0/tests/upgrades/0.5.0/tools/da3867841890b66c16218628550d133c2ad3a270a7283eefab80110679d87d41.json +83 -0
- interlock_fiduciary-1.0.0/tests/upstream_server.py +64 -0
- interlock_fiduciary-1.0.0/uv.lock +1113 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/index.json +838 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/unreadable-not-a-tar.fidb +64 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v1-byte-changed.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v1-member-deleted.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v1-member-duplicated.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v1-members-out-of-order.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v10-unanchored-record.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v11-commit-after-revocation.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v12-records-ahead-of-the-ledger.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v2-wrong-pinned-charter.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v3-child-broader-than-parent.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v3-mandate-one-approval-short.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v4-other-deployment.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v5-other-receipt-key.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v6-other-ledger-key.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v6-witness-never-cosigned.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v7-break-glass-release.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v7-manual-release.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v7-raw-reset.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v7-unmandated-delegation.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v7-unmandated-plan.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v8-executed-after-not-after.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v8-false-rule-predicate.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v8-head-moved.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v8-warrant-one-approval-short.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v9-log-edited-manifest-rewritten.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v9-manifest-signed-by-another.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/v9-other-service-key.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/valid-held-release.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/valid-lineage-at-work.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/bundles/valid-phase-4-lifecycle.fidb +0 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/invalid.json +2834 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/records.json +83 -0
- interlock_fiduciary-1.0.0/vectors/fidu1/valid.json +816 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
workflow_call: # release.yml runs every check before it builds
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
name: test (py${{ matrix.python-version }}, ${{ matrix.os }})
|
|
20
|
+
runs-on: ${{ matrix.os }}
|
|
21
|
+
timeout-minutes: 30
|
|
22
|
+
env:
|
|
23
|
+
UV_PYTHON: ${{ matrix.python-version }}
|
|
24
|
+
strategy:
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
28
|
+
os: [ubuntu-latest]
|
|
29
|
+
include:
|
|
30
|
+
# SQLite's file locking differs by platform, and the store claims a
|
|
31
|
+
# log's single writer with a lock beside the file.
|
|
32
|
+
- python-version: "3.12"
|
|
33
|
+
os: macos-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: astral-sh/setup-uv@v5
|
|
37
|
+
with:
|
|
38
|
+
enable-cache: true
|
|
39
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
40
|
+
run: uv python install ${{ matrix.python-version }}
|
|
41
|
+
# Interlock and AgentGov resolve from PyPI, pinned in uv.lock; --frozen
|
|
42
|
+
# fails a dependency edit that was not re-locked.
|
|
43
|
+
- name: Install the project
|
|
44
|
+
run: uv sync --frozen --python ${{ matrix.python-version }}
|
|
45
|
+
- name: Lint (ruff check)
|
|
46
|
+
run: uv run ruff check .
|
|
47
|
+
- name: Format (ruff format --check)
|
|
48
|
+
run: uv run ruff format --check .
|
|
49
|
+
- name: Type-check the package (mypy --strict)
|
|
50
|
+
run: uv run mypy src/
|
|
51
|
+
- name: Type-check the tests and scripts (mypy --strict)
|
|
52
|
+
run: uv run mypy --strict tests/ scripts/
|
|
53
|
+
- name: The golden vectors are what the generator writes
|
|
54
|
+
run: |
|
|
55
|
+
uv run python scripts/make_vectors.py
|
|
56
|
+
git diff --exit-code vectors/
|
|
57
|
+
- name: The spec's ILOK1 sizes are what interlock signs (F3-9)
|
|
58
|
+
run: uv run python scripts/ilok1_sizes.py --check
|
|
59
|
+
- name: Tests with coverage
|
|
60
|
+
run: uv run pytest -v --cov=fiduciary --cov-branch --cov-report=term-missing
|
|
61
|
+
# postgres.py runs only against a server, which this job has none of; the
|
|
62
|
+
# postgres job below measures everything against the higher floors.
|
|
63
|
+
- name: Enforce coverage floor
|
|
64
|
+
run: uv run coverage report --fail-under=90 --omit=src/fiduciary/postgres.py
|
|
65
|
+
|
|
66
|
+
postgres:
|
|
67
|
+
name: test against PostgreSQL ${{ matrix.postgres }} (py3.12)
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
timeout-minutes: 30
|
|
70
|
+
strategy:
|
|
71
|
+
fail-fast: false
|
|
72
|
+
matrix:
|
|
73
|
+
postgres: ["14", "16", "18"]
|
|
74
|
+
services:
|
|
75
|
+
postgres:
|
|
76
|
+
image: postgres:${{ matrix.postgres }}
|
|
77
|
+
env:
|
|
78
|
+
POSTGRES_USER: fiduciary_admin
|
|
79
|
+
POSTGRES_PASSWORD: fiduciary
|
|
80
|
+
ports: ["5432:5432"]
|
|
81
|
+
options: >-
|
|
82
|
+
--health-cmd "pg_isready -U fiduciary_admin"
|
|
83
|
+
--health-interval 2s --health-timeout 5s --health-retries 30
|
|
84
|
+
env:
|
|
85
|
+
UV_PYTHON: "3.12"
|
|
86
|
+
FIDUCIARY_TEST_POSTGRES_DSN: postgresql://fiduciary_admin:fiduciary@localhost:5432/postgres
|
|
87
|
+
FIDUCIARY_REQUIRE_POSTGRES: "1"
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/checkout@v4
|
|
90
|
+
- uses: astral-sh/setup-uv@v5
|
|
91
|
+
with:
|
|
92
|
+
enable-cache: true
|
|
93
|
+
- run: uv python install 3.12
|
|
94
|
+
- run: uv sync --frozen --python 3.12
|
|
95
|
+
- name: Tests with coverage, both stores
|
|
96
|
+
run: uv run pytest -v --cov=fiduciary --cov-branch --cov-report=term-missing --cov-report=json
|
|
97
|
+
# The floors: 95% of lines and 90% of branches, measured apart.
|
|
98
|
+
- name: Enforce coverage floors
|
|
99
|
+
run: |
|
|
100
|
+
uv run python - <<'EOF'
|
|
101
|
+
import json, sys
|
|
102
|
+
totals = json.load(open("coverage.json"))["totals"]
|
|
103
|
+
lines = 100 * totals["covered_lines"] / totals["num_statements"]
|
|
104
|
+
branches = 100 * totals["covered_branches"] / totals["num_branches"]
|
|
105
|
+
print(f"lines {lines:.2f}%, branches {branches:.2f}%")
|
|
106
|
+
sys.exit(0 if lines >= 95 and branches >= 90 else 1)
|
|
107
|
+
EOF
|
|
108
|
+
|
|
109
|
+
upstream:
|
|
110
|
+
# The fixes of the spec's section 12 land on interlock's and AgentGov's main
|
|
111
|
+
# before a release. Here the tests that need them run, and those of each
|
|
112
|
+
# fallback skip: the jobs above hold the fallbacks, on the releases uv.lock pins.
|
|
113
|
+
name: test against interlock and AgentGov main (py3.12, PostgreSQL 16)
|
|
114
|
+
runs-on: ubuntu-latest
|
|
115
|
+
timeout-minutes: 30
|
|
116
|
+
services:
|
|
117
|
+
postgres:
|
|
118
|
+
image: postgres:16
|
|
119
|
+
env:
|
|
120
|
+
POSTGRES_USER: fiduciary_admin
|
|
121
|
+
POSTGRES_PASSWORD: fiduciary
|
|
122
|
+
ports: ["5432:5432"]
|
|
123
|
+
options: >-
|
|
124
|
+
--health-cmd "pg_isready -U fiduciary_admin"
|
|
125
|
+
--health-interval 2s --health-timeout 5s --health-retries 30
|
|
126
|
+
env:
|
|
127
|
+
UV_PYTHON: "3.12"
|
|
128
|
+
FIDUCIARY_TEST_POSTGRES_DSN: postgresql://fiduciary_admin:fiduciary@localhost:5432/postgres
|
|
129
|
+
FIDUCIARY_REQUIRE_POSTGRES: "1"
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/checkout@v4
|
|
132
|
+
- uses: astral-sh/setup-uv@v5
|
|
133
|
+
with:
|
|
134
|
+
enable-cache: true
|
|
135
|
+
- run: uv python install 3.12
|
|
136
|
+
- run: uv sync --frozen --python 3.12
|
|
137
|
+
- name: Install interlock and AgentGov from main
|
|
138
|
+
run: >-
|
|
139
|
+
uv pip install --python .venv/bin/python
|
|
140
|
+
"interlock-agentgov @ git+https://github.com/crimsondevil0929/agentgov@main"
|
|
141
|
+
"interlock-escrow @ git+https://github.com/crimsondevil0929/interlock@main"
|
|
142
|
+
- name: Type-check the package against them (mypy --strict)
|
|
143
|
+
run: uv run --no-sync mypy src/
|
|
144
|
+
- name: Tests, both stores
|
|
145
|
+
run: uv run --no-sync pytest -v
|
|
146
|
+
|
|
147
|
+
build:
|
|
148
|
+
name: build (wheel + sdist)
|
|
149
|
+
runs-on: ubuntu-latest
|
|
150
|
+
steps:
|
|
151
|
+
- uses: actions/checkout@v4
|
|
152
|
+
- uses: astral-sh/setup-uv@v5
|
|
153
|
+
- run: uv build -o "${{ runner.temp }}/dist" > "${{ runner.temp }}/build.log" 2>&1 || (cat "${{ runner.temp }}/build.log"; exit 1)
|
|
154
|
+
- name: Install the wheel into a bare environment
|
|
155
|
+
run: |
|
|
156
|
+
uv venv "${{ runner.temp }}/bare" --python 3.12
|
|
157
|
+
uv pip install --python "${{ runner.temp }}/bare/bin/python" "${{ runner.temp }}"/dist/*.whl
|
|
158
|
+
"${{ runner.temp }}/bare/bin/fiduciary" --version
|
|
159
|
+
"${{ runner.temp }}/bare/bin/python" -W error -c "import fiduciary.cli, fiduciary.postgres, fiduciary.verify"
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# On a version tag: every check of ci.yml, then the wheel and the sdist, built
|
|
4
|
+
# once, published to PyPI by trusted publishing: no API token exists anywhere,
|
|
5
|
+
# PyPI exchanges this workflow's OIDC identity for a short-lived one. Every
|
|
6
|
+
# distribution carries a PEP 740 attestation (PyPI shows and verifies it) and a
|
|
7
|
+
# GitHub build provenance attestation (`gh attestation verify`), and the GitHub
|
|
8
|
+
# release carries a CycloneDX SBOM of everything the package and its extras
|
|
9
|
+
# install: the pipeline of interlock-escrow and interlock-agentgov.
|
|
10
|
+
#
|
|
11
|
+
# Before the first release, register this repository, this workflow
|
|
12
|
+
# (release.yml) and the `pypi` environment as a trusted publisher of
|
|
13
|
+
# interlock-fiduciary on PyPI, and give the environment required reviewers.
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
push:
|
|
17
|
+
tags: ["v*"]
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
checks:
|
|
24
|
+
name: every check
|
|
25
|
+
uses: ./.github/workflows/ci.yml
|
|
26
|
+
|
|
27
|
+
build:
|
|
28
|
+
name: build the distributions and their SBOM
|
|
29
|
+
needs: checks
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Install uv
|
|
35
|
+
uses: astral-sh/setup-uv@v5
|
|
36
|
+
|
|
37
|
+
- name: The tag names the version in pyproject.toml and fiduciary.__version__
|
|
38
|
+
run: |
|
|
39
|
+
declared=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
|
|
40
|
+
module=$(python3 -c "import ast; tree = ast.parse(open('src/fiduciary/__init__.py').read()); print(next(n.value.value for n in tree.body if isinstance(n, ast.Assign) and any(getattr(t, 'id', '') == '__version__' for t in n.targets)))")
|
|
41
|
+
if [ "v$declared" != "$GITHUB_REF_NAME" ] || [ "$module" != "$declared" ]; then
|
|
42
|
+
echo "::error::tag $GITHUB_REF_NAME, pyproject.toml $declared, fiduciary.__version__ $module"
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
- name: Build, failing on packaging warnings
|
|
47
|
+
run: |
|
|
48
|
+
set -o pipefail
|
|
49
|
+
# The log goes outside the checkout: the sdist packs the source tree.
|
|
50
|
+
uv build 2>&1 | tee "${{ runner.temp }}/build.log"
|
|
51
|
+
if grep -i '^warning' "${{ runner.temp }}/build.log"; then
|
|
52
|
+
echo "::error::uv build emitted packaging warnings"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
- name: The wheel installs into a bare environment and runs
|
|
57
|
+
run: |
|
|
58
|
+
uv venv "${{ runner.temp }}/bare" --python 3.12
|
|
59
|
+
uv pip install --python "${{ runner.temp }}/bare/bin/python" dist/*.whl
|
|
60
|
+
"${{ runner.temp }}/bare/bin/fiduciary" --version
|
|
61
|
+
|
|
62
|
+
# Every package `pip install 'interlock-fiduciary[...]'` can bring in, at
|
|
63
|
+
# the versions this release was tested with (uv.lock).
|
|
64
|
+
- name: Describe the dependencies (CycloneDX)
|
|
65
|
+
run: |
|
|
66
|
+
mkdir sbom
|
|
67
|
+
uv export --frozen --no-dev --all-extras --no-emit-project --no-hashes \
|
|
68
|
+
--format requirements-txt --output-file sbom/requirements.txt
|
|
69
|
+
uvx --from cyclonedx-bom==7.4.0 cyclonedx-py requirements sbom/requirements.txt \
|
|
70
|
+
--output-format JSON --output-file "sbom/interlock-fiduciary-${GITHUB_REF_NAME#v}.cdx.json"
|
|
71
|
+
|
|
72
|
+
- uses: actions/upload-artifact@v4
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: dist/
|
|
76
|
+
|
|
77
|
+
- uses: actions/upload-artifact@v4
|
|
78
|
+
with:
|
|
79
|
+
name: sbom
|
|
80
|
+
path: sbom/
|
|
81
|
+
|
|
82
|
+
publish:
|
|
83
|
+
name: publish to PyPI
|
|
84
|
+
needs: build
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
environment:
|
|
87
|
+
name: pypi
|
|
88
|
+
url: https://pypi.org/project/interlock-fiduciary/
|
|
89
|
+
permissions:
|
|
90
|
+
id-token: write # trusted publishing, and signing the attestations
|
|
91
|
+
attestations: write
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/download-artifact@v4
|
|
94
|
+
with:
|
|
95
|
+
name: dist
|
|
96
|
+
path: dist/
|
|
97
|
+
|
|
98
|
+
- name: Attest the distributions' build provenance
|
|
99
|
+
uses: actions/attest-build-provenance@v1
|
|
100
|
+
with:
|
|
101
|
+
subject-path: dist/*
|
|
102
|
+
|
|
103
|
+
- name: Publish, with a PEP 740 attestation for each file
|
|
104
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
105
|
+
with:
|
|
106
|
+
attestations: true
|
|
107
|
+
|
|
108
|
+
github-release:
|
|
109
|
+
name: GitHub release, with the SBOM
|
|
110
|
+
needs: publish
|
|
111
|
+
runs-on: ubuntu-latest
|
|
112
|
+
permissions:
|
|
113
|
+
contents: write
|
|
114
|
+
steps:
|
|
115
|
+
- uses: actions/checkout@v4
|
|
116
|
+
|
|
117
|
+
- uses: actions/download-artifact@v4
|
|
118
|
+
with:
|
|
119
|
+
path: assets/
|
|
120
|
+
|
|
121
|
+
- name: Create the release from the tag
|
|
122
|
+
env:
|
|
123
|
+
GH_TOKEN: ${{ github.token }}
|
|
124
|
+
run: |
|
|
125
|
+
prerelease=""
|
|
126
|
+
if [[ "$GITHUB_REF_NAME" =~ (a|b|rc)[0-9]+$ ]]; then prerelease="--prerelease"; fi
|
|
127
|
+
gh release create "$GITHUB_REF_NAME" --verify-tag --generate-notes $prerelease \
|
|
128
|
+
--title "interlock-fiduciary ${GITHUB_REF_NAME#v}" assets/dist/* assets/sbom/*.cdx.json
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Python build and bytecode
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
|
|
12
|
+
# Tooling caches
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
.coverage.*
|
|
18
|
+
htmlcov/
|
|
19
|
+
.hypothesis/
|
|
20
|
+
|
|
21
|
+
# Logs, such as a build's: the sdist packs whatever is not ignored
|
|
22
|
+
*.log
|
|
23
|
+
|
|
24
|
+
# Stores and keys made by hand while trying the command line
|
|
25
|
+
*.db
|
|
26
|
+
*.db-wal
|
|
27
|
+
*.db-shm
|
|
28
|
+
*.key
|
|
29
|
+
|
|
30
|
+
# OS metadata
|
|
31
|
+
.DS_Store
|
|
32
|
+
|
|
33
|
+
# The live acceptance suite's key, and its runs: never committed, never packed
|
|
34
|
+
.env.benchmark
|
|
35
|
+
live-run/
|
|
36
|
+
|
|
37
|
+
# The soak's runs (scripts/live_stress_test.py --out): never committed, never packed
|
|
38
|
+
soak/
|