matrixscroll 0.1.1__tar.gz → 0.2.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.
Files changed (74) hide show
  1. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/CHANGELOG.md +25 -0
  2. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/PKG-INFO +35 -4
  3. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/README.md +32 -3
  4. matrixscroll-0.2.0/docs/hardware-provider.md +20 -0
  5. matrixscroll-0.2.0/docs/quickstart-git.md +61 -0
  6. matrixscroll-0.2.0/docs/superpowers/plans/2026-06-19-ci-action-plan.md +88 -0
  7. matrixscroll-0.2.0/docs/superpowers/plans/2026-06-19-sdk-refactor-plan.md +166 -0
  8. matrixscroll-0.2.0/docs/superpowers/specs/2026-06-19-matrixscroll-git-design.md +205 -0
  9. matrixscroll-0.2.0/docs/yubikey-bridge.md +137 -0
  10. matrixscroll-0.2.0/examples/agentic_ai_evidence_manifest.signed.json +80 -0
  11. matrixscroll-0.2.0/examples/ci/protected-branch.yml +38 -0
  12. matrixscroll-0.2.0/examples/commit-envelope.json +29 -0
  13. matrixscroll-0.2.0/examples/commit-envelope.signed.json +38 -0
  14. matrixscroll-0.2.0/examples/demo/agent-commit-demo.sh +46 -0
  15. matrixscroll-0.2.0/examples/demo/generate_signed_examples.py +32 -0
  16. matrixscroll-0.2.0/examples/release-manifest.json +24 -0
  17. matrixscroll-0.2.0/examples/release-manifest.signed.json +33 -0
  18. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/matrixscroll/__init__.py +1 -1
  19. matrixscroll-0.2.0/matrixscroll/_core.py +43 -0
  20. matrixscroll-0.2.0/matrixscroll/canonical.py +18 -0
  21. matrixscroll-0.2.0/matrixscroll/cli.py +178 -0
  22. matrixscroll-0.2.0/matrixscroll/constants.py +12 -0
  23. matrixscroll-0.2.0/matrixscroll/errors.py +11 -0
  24. matrixscroll-0.2.0/matrixscroll/git.py +376 -0
  25. matrixscroll-0.2.0/matrixscroll/hooks/post-commit +17 -0
  26. matrixscroll-0.2.0/matrixscroll/hooks/pre-push +17 -0
  27. matrixscroll-0.2.0/matrixscroll/manifest.py +59 -0
  28. matrixscroll-0.2.0/matrixscroll/policy.py +55 -0
  29. matrixscroll-0.2.0/matrixscroll/providers/__init__.py +7 -0
  30. matrixscroll-0.2.0/matrixscroll/providers/base.py +26 -0
  31. matrixscroll-0.2.0/matrixscroll/providers/emulated.py +116 -0
  32. matrixscroll-0.2.0/matrixscroll/providers/hardware.py +22 -0
  33. matrixscroll-0.2.0/matrixscroll/providers/registry.py +106 -0
  34. matrixscroll-0.2.0/matrixscroll/providers/yubikey.py +104 -0
  35. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/pyproject.toml +4 -1
  36. matrixscroll-0.2.0/schemas/commit-envelope.v1.json +150 -0
  37. matrixscroll-0.2.0/schemas/evidence-pack.v1.json +54 -0
  38. matrixscroll-0.2.0/schemas/release-manifest.v1.json +63 -0
  39. matrixscroll-0.2.0/tests/test_canonical.py +10 -0
  40. matrixscroll-0.2.0/tests/test_git_envelope.py +88 -0
  41. matrixscroll-0.2.0/tests/test_policy.py +26 -0
  42. matrixscroll-0.2.0/tests/test_yubikey_provider.py +35 -0
  43. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/_fixture_key.json +5 -5
  44. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_algorithm.json +13 -13
  45. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_device_id.json +13 -13
  46. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_field.json +13 -13
  47. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_nested.json +28 -28
  48. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_public_key.json +13 -13
  49. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_schema.json +13 -13
  50. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_signature.json +13 -13
  51. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/unsigned_empty_block.json +6 -6
  52. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/unsigned_no_block.json +4 -4
  53. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_nested.json +28 -28
  54. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_simple.json +13 -13
  55. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_unicode.json +14 -14
  56. matrixscroll-0.1.1/matrixscroll/_core.py +0 -360
  57. matrixscroll-0.1.1/matrixscroll/cli.py +0 -94
  58. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/.gitignore +0 -0
  59. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/CONTRIBUTING.md +0 -0
  60. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/LICENSE +0 -0
  61. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/SECURITY.md +0 -0
  62. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/SPEC.md +0 -0
  63. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/controls/agentic_ai_controls.json +0 -0
  64. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/docs/AGENTIC_AI_SECURITY.md +0 -0
  65. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/examples/agentic_ai_evidence_manifest.json +0 -0
  66. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/matrixscroll/py.typed +0 -0
  67. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/__init__.py +0 -0
  68. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_agentic_guidance.py +0 -0
  69. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_cli.py +0 -0
  70. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_core.py +0 -0
  71. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_release_metadata.py +0 -0
  72. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_vectors.py +0 -0
  73. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/README.md +0 -0
  74. {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/_generate.py +0 -0
@@ -4,6 +4,30 @@ All notable changes to the Matrix Scroll Python SDK are documented here. The
4
4
  format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
5
  this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.2.0] - 2026-06-20
8
+
9
+ Agent provenance release: Git commit envelopes, SDK module split, CI scaffolding.
10
+
11
+ ### Added
12
+ - **Git integration** — `matrixscroll/git.py` with post-commit envelope signing
13
+ and pre-push verification for commits being pushed.
14
+ - **Hook installer** — `matrixscroll hook-install` / `matrixscroll hook-status`
15
+ (hooks ship inside the wheel at `matrixscroll/hooks/`).
16
+ - **Commit envelope schema** — `schemas/commit-envelope.v1.json` plus release and
17
+ evidence-pack schemas under `schemas/`.
18
+ - **Signed examples** — `examples/*.signed.json` for CI and documentation.
19
+ - **Agent demo** — `examples/demo/agent-commit-demo.sh` and signed-example generator.
20
+ - **SDK split** — `canonical.py`, `manifest.py`, `policy.py`, `providers/` with
21
+ `_core.py` retained as a compatibility shim.
22
+ - **Policy verification** — `verify_manifest_with_policy()` for mode and trusted-key gates.
23
+ - **YubiKey prototype** — `providers/yubikey.py` boundary (`MATRIXSCROLL_MODE=yubikey`).
24
+ - **CI** — `verify-manifest` workflow and protected-branch example using
25
+ `SSX360/matrixscroll-verify-action@v1`.
26
+
27
+ ### Changed
28
+ - CLI adds `envelope`, `envelope-verify`, and hook subcommands.
29
+ - Commit envelopes bind to the **actual** commit SHA via post-commit signing.
30
+
7
31
  ## [0.1.1] - 2026-06-19
8
32
 
9
33
  Copy and citation hardening patch. No protocol or API changes.
@@ -44,5 +68,6 @@ Initial public release. Extracted from the SSX360 reference implementation.
44
68
  - Device id format: `MS-XXXX-XXXX` (SHA-256 of the raw public key, first 8 hex
45
69
  chars, uppercase).
46
70
 
71
+ [0.2.0]: https://github.com/SSX360/matrixscroll/releases/tag/v0.2.0
47
72
  [0.1.1]: https://github.com/SSX360/matrixscroll/releases/tag/v0.1.1
48
73
  [0.1.0]: https://github.com/SSX360/matrixscroll/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrixscroll
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Open protocol for signing AI-assisted code provenance with Ed25519; shipping software root of trust with SSX360 hardware support in progress.
5
5
  Project-URL: Homepage, https://matrixscroll.com
6
6
  Project-URL: Documentation, https://matrixscroll.com/docs
@@ -31,6 +31,8 @@ Requires-Dist: cryptography>=41.0
31
31
  Provides-Extra: dev
32
32
  Requires-Dist: build>=1.0; extra == 'dev'
33
33
  Requires-Dist: pytest>=7.4; extra == 'dev'
34
+ Provides-Extra: git
35
+ Provides-Extra: yubikey
34
36
  Description-Content-Type: text/markdown
35
37
 
36
38
  # Matrix Scroll
@@ -39,9 +41,9 @@ Description-Content-Type: text/markdown
39
41
 
40
42
  Every AI-generated change in your IDE can be cryptographically signed by an
41
43
  Ed25519 identity and verified offline with a public key and one command. The
42
- v0.1.x reference implementation ships a well-tested software root of trust;
43
- SSX360/NXP SE050 hardware signing is the compatible reference-device path in
44
- progress.
44
+ v0.2.x reference implementation ships a well-tested software root of trust
45
+ with Git commit-envelope hooks; SSX360/NXP SE050 hardware signing is the
46
+ compatible reference-device path in progress.
45
47
 
46
48
  - 📜 **Spec:** [`SPEC.md`](SPEC.md) — wire format, canonical encoding, schemas.
47
49
  - 🛡 **Agentic AI controls:** [`docs/AGENTIC_AI_SECURITY.md`](docs/AGENTIC_AI_SECURITY.md)
@@ -72,6 +74,35 @@ signed = matrixscroll.sign_manifest({"release": "v1.0.0", "artifacts": [...]})
72
74
  assert matrixscroll.verify_manifest(signed)
73
75
  ```
74
76
 
77
+ ## Agent provenance for Git commits
78
+
79
+ When an AI agent (Cursor, Claude Code, Copilot, etc.) produces a commit, Matrix
80
+ Scroll attaches a signed **commit envelope** with actor, tool, and scope metadata.
81
+ Verify in CI without trusting the IDE.
82
+
83
+ ```bash
84
+ pip install matrixscroll
85
+ matrixscroll hook-install
86
+
87
+ export MATRIXSCROLL_ACTOR_TYPE=agent
88
+ export MATRIXSCROLL_TOOL=cursor
89
+ git commit -m "feat: agent-assisted change"
90
+
91
+ matrixscroll envelope-verify "$(git rev-parse HEAD)"
92
+ ```
93
+
94
+ See [`docs/quickstart-git.md`](docs/quickstart-git.md) and run
95
+ [`examples/demo/agent-commit-demo.sh`](examples/demo/agent-commit-demo.sh).
96
+
97
+ ### CI verify
98
+
99
+ ```yaml
100
+ - uses: SSX360/matrixscroll-verify-action@v1
101
+ with:
102
+ manifest: examples/agentic_ai_evidence_manifest.signed.json
103
+ matrixscroll-version: "0.2.0"
104
+ ```
105
+
75
106
  ## CLI
76
107
 
77
108
  ```bash
@@ -4,9 +4,9 @@
4
4
 
5
5
  Every AI-generated change in your IDE can be cryptographically signed by an
6
6
  Ed25519 identity and verified offline with a public key and one command. The
7
- v0.1.x reference implementation ships a well-tested software root of trust;
8
- SSX360/NXP SE050 hardware signing is the compatible reference-device path in
9
- progress.
7
+ v0.2.x reference implementation ships a well-tested software root of trust
8
+ with Git commit-envelope hooks; SSX360/NXP SE050 hardware signing is the
9
+ compatible reference-device path in progress.
10
10
 
11
11
  - 📜 **Spec:** [`SPEC.md`](SPEC.md) — wire format, canonical encoding, schemas.
12
12
  - 🛡 **Agentic AI controls:** [`docs/AGENTIC_AI_SECURITY.md`](docs/AGENTIC_AI_SECURITY.md)
@@ -37,6 +37,35 @@ signed = matrixscroll.sign_manifest({"release": "v1.0.0", "artifacts": [...]})
37
37
  assert matrixscroll.verify_manifest(signed)
38
38
  ```
39
39
 
40
+ ## Agent provenance for Git commits
41
+
42
+ When an AI agent (Cursor, Claude Code, Copilot, etc.) produces a commit, Matrix
43
+ Scroll attaches a signed **commit envelope** with actor, tool, and scope metadata.
44
+ Verify in CI without trusting the IDE.
45
+
46
+ ```bash
47
+ pip install matrixscroll
48
+ matrixscroll hook-install
49
+
50
+ export MATRIXSCROLL_ACTOR_TYPE=agent
51
+ export MATRIXSCROLL_TOOL=cursor
52
+ git commit -m "feat: agent-assisted change"
53
+
54
+ matrixscroll envelope-verify "$(git rev-parse HEAD)"
55
+ ```
56
+
57
+ See [`docs/quickstart-git.md`](docs/quickstart-git.md) and run
58
+ [`examples/demo/agent-commit-demo.sh`](examples/demo/agent-commit-demo.sh).
59
+
60
+ ### CI verify
61
+
62
+ ```yaml
63
+ - uses: SSX360/matrixscroll-verify-action@v1
64
+ with:
65
+ manifest: examples/agentic_ai_evidence_manifest.signed.json
66
+ matrixscroll-version: "0.2.0"
67
+ ```
68
+
40
69
  ## CLI
41
70
 
42
71
  ```bash
@@ -0,0 +1,20 @@
1
+ # SSX360 hardware provider (L2)
2
+
3
+ **Status:** Stage-0 prototype — `HardwareProvider` reports unavailable until the
4
+ NXP SE050 transport ships on the SSX360 reference device.
5
+
6
+ ## Planned behavior
7
+
8
+ - `MATRIXSCROLL_MODE=hardware` selects the secure-element provider
9
+ - Private keys never leave the SE050; no seed on disk
10
+ - User-presence touch gating for protected-branch commits
11
+ - Compatible with the same manifest and commit-envelope schemas as L1 emulated mode
12
+
13
+ ## Related docs
14
+
15
+ - [`docs/yubikey-bridge.md`](yubikey-bridge.md) — bridge path before SSX360 GA
16
+ - [`SPEC.md`](../SPEC.md) — wire format (unchanged for L2 signing algorithm)
17
+
18
+ ## Device
19
+
20
+ Reference hardware: [matrixscroll.com/device](https://matrixscroll.com/device)
@@ -0,0 +1,61 @@
1
+ # Git Quickstart
2
+
3
+ Matrix Scroll Git hooks attach a signed **commit envelope** to every local commit.
4
+
5
+ ## Install hooks
6
+
7
+ ```bash
8
+ pip install matrixscroll
9
+ matrixscroll hook-install
10
+ matrixscroll hook-status
11
+ ```
12
+
13
+ Hooks ship inside the Python wheel (`matrixscroll/hooks/`). No separate clone path
14
+ is required for pip-installed users.
15
+
16
+ ## What happens on commit
17
+
18
+ 1. **post-commit** reads the new commit SHA and builds a commit envelope from `git show`
19
+ 2. The envelope is signed with your active Matrix Scroll identity
20
+ 3. The signed envelope is stored at `.git/matrixscroll/envelopes/<sha>.json`
21
+
22
+ **pre-push** verifies envelopes only for commits being pushed (not every envelope
23
+ ever stored locally).
24
+
25
+ By default hooks run in **warn mode** (signing failures do not block commits).
26
+ Enable enforce mode in `.git/matrixscroll/config.json`:
27
+
28
+ ```json
29
+ {
30
+ "enforce": true,
31
+ "actor_type": "human",
32
+ "tool": "cursor"
33
+ }
34
+ ```
35
+
36
+ ## Agent provenance
37
+
38
+ Set environment variables before committing:
39
+
40
+ ```bash
41
+ export MATRIXSCROLL_ACTOR_TYPE=agent
42
+ export MATRIXSCROLL_TOOL=cursor
43
+ export MATRIXSCROLL_AGENT_SCOPE=examples/agentic_ai_evidence_manifest.signed.json
44
+ ```
45
+
46
+ ## Verify in CI
47
+
48
+ ```bash
49
+ matrixscroll verify .git/matrixscroll/envelopes/<commit-sha>.json
50
+ matrixscroll envelope-verify <commit-sha>
51
+ ```
52
+
53
+ Or use [`SSX360/matrixscroll-verify-action@v1`](https://github.com/SSX360/matrixscroll-verify-action).
54
+
55
+ ## Demo
56
+
57
+ ```bash
58
+ bash examples/demo/agent-commit-demo.sh
59
+ ```
60
+
61
+ See [spec](../superpowers/specs/2026-06-19-matrixscroll-git-design.md).
@@ -0,0 +1,88 @@
1
+ # CI Action Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Provide a zero-config GitHub Action that runs `matrixscroll verify` with CI-friendly exit codes.
6
+
7
+ **Architecture:** Composite action installs matrixscroll from PyPI, runs verify on one or more manifest paths, optionally applies policy flags.
8
+
9
+ **Tech Stack:** GitHub Actions, Python 3.10+, matrixscroll CLI
10
+
11
+ ---
12
+
13
+ ## Exit code contract
14
+
15
+ | Code | Meaning | CI interpretation |
16
+ |------|---------|-------------------|
17
+ | 0 | Valid signature | Pass check |
18
+ | 1 | Usage/config error | Fail workflow (misconfiguration) |
19
+ | 2 | Verification failed | Fail workflow (tampered/invalid) |
20
+
21
+ The action MUST propagate CLI exit codes unchanged (`set -e` in bash step).
22
+
23
+ ## Action inputs
24
+
25
+ | Input | Required | Default | Description |
26
+ |-------|----------|---------|-------------|
27
+ | `manifest` | yes | — | Path to signed manifest JSON |
28
+ | `python-version` | no | `3.12` | Python for pip install |
29
+ | `matrixscroll-version` | no | `latest` | Pin e.g. `0.1.1` for reproducibility |
30
+ | `require-mode` | no | `` | Pass through to policy verify (v0.2.1) |
31
+ | `trusted-keys` | no | `` | Path to trusted keys JSON (v0.2.1) |
32
+
33
+ ## Action outputs
34
+
35
+ | Output | Description |
36
+ |--------|-------------|
37
+ | `ok` | `true` or `false` |
38
+ | `device_id` | Signer device id from manifest |
39
+ | `mode` | Provider mode (`emulated`, `hardware`, `yubikey`) |
40
+
41
+ ## Files
42
+
43
+ | File | Purpose |
44
+ |------|---------|
45
+ | `matrixscroll-action/action.yml` | Composite action definition |
46
+ | `matrixscroll-action/README.md` | Usage docs |
47
+ | `matrixscroll/.github/workflows/verify-manifest.yml` | Dogfood workflow |
48
+ | `matrixscroll/examples/ci/protected-branch.yml` | Copy-paste template |
49
+
50
+ ## Protected branch pattern
51
+
52
+ ```yaml
53
+ name: provenance
54
+ on:
55
+ pull_request:
56
+ branches: [main]
57
+ jobs:
58
+ verify-release-manifest:
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - uses: SSX360/matrixscroll-verify-action@v1
63
+ with:
64
+ manifest: examples/release-manifest.signed.json
65
+ ```
66
+
67
+ ## Release verification pattern
68
+
69
+ 1. Build job signs release manifest, uploads artifact
70
+ 2. Verify job downloads artifact, runs action
71
+ 3. Deploy job requires verify job success
72
+
73
+ ## Task checklist
74
+
75
+ - [x] Write action.yml composite action
76
+ - [x] Add dogfood workflow in matrixscroll repo
77
+ - [x] Add protected-branch example
78
+ - [ ] Publish action repo and tag v1 (manual release step)
79
+ - [ ] Add signed release-manifest to examples once v0.2.0 ships
80
+
81
+ ## Verification
82
+
83
+ ```bash
84
+ cd matrixscroll
85
+ pip install -e ".[dev]"
86
+ pytest tests/test_cli.py -v
87
+ matrixscroll verify examples/agentic_ai_evidence_manifest.json # expect exit 2 unsigned
88
+ ```
@@ -0,0 +1,166 @@
1
+ # SDK Refactor Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development or superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Split the monolithic `_core.py` into focused modules while preserving the public API in `matrixscroll/__init__.py`.
6
+
7
+ **Architecture:** Move crypto, canonical encoding, manifest signing, providers, and policy into separate modules. Keep `_core.py` as a thin compatibility shim that re-exports everything until v0.3.0.
8
+
9
+ **Tech Stack:** Python 3.10+, cryptography, pytest
10
+
11
+ ---
12
+
13
+ ## Target module layout
14
+
15
+ ```
16
+ matrixscroll/
17
+ __init__.py # unchanged public API
18
+ _core.py # compatibility re-exports (deprecated v0.3.0)
19
+ canonical.py # deterministic JSON encoding
20
+ manifest.py # sign_manifest / verify_manifest
21
+ policy.py # policy-aware verification
22
+ errors.py # IdentityError, VerificationError
23
+ git.py # git hooks (v0.2.0)
24
+ providers/
25
+ __init__.py
26
+ base.py # IdentityProvider ABC
27
+ emulated.py # EmulatedProvider
28
+ hardware.py # HardwareProvider stub
29
+ yubikey.py # YubiKey bridge (optional extra)
30
+ cli.py
31
+ py.typed
32
+ ```
33
+
34
+ ## Public API contract (must not break)
35
+
36
+ These symbols remain importable from `matrixscroll`:
37
+
38
+ - Constants: `SCHEMA`, `SIGNATURE_SCHEMA`, `ALGORITHM`, `DEVICE_FILE`
39
+ - Exceptions: `IdentityError`
40
+ - Providers: `IdentityProvider`, `EmulatedProvider`, `HardwareProvider`
41
+ - Functions: `store_dir`, `device_id`, `get_provider`, `identity_info`, `status`, `public_key_b64`, `sign`, `verify`, `sign_manifest`, `verify_manifest`
42
+
43
+ ## Task 1: Extract errors and constants
44
+
45
+ **Files:**
46
+ - Create: `matrixscroll/errors.py`
47
+ - Create: `matrixscroll/constants.py`
48
+ - Modify: `matrixscroll/_core.py`
49
+
50
+ Move `IdentityError`, `SCHEMA`, `SIGNATURE_SCHEMA`, `ALGORITHM`, `DEVICE_FILE`, `SEED_LEN`, mode constants.
51
+
52
+ ## Task 2: Extract canonical encoding
53
+
54
+ **Files:**
55
+ - Create: `matrixscroll/canonical.py`
56
+ - Modify: `matrixscroll/manifest.py`
57
+
58
+ Move `_canonical()` → `canonical_bytes(payload: dict) -> bytes`.
59
+
60
+ ## Task 3: Extract manifest signing
61
+
62
+ **Files:**
63
+ - Create: `matrixscroll/manifest.py`
64
+
65
+ Move `sign_manifest`, `verify_manifest`, keep importing `sign`/`verify` from providers layer.
66
+
67
+ ## Task 4: Extract providers
68
+
69
+ **Files:**
70
+ - Create: `matrixscroll/providers/base.py`
71
+ - Create: `matrixscroll/providers/emulated.py`
72
+ - Create: `matrixscroll/providers/hardware.py`
73
+ - Create: `matrixscroll/providers/__init__.py`
74
+
75
+ Move provider classes and `get_provider()`.
76
+
77
+ ## Task 5: Add policy module
78
+
79
+ **Files:**
80
+ - Create: `matrixscroll/policy.py`
81
+ - Modify: `matrixscroll/cli.py`
82
+
83
+ Add:
84
+
85
+ ```python
86
+ @dataclass
87
+ class VerifyPolicy:
88
+ require_mode: str | None = None
89
+ trusted_public_keys: set[str] | None = None
90
+ allowed_schemas: set[str] | None = None
91
+
92
+ def verify_manifest_with_policy(manifest: dict, policy: VerifyPolicy) -> tuple[bool, str | None]:
93
+ ...
94
+ ```
95
+
96
+ CLI flags (v0.2.1):
97
+
98
+ ```
99
+ matrixscroll verify manifest.json --require-mode hardware --trusted-keys keys.json
100
+ ```
101
+
102
+ ## Task 6: Compatibility shim
103
+
104
+ **Files:**
105
+ - Modify: `matrixscroll/_core.py`
106
+
107
+ Replace body with re-exports:
108
+
109
+ ```python
110
+ from .canonical import canonical_bytes as _canonical
111
+ from .manifest import sign_manifest, verify_manifest
112
+ from .providers import EmulatedProvider, HardwareProvider, IdentityProvider, get_provider
113
+ ...
114
+ ```
115
+
116
+ Add deprecation comment; remove shim in v0.3.0.
117
+
118
+ ## Task 7: Update tests
119
+
120
+ **Files:**
121
+ - Modify: `tests/test_core.py` — add imports from new modules
122
+ - Create: `tests/test_policy.py`
123
+ - Create: `tests/test_canonical.py`
124
+
125
+ Run: `pytest -ra`
126
+
127
+ ## Task 8: Update packaging
128
+
129
+ **Files:**
130
+ - Modify: `pyproject.toml` — include `schemas/`, optional `[yubikey]` extra
131
+
132
+ ```toml
133
+ [project.optional-dependencies]
134
+ yubikey = [] # PKCS#11 deps added when bridge ships
135
+ git = []
136
+ ```
137
+
138
+ ## Migration guide (for downstream consumers)
139
+
140
+ | Before | After (preferred) |
141
+ |--------|-------------------|
142
+ | `from matrixscroll._core import _canonical` | `from matrixscroll.canonical import canonical_bytes` |
143
+ | `verify_manifest(m)` | `verify_manifest_with_policy(m, policy)` for CI gates |
144
+ | `MATRIXSCROLL_MODE=hardware` | unchanged |
145
+
146
+ ## Version bump
147
+
148
+ - v0.2.0: git module, schemas, provider split (shim retained)
149
+ - v0.2.1: policy CLI flags
150
+ - v0.3.0: remove `_core.py` shim, add YubiKey extra
151
+
152
+ ## Risks
153
+
154
+ | Risk | Mitigation |
155
+ |------|------------|
156
+ | Import cycles | providers → manifest → canonical (one direction) |
157
+ | Vector drift | run `tests/test_vectors.py` after every task |
158
+ | Breaking private imports | document `_core` deprecation; grep GitHub for `_core` usage |
159
+
160
+ ## Verification checklist
161
+
162
+ - [ ] `pytest` green
163
+ - [ ] `matrixscroll status` unchanged output shape
164
+ - [ ] All vectors pass
165
+ - [ ] `pip install -e .` works
166
+ - [ ] No new runtime deps without CONTRIBUTING discussion
@@ -0,0 +1,205 @@
1
+ # matrixscroll-git — Design Spec
2
+
3
+ **Date:** 2026-06-19
4
+ **Status:** Approved for v0.2.0 implementation
5
+ **Scope:** Local Git hooks, commit-envelope manifest, CLI extensions, CI verification contract
6
+
7
+ ## 1. Goal
8
+
9
+ Attach a Matrix Scroll cryptographic provenance envelope to every Git commit made
10
+ by a human or AI agent. Verify envelopes offline in CI without trusting the
11
+ host IDE or agent runtime.
12
+
13
+ This is the Day-1 beachhead: Git commits are standardized, high-consequence, and
14
+ already support signing workflows.
15
+
16
+ ## 2. Non-goals (v0.2.0)
17
+
18
+ - Replacing GPG/SSH commit signing (Matrix Scroll is additive metadata)
19
+ - Remote attestation (L3) or hardware touch gating (L2 transport)
20
+ - Server-side registry or enrollment APIs
21
+
22
+ ## 3. Commit envelope schema
23
+
24
+ Schema id: `matrixscroll.commit_envelope.v1`
25
+
26
+ See [`schemas/commit-envelope.v1.json`](../schemas/commit-envelope.v1.json) and
27
+ [`examples/commit-envelope.json`](../../examples/commit-envelope.json).
28
+
29
+ ### Required fields
30
+
31
+ | Field | Type | Description |
32
+ |-------|------|-------------|
33
+ | `schema` | string | Constant `matrixscroll.commit_envelope.v1` |
34
+ | `commit` | object | Git commit identity material |
35
+ | `commit.tree` | string | Full tree SHA-1 hex |
36
+ | `commit.parents` | string[] | Parent commit SHAs (empty for root) |
37
+ | `commit.author` | object | `{name, email, date}` from commit object |
38
+ | `commit.committer` | object | `{name, email, date}` from commit object |
39
+ | `commit.message` | string | Raw commit message bytes as UTF-8 string |
40
+ | `provenance` | object | Who/what produced the commit |
41
+ | `provenance.actor_type` | string | `human` \| `agent` \| `ci` |
42
+ | `provenance.tool` | string | e.g. `cursor`, `claude-code`, `git-cli` |
43
+ | `provenance.tool_version` | string | Optional semver or build id |
44
+ | `provenance.agent_scope` | string | Optional reference to signed agent evidence manifest |
45
+ | `repository` | object | `{name, remote_url}` best-effort from git config |
46
+ | `signature` | object | Matrix Scroll signature block (see SPEC.md §5) |
47
+
48
+ ### Signing input
49
+
50
+ The envelope is signed with `sign_manifest()` using canonical JSON rules from
51
+ SPEC.md §4. The top-level `signature` block is excluded from the signing input.
52
+
53
+ ### Commit binding
54
+
55
+ The envelope MUST be bound to the commit it describes:
56
+
57
+ ```
58
+ commit_id = SHA-1( commit_object_bytes )
59
+ ```
60
+
61
+ The hook computes `commit_id` from the staged tree + message at commit time
62
+ (before the commit object exists) using:
63
+
64
+ ```
65
+ tree = git write-tree
66
+ commit_body = git commit-tree $tree -p $parents -m "$message"
67
+ commit_id = SHA-1(commit_body) # computed, not yet committed
68
+ ```
69
+
70
+ The envelope stores `commit.expected_id` (the computed SHA). After commit,
71
+ `commit.actual_id` is written to `.git/matrixscroll/envelopes/<sha>.json`.
72
+
73
+ ## 4. Storage layout
74
+
75
+ ```
76
+ .git/matrixscroll/
77
+ config.json # hook config (require_envelope, actor defaults)
78
+ envelopes/
79
+ <40-char-sha>.json # one signed envelope per commit
80
+ ```
81
+
82
+ Envelopes are **local provenance artifacts**. They may be exported to CI as
83
+ build artifacts or pushed to a release evidence bucket; they are not committed
84
+ to the source tree by default.
85
+
86
+ ## 5. CLI commands
87
+
88
+ Extend the `matrixscroll` CLI:
89
+
90
+ | Command | Description | Exit codes |
91
+ |---------|-------------|------------|
92
+ | `matrixscroll hook install` | Install pre-commit + pre-push hooks | 0 ok, 1 error |
93
+ | `matrixscroll hook uninstall` | Remove hooks | 0 ok |
94
+ | `matrixscroll hook status` | JSON: installed, config, envelope count | 0 |
95
+ | `matrixscroll envelope build` | Build envelope for staged commit (stdin/flags) | 0 ok, 2 fail |
96
+ | `matrixscroll envelope verify <sha\|file>` | Verify envelope for commit | 0 pass, 2 fail |
97
+ | `matrixscroll verify <file>` | *(existing)* verify any signed manifest | 0 pass, 2 fail |
98
+
99
+ Environment variables (inherit from SDK):
100
+
101
+ - `MATRIXSCROLL_MODE` — `emulated` (default) or `hardware`
102
+ - `MATRIXSCROLL_HOME` — key store override
103
+ - `MATRIXSCROLL_ACTOR_TYPE` — default `human` | `agent` | `ci`
104
+ - `MATRIXSCROLL_TOOL` — default tool name for provenance block
105
+
106
+ ## 6. Hook behavior
107
+
108
+ ### pre-commit
109
+
110
+ 1. Read staged tree via `git write-tree`
111
+ 2. Build commit preview (parents from `HEAD`, message from `-F` or `-m`)
112
+ 3. Construct commit envelope manifest
113
+ 4. Sign with active provider via `sign_manifest()`
114
+ 5. Write envelope to `.git/matrixscroll/envelopes/<expected_id>.json`
115
+ 6. Exit 0 (never block commit on signing failure in v0.2.0 **warn mode**;
116
+ **enforce mode** exits 2)
117
+
118
+ Config flag `enforce: true` blocks commits when signing fails.
119
+
120
+ ### pre-push
121
+
122
+ 1. For each commit being pushed not already on remote:
123
+ - Load envelope from `.git/matrixscroll/envelopes/<sha>.json`
124
+ - Run `verify_manifest()`
125
+ 2. Exit 2 if any envelope missing or invalid (when `enforce: true`)
126
+
127
+ ### prepare-commit-msg (optional, phase 2)
128
+
129
+ Append `Matrix-Scroll-Envelope: <sha>` trailer to commit message for
130
+ human-visible provenance pointer.
131
+
132
+ ## 7. CI verification contract
133
+
134
+ CI MUST NOT parse free-text hook output. Use exit codes:
135
+
136
+ | Exit code | Meaning |
137
+ |-----------|---------|
138
+ | 0 | Signature valid |
139
+ | 1 | Usage / configuration error |
140
+ | 2 | Verification failed (tampered, missing, wrong schema) |
141
+
142
+ ### GitHub Actions pattern
143
+
144
+ ```yaml
145
+ - uses: actions/setup-python@v5
146
+ with:
147
+ python-version: "3.12"
148
+ - run: pip install matrixscroll
149
+ - run: matrixscroll verify evidence/commit-envelope.json
150
+ ```
151
+
152
+ For protected branches, CI receives exported envelopes as artifacts from a
153
+ prior build job or fetches them from object storage.
154
+
155
+ Policy extensions (v0.2.1):
156
+
157
+ ```bash
158
+ matrixscroll verify release.json \
159
+ --require-mode hardware \
160
+ --trusted-keys trusted-keys.json
161
+ ```
162
+
163
+ ## 8. Error handling
164
+
165
+ | Failure | Hook (warn) | Hook (enforce) | CI |
166
+ |---------|-------------|----------------|-----|
167
+ | Provider unavailable | warn, continue | exit 2 | exit 2 |
168
+ | Corrupt envelope | warn | exit 2 | exit 2 |
169
+ | Tampered manifest | warn | exit 2 | exit 2 |
170
+ | Missing envelope | warn | exit 2 | exit 2 |
171
+ | Wrong schema version | warn | exit 2 | exit 2 |
172
+
173
+ ## 9. Security considerations
174
+
175
+ - Envelopes prove **who signed the provenance record**, not that Git's native
176
+ signature is valid. Pair with branch protection + required status checks.
177
+ - Emulated mode (L1) is suitable for dev; release branches SHOULD require
178
+ `mode: hardware` once L2 ships.
179
+ - Never store private keys in envelope files; only public key + signature.
180
+
181
+ ## 10. Test plan
182
+
183
+ - Unit: envelope schema validation, commit_id computation
184
+ - Integration: `hook install` → commit → envelope exists → `verify` passes
185
+ - Tamper: modify envelope field → `verify` exits 2
186
+ - Vectors: add `vectors/valid_commit_envelope.json` in v0.2.0
187
+
188
+ ## 11. Implementation files
189
+
190
+ | File | Responsibility |
191
+ |------|----------------|
192
+ | `schemas/commit-envelope.v1.json` | JSON Schema |
193
+ | `examples/commit-envelope.json` | Reference example |
194
+ | `tools/git/install.py` | Hook installer |
195
+ | `tools/git/hooks/pre-commit` | Pre-commit hook script |
196
+ | `tools/git/hooks/pre-push` | Pre-push hook script |
197
+ | `matrixscroll/git.py` | Python hook/envelope API (v0.2.0) |
198
+ | `tests/test_git_envelope.py` | Tests |
199
+
200
+ ## 12. Rollout phases
201
+
202
+ 1. **v0.2.0-alpha:** warn-mode hooks, emulated signing, local envelopes
203
+ 2. **v0.2.0:** enforce-mode, GitHub Action, commit-envelope vectors
204
+ 3. **v0.2.1:** policy flags (`--require-mode`, trusted keys)
205
+ 4. **v0.3.0:** YubiKey bridge provider, hardware mode for release branches