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.
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/CHANGELOG.md +25 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/PKG-INFO +35 -4
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/README.md +32 -3
- matrixscroll-0.2.0/docs/hardware-provider.md +20 -0
- matrixscroll-0.2.0/docs/quickstart-git.md +61 -0
- matrixscroll-0.2.0/docs/superpowers/plans/2026-06-19-ci-action-plan.md +88 -0
- matrixscroll-0.2.0/docs/superpowers/plans/2026-06-19-sdk-refactor-plan.md +166 -0
- matrixscroll-0.2.0/docs/superpowers/specs/2026-06-19-matrixscroll-git-design.md +205 -0
- matrixscroll-0.2.0/docs/yubikey-bridge.md +137 -0
- matrixscroll-0.2.0/examples/agentic_ai_evidence_manifest.signed.json +80 -0
- matrixscroll-0.2.0/examples/ci/protected-branch.yml +38 -0
- matrixscroll-0.2.0/examples/commit-envelope.json +29 -0
- matrixscroll-0.2.0/examples/commit-envelope.signed.json +38 -0
- matrixscroll-0.2.0/examples/demo/agent-commit-demo.sh +46 -0
- matrixscroll-0.2.0/examples/demo/generate_signed_examples.py +32 -0
- matrixscroll-0.2.0/examples/release-manifest.json +24 -0
- matrixscroll-0.2.0/examples/release-manifest.signed.json +33 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/matrixscroll/__init__.py +1 -1
- matrixscroll-0.2.0/matrixscroll/_core.py +43 -0
- matrixscroll-0.2.0/matrixscroll/canonical.py +18 -0
- matrixscroll-0.2.0/matrixscroll/cli.py +178 -0
- matrixscroll-0.2.0/matrixscroll/constants.py +12 -0
- matrixscroll-0.2.0/matrixscroll/errors.py +11 -0
- matrixscroll-0.2.0/matrixscroll/git.py +376 -0
- matrixscroll-0.2.0/matrixscroll/hooks/post-commit +17 -0
- matrixscroll-0.2.0/matrixscroll/hooks/pre-push +17 -0
- matrixscroll-0.2.0/matrixscroll/manifest.py +59 -0
- matrixscroll-0.2.0/matrixscroll/policy.py +55 -0
- matrixscroll-0.2.0/matrixscroll/providers/__init__.py +7 -0
- matrixscroll-0.2.0/matrixscroll/providers/base.py +26 -0
- matrixscroll-0.2.0/matrixscroll/providers/emulated.py +116 -0
- matrixscroll-0.2.0/matrixscroll/providers/hardware.py +22 -0
- matrixscroll-0.2.0/matrixscroll/providers/registry.py +106 -0
- matrixscroll-0.2.0/matrixscroll/providers/yubikey.py +104 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/pyproject.toml +4 -1
- matrixscroll-0.2.0/schemas/commit-envelope.v1.json +150 -0
- matrixscroll-0.2.0/schemas/evidence-pack.v1.json +54 -0
- matrixscroll-0.2.0/schemas/release-manifest.v1.json +63 -0
- matrixscroll-0.2.0/tests/test_canonical.py +10 -0
- matrixscroll-0.2.0/tests/test_git_envelope.py +88 -0
- matrixscroll-0.2.0/tests/test_policy.py +26 -0
- matrixscroll-0.2.0/tests/test_yubikey_provider.py +35 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/_fixture_key.json +5 -5
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_algorithm.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_device_id.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_field.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_nested.json +28 -28
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_public_key.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_schema.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/tampered_signature.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/unsigned_empty_block.json +6 -6
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/unsigned_no_block.json +4 -4
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_nested.json +28 -28
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_simple.json +13 -13
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/valid_unicode.json +14 -14
- matrixscroll-0.1.1/matrixscroll/_core.py +0 -360
- matrixscroll-0.1.1/matrixscroll/cli.py +0 -94
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/.gitignore +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/CONTRIBUTING.md +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/LICENSE +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/SECURITY.md +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/SPEC.md +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/controls/agentic_ai_controls.json +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/docs/AGENTIC_AI_SECURITY.md +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/examples/agentic_ai_evidence_manifest.json +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/matrixscroll/py.typed +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/__init__.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_agentic_guidance.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_cli.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_core.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_release_metadata.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/tests/test_vectors.py +0 -0
- {matrixscroll-0.1.1 → matrixscroll-0.2.0}/vectors/README.md +0 -0
- {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.
|
|
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.
|
|
43
|
-
SSX360/NXP SE050 hardware signing is the
|
|
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.
|
|
8
|
-
SSX360/NXP SE050 hardware signing is the
|
|
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
|