Watch
1
0
Fork
You've already forked RedFlag
0
RedFlag/protocol
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Fimeg f5eb83ca94 feat: pin mutation manifest authority bytes
Introduce a dormant MutationEnvelope beside the current closure token. Server, Agent, and helper now agree on length-prefixed manifest and authorization bytes, with one shared fixture pinning the hash, key identity, and Ed25519 signature.\n\nExecutor-affecting provenance, location, target, backend, and backend payload now have a signed home before any runtime path migrates. Exact duplicates stay visible in the hash; ordering does not. Current APT/DNF and Windows behavior remains untouched.
2026-08-26 16:07:19 -04:00
..
testdata feat: pin mutation manifest authority bytes 2026-08-26 16:07:19 -04:00
README.md feat: pin mutation manifest authority bytes 2026-08-26 16:07:19 -04:00

Mutation manifest wire contract

This directory owns the language-independent bytes shared by RedFlag Server, Agent, and helper. The current closure-based capability token remains the only runtime execution path; the mutation envelope is pinned and tested but not wired to a backend yet.

Envelope

MutationEnvelope
├── MutationManifest
│   ├── protocol_version
│   ├── operation_id
│   ├── target_id
│   ├── backend
│   ├── operation
│   ├── resolved_actions[]
│   │   ├── kind
│   │   ├── identity
│   │   └── payload       exact backend-owned UTF-8 JSON bytes
│   └── evidence[]
│       ├── kind
│       └── digest        SHA-256 hex
└── MutationAuthorization
    ├── protocol_version
    ├── authorization_id
    ├── manifest_hash
    ├── authority_kind
    ├── authority_id
    ├── target_id
    ├── issued_at / not_before / expires_at
    ├── decision
    ├── key_id
    └── signature

The protocol envelope begins at format 1 in its own namespace. It is not a new numbered generation of CapabilityToken; the two named contracts coexist until a backend migrates. Unknown format values fail closed.

Canonical records

Every value is encoded as UTF-8 decimal_byte_length:value, with no separator between fields. Each record begins with a length-prefixed domain string.

Manifest field order:

redflag.mutation-manifest
protocol_version
operation_id
target_id
backend
operation
resolved_action_count
sorted(length-prefixed resolved-action records)
evidence_count
sorted(length-prefixed evidence records)

Resolved action field order:

redflag.resolved-action
kind
identity
payload

Evidence field order:

redflag.evidence
kind
digest

Authorization field order:

redflag.mutation-authorization
protocol_version
authorization_id
manifest_hash
authority_kind
authority_id
target_id
issued_at
not_before
expires_at
decision
key_id

manifest_hash is lowercase hex SHA-256 over the manifest canonical bytes. The Ed25519 signature is over the authorization canonical bytes. The signature itself is not included in those bytes; every other authorization field, including key_id, is.

Collection semantics

Resolved actions and evidence are unordered multisets. Their canonical records are sorted bytewise for hashing. Exact duplicates remain present, increment the count, and change the hash. No implementation may convert either collection to a set.

A backend that needs ordered execution encodes the sequence inside one signed payload. The common layer never infers package, WUA, Winget, Docker, or self-update semantics from that payload.

Provenance is evidence. Cache paths, URLs, repository selectors, WUA identities, and other execution inputs belong in the exact signed backend payload or must be derived deterministically from it.

Golden fixture

testdata/mutation-golden.json pins:

  • manifest canonical bytes and hash;
  • authorization canonical bytes;
  • authority key ID;
  • deterministic Ed25519 signature;
  • action/evidence ordering behavior;
  • duplicate retention;
  • tamper refusal for provenance, execution location, target, backend, resolved action, authorization metadata, decision, time window, and unknown formats.

Go tests live in both capability packages. Rust tests live in helper/src/mutation_protocol.rs.