From 4032ba8f21df6c0a3d9f17002a662a547cb3ce08 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 14:31:39 -0400 Subject: [PATCH 1/8] Add signed release bundle envelope schema --- ...signed-release-bundle-envelope.schema.json | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 contracts/signed-release-bundle-envelope.schema.json diff --git a/contracts/signed-release-bundle-envelope.schema.json b/contracts/signed-release-bundle-envelope.schema.json new file mode 100644 index 0000000..0a0d1cf --- /dev/null +++ b/contracts/signed-release-bundle-envelope.schema.json @@ -0,0 +1,78 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "urn:srcos:agent-machine:schema:signed-release-bundle-envelope:v0.1.0", + "title": "SignedReleaseBundleEnvelope", + "description": "Secret-free signing envelope for Agent Machine ReleaseEvidenceBundle payloads. Bootstrap supports unsigned and signed-placeholder envelopes; production requires real signature verification.", + "type": "object", + "additionalProperties": false, + "required": [ + "specVersion", + "id", + "kind", + "subject", + "signature", + "verification", + "receiptSafety", + "generatedAt" + ], + "properties": { + "specVersion": { "type": "string", "const": "0.1.0" }, + "id": { + "type": "string", + "pattern": "^urn:srcos:agent-machine:signed-release-bundle-envelope:[a-z0-9][a-z0-9-]*$" + }, + "kind": { "type": "string", "const": "SignedReleaseBundleEnvelope" }, + "subject": { + "type": "object", + "additionalProperties": false, + "required": ["subjectKind", "subjectRef", "subjectDigest"], + "properties": { + "subjectKind": { "type": "string", "const": "ReleaseEvidenceBundle" }, + "subjectRef": { "type": "string" }, + "subjectDigest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" }, + "sourceCommitSha": { "type": ["string", "null"], "pattern": "^[a-f0-9]{40}$" }, + "workflowRunId": { "type": ["integer", "null"], "minimum": 1 } + } + }, + "signature": { + "type": "object", + "additionalProperties": false, + "required": ["status", "algorithm", "keyRef", "signatureDigest", "signatureRef"], + "properties": { + "status": { "type": "string", "enum": ["unsigned", "signed-placeholder", "signed"] }, + "algorithm": { "type": ["string", "null"], "enum": ["cosign-keyless", "cosign-key-pair", "minisign", "ssh-sig", "gpg", "unknown", null] }, + "keyRef": { "type": ["string", "null"] }, + "signatureDigest": { "type": ["string", "null"], "pattern": "^sha256:[a-f0-9]{64}$" }, + "signatureRef": { "type": ["string", "null"] }, + "transparencyLogRef": { "type": ["string", "null"] }, + "certificateRef": { "type": ["string", "null"] } + } + }, + "verification": { + "type": "object", + "additionalProperties": false, + "required": ["verified", "verificationStatus", "verifiedAt", "verifierVersion"], + "properties": { + "verified": { "type": "boolean" }, + "verificationStatus": { "type": "string", "enum": ["not-implemented", "not-run", "passed", "failed", "unknown"] }, + "verifiedAt": { "type": ["string", "null"] }, + "verifierVersion": { "type": ["string", "null"] }, + "failureReason": { "type": ["string", "null"] } + } + }, + "receiptSafety": { + "type": "object", + "additionalProperties": false, + "required": ["includeRawContent", "rawPromptContentIncluded", "rawKvCacheContentIncluded", "secretValuesIncluded", "privateMemoryIncluded"], + "properties": { + "includeRawContent": { "type": "boolean", "const": false }, + "rawPromptContentIncluded": { "type": "boolean", "const": false }, + "rawKvCacheContentIncluded": { "type": "boolean", "const": false }, + "secretValuesIncluded": { "type": "boolean", "const": false }, + "privateMemoryIncluded": { "type": "boolean", "const": false } + } + }, + "generatedAt": { "type": "string" }, + "notes": { "type": "array", "items": { "type": "string" } } + } +} From 88d216602a62c57ccc1103e79c6b819b7a9c409d Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 14:34:01 -0400 Subject: [PATCH 2/8] Validate SignedReleaseBundleEnvelope examples by kind --- src/agent_machine/contracts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/agent_machine/contracts.py b/src/agent_machine/contracts.py index b5f6f7e..3caa256 100644 --- a/src/agent_machine/contracts.py +++ b/src/agent_machine/contracts.py @@ -56,6 +56,7 @@ def schema_by_kind(root: Path | None = None) -> dict[str, Path]: "InferenceProvider": base / "inference-provider.schema.json", "PolicyAdmission": base / "policy-admission.schema.json", "ReleaseEvidenceBundle": base / "release-evidence-bundle.schema.json", + "SignedReleaseBundleEnvelope": base / "signed-release-bundle-envelope.schema.json", "StorageReceipt": base / "storage-receipt.schema.json", } From 566d0b142414c09e8cd2e337a87d0073f71c6e30 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 14:34:47 -0400 Subject: [PATCH 3/8] Add unsigned release bundle envelope example --- ...gned-release-bundle-envelope.unsigned.json | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 examples/signed-release-bundle-envelope.unsigned.json diff --git a/examples/signed-release-bundle-envelope.unsigned.json b/examples/signed-release-bundle-envelope.unsigned.json new file mode 100644 index 0000000..ddb58dc --- /dev/null +++ b/examples/signed-release-bundle-envelope.unsigned.json @@ -0,0 +1,40 @@ +{ + "specVersion": "0.1.0", + "id": "urn:srcos:agent-machine:signed-release-bundle-envelope:bootstrap-unsigned", + "kind": "SignedReleaseBundleEnvelope", + "subject": { + "subjectKind": "ReleaseEvidenceBundle", + "subjectRef": "examples/release-evidence-bundle.bootstrap.json", + "subjectDigest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "sourceCommitSha": "2f905e63818cbefe823977946ba24bce801c7fa2", + "workflowRunId": 25335379781 + }, + "signature": { + "status": "unsigned", + "algorithm": null, + "keyRef": null, + "signatureDigest": null, + "signatureRef": null, + "transparencyLogRef": null, + "certificateRef": null + }, + "verification": { + "verified": false, + "verificationStatus": "not-run", + "verifiedAt": null, + "verifierVersion": null, + "failureReason": "bootstrap envelope is intentionally unsigned" + }, + "receiptSafety": { + "includeRawContent": false, + "rawPromptContentIncluded": false, + "rawKvCacheContentIncluded": false, + "secretValuesIncluded": false, + "privateMemoryIncluded": false + }, + "generatedAt": "2026-05-04T18:20:00Z", + "notes": [ + "Unsigned bootstrap envelope only.", + "Production release bundles require real signature verification." + ] +} From 3760ced7b53fb00dbab7ad79354a7769a3116fc6 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 14:38:47 -0400 Subject: [PATCH 4/8] Add signed-placeholder release bundle envelope example --- ...se-bundle-envelope.signed-placeholder.json | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 examples/signed-release-bundle-envelope.signed-placeholder.json diff --git a/examples/signed-release-bundle-envelope.signed-placeholder.json b/examples/signed-release-bundle-envelope.signed-placeholder.json new file mode 100644 index 0000000..bed5ad8 --- /dev/null +++ b/examples/signed-release-bundle-envelope.signed-placeholder.json @@ -0,0 +1,40 @@ +{ + "specVersion": "0.1.0", + "id": "urn:srcos:agent-machine:signed-release-bundle-envelope:bootstrap-signed-placeholder", + "kind": "SignedReleaseBundleEnvelope", + "subject": { + "subjectKind": "ReleaseEvidenceBundle", + "subjectRef": "examples/release-evidence-bundle.bootstrap.json", + "subjectDigest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "sourceCommitSha": "2f905e63818cbefe823977946ba24bce801c7fa2", + "workflowRunId": 25335379781 + }, + "signature": { + "status": "signed-placeholder", + "algorithm": "cosign-keyless", + "keyRef": "urn:srcos:signing-key:placeholder", + "signatureDigest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", + "signatureRef": "urn:srcos:signature:placeholder", + "transparencyLogRef": "urn:srcos:rekor:placeholder", + "certificateRef": "urn:srcos:certificate:placeholder" + }, + "verification": { + "verified": false, + "verificationStatus": "not-implemented", + "verifiedAt": null, + "verifierVersion": null, + "failureReason": "signature verification is not implemented in bootstrap lane" + }, + "receiptSafety": { + "includeRawContent": false, + "rawPromptContentIncluded": false, + "rawKvCacheContentIncluded": false, + "secretValuesIncluded": false, + "privateMemoryIncluded": false + }, + "generatedAt": "2026-05-04T18:20:00Z", + "notes": [ + "Signed-placeholder envelope shape only.", + "Production release bundles require a verified signature and verifier output." + ] +} From a575e44baeb08a1eeb8783cecad27b1af8289706 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 15:51:40 -0400 Subject: [PATCH 5/8] Document signed release bundle envelope --- .../signed-release-bundle-envelope.md | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/architecture/signed-release-bundle-envelope.md diff --git a/docs/architecture/signed-release-bundle-envelope.md b/docs/architecture/signed-release-bundle-envelope.md new file mode 100644 index 0000000..c4bb1e5 --- /dev/null +++ b/docs/architecture/signed-release-bundle-envelope.md @@ -0,0 +1,79 @@ +# Signed Release Bundle Envelope + +Agent Machine release evidence bundles need a signing envelope before they can become release-candidate or production promotion artifacts. The current bootstrap lane defines the envelope shape and examples, but does not implement cryptographic signing or verification. + +## Decision + +Define `SignedReleaseBundleEnvelope` as the contract wrapper around a `ReleaseEvidenceBundle`. + +The envelope records: + +- subject kind and reference; +- subject digest; +- source commit SHA; +- workflow run ID; +- signature status; +- signing algorithm; +- key or identity reference; +- signature digest/reference; +- transparency log reference; +- certificate reference; +- verification result; +- receipt-safety flags. + +## Bootstrap states + +Bootstrap supports two non-production states: + +| State | Meaning | +| --- | --- | +| `unsigned` | The bundle is intentionally unsigned. This is acceptable only for bootstrap development. | +| `signed-placeholder` | The envelope shape contains placeholder signing metadata, but verification is not implemented. | + +Neither state is production-valid. + +## Production state + +Production requires: + +```text +signature.status = signed +verification.verified = true +verification.verificationStatus = passed +``` + +Production signing should eventually use a verifiable signing lane such as keyless signing with transparency-log evidence, or another SourceOS-approved signing policy. + +## Current implementation + +Implemented now: + +- `contracts/signed-release-bundle-envelope.schema.json`; +- `examples/signed-release-bundle-envelope.unsigned.json`; +- `examples/signed-release-bundle-envelope.signed-placeholder.json`. + +## Validation + +The examples validate through `validate-json` because `SignedReleaseBundleEnvelope` is mapped in `src/agent_machine/contracts.py`. + +```bash +make validate-json +``` + +## Non-goals for this bootstrap lane + +- Generating real signatures. +- Verifying real signatures. +- Submitting to a transparency log. +- Managing signing keys. +- Claiming production readiness. + +## Future hardening + +Next steps: + +1. Add a signing CLI that can wrap a generated `ReleaseEvidenceBundle`. +2. Add a verifier CLI that checks the signature and updates verification status. +3. Add transparency-log references. +4. Add policy-controlled signing key selection. +5. Add branch protection and required validation checks before allowing production promotion. From e7256deb414da5ef66d957a045270ce1d09470e2 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 16:06:30 -0400 Subject: [PATCH 6/8] Require signed release envelope schema mapping in package validation --- scripts/validate-package.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/validate-package.py b/scripts/validate-package.py index 1c6f31f..cc3e700 100644 --- a/scripts/validate-package.py +++ b/scripts/validate-package.py @@ -40,6 +40,7 @@ def main() -> int: "AgentRegistryGrant", "PolicyAdmission", "ReleaseEvidenceBundle", + "SignedReleaseBundleEnvelope", "StorageReceipt", } missing = sorted(required_kinds - set(mapping)) From 802da7327f6182c13a1a32fa66a7b1aefc10ce2d Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 16:24:40 -0400 Subject: [PATCH 7/8] Link signed release envelope docs --- docs/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index e59526e..71f869b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -22,6 +22,7 @@ Agent Machine is a bootstrap runtime-control substrate for SourceOS agent worklo | [Receipt chain](architecture/receipt-chain.md) | AgentPod source to plan, manifest, receipt, policy, registry, and AgentPlane evidence. | | [Image digest pinning and provenance](architecture/image-digest-pinning-and-provenance.md) | Supply-chain strict-mode gate for digest-pinned release-candidate artifacts. | | [Release evidence bundle](architecture/release-evidence-bundle.md) | Deterministic validation/source/inventory/render/supply-chain/readiness bundle. | +| [Signed release bundle envelope](architecture/signed-release-bundle-envelope.md) | Signing envelope contract for release evidence bundles. | | [Runtime package layout](architecture/runtime-package-layout.md) | Migration from loose scripts to `src/agent_machine/` package modules. | | [Homebrew Python dependencies](architecture/homebrew-python-dependencies.md) | Current dependency strategy for render/evaluation commands. | | [Local LVM and TopoLVM profile](architecture/local-lvm-and-topolvm-profile.md) | Local and Kubernetes storage/cache/evidence profile. | @@ -73,6 +74,7 @@ Important contract families: | `AgentRegistryGrant` | Agent Registry grant/stub. | | `ActivationDecision` | Final dry-run activation decision. | | `ReleaseEvidenceBundle` | Secret-free release validation/source/inventory/render/supply-chain/readiness evidence. | +| `SignedReleaseBundleEnvelope` | Signing/verification envelope around a release evidence bundle. | ## Validation @@ -107,6 +109,7 @@ Current blockers: - main-branch CI visibility and branch protection; - real image digest pinning/provenance from trusted build artifacts; +- real release bundle signature verification; - real Policy Fabric client or endpoint; - real Agent Registry grant resolver; - real AgentPlane evidence submission/staging client; @@ -114,5 +117,4 @@ Current blockers: - TopoLVM runtime integration beyond skeleton manifests; - provider discovery and controlled provider activation implementation; - M2 Asahi host measurement/provider readiness data; -- signed release evidence bundle; - rollback, teardown, and wipe workflows. From 7a670ff74db9f3919f6f333b98e54f57bae0a902 Mon Sep 17 00:00:00 2001 From: mdheller <21163552+mdheller@users.noreply.github.com> Date: Mon, 4 May 2026 16:27:45 -0400 Subject: [PATCH 8/8] Document branch protection and required checks --- docs/architecture/branch-protection.md | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/architecture/branch-protection.md diff --git a/docs/architecture/branch-protection.md b/docs/architecture/branch-protection.md new file mode 100644 index 0000000..86af9f1 --- /dev/null +++ b/docs/architecture/branch-protection.md @@ -0,0 +1,76 @@ +# Branch Protection and Required Checks + +Agent Machine has a green PR-triggered validation lane. Branch protection is still a release-gate follow-up because required checks should not be configured until the expected check name and workflow visibility are stable. + +## Required check + +Current validation workflow: + +```text +validate +``` + +Current required job name candidate: + +```text +Validate contracts, examples, CLI, formula, and docs +``` + +Canonical local command: + +```bash +make validate +``` + +## Recommended branch protection for `main` + +Recommended settings once main-branch visibility is confirmed: + +- require pull request before merging; +- require status checks to pass before merging; +- require the `validate` workflow/job; +- require branches to be up to date before merging if the repository starts receiving concurrent changes; +- restrict bypasses to repository administrators only when emergency remediation is needed; +- do not require signed commits until the signing policy is documented and tested; +- do not require linear history unless the repo standardizes on squash-only merges. + +## Current CI proof + +Known green proof: + +```text +PR #9 +workflow run: 25322297618 +job: Validate contracts, examples, CLI, formula, and docs +command: make validate +``` + +Supply-chain strict-mode proof: + +```text +PR #11 +workflow run: 25327418937 +job: Validate contracts, examples, CLI, formula, and docs +command: make validate +``` + +Release bundle proof: + +```text +PR #14 +workflow run: 25335379781 +job: Validate contracts, examples, CLI, formula, and docs +command: make validate +``` + +## Open issue + +Tracked by: + +```text +Issue #10: Add branch protection and required validation checks for Agent Machine +``` + +## Why not close yet + +The connector can see PR-triggered runs. Main-branch push workflow visibility has been inconsistent or unavailable through the connector/API path. Branch protection should be configured after the required check appears consistently for the protected branch, or after the UI confirms the check can be selected.