AgentBlueprintProtocol.Blueprint (Agent Blueprint Protocol v0.1.0)

Copy Markdown View Source

The Blueprint artifact (base §6): an immutable, portable, inert statement of intent, decoded and validated through the ONE generic field-registry engine (AgentBlueprintProtocol.Registry) parameterized by this module's 18-member table.

The decode pipeline, in order, each stage fail-closed:

  1. Canonicalization.verify/2 on the received bytes — a non-canonical spelling of a byte-identical value denies :non_canonical_bytes BEFORE any semantic read or digest comparison (the canonicality obligation: digests are computed only over exact received bytes, and a re-encode-then-digest shortcut must fail this gate, never verify_content).
  2. AgentBlueprintProtocol.Registry.validate/2 against table/0 — closed world (:unknown_member), required members, tag-strict integer typing (the The window-float deny: {:float, f} in an integer-typed core field is :invalid_type here, because only this layer sees the decoder tag the wire cannot carry), enums, cardinalities, and the per-member custom checks (bounded schemas via Schema, signature envelopes via Signature, the extension envelope, the assertion operands).
  3. The portability scan (Portability) — full scan over the open regions (extension bodies, bounded-schema documents), value-shape scan over every other string including signature key_id, :forbidden_portable_value.
  4. The content-digest comparison — Digest.verify_content/3 over the canonical bytes of the covered members (everything except content_digest, signatures, attestations), :digest_mismatch on divergence.

from_value/1 runs stages 2-3 without canonicality (there are no bytes): structure only, for values that came from verify-ed bytes or for producer-side composition — verify_content_digest/1 is the integrity half and must be called separately for the compose-then-verify flow.

to_value/1 is the identity on the held tagged value, so decode → to_value → encode is a byte-exact fixed point (the quarantine round-trip depends on it). A Blueprint is an inert description: decoding one never authorizes an operation.

Summary

Functions

The canonical bytes of the whole artifact.

The honest content digest over the covered members' canonical bytes.

Decode and fully verify artifact bytes: canonical verify → registry validation → portability scan → content-digest comparison. Total and never-raising.

Whether member_name (a wire-level member name) is digest-covered.

The digest input: the artifact minus the three evidence members (§8.2).

Validate an already-decoded tagged value (stages 2-3; no canonicality — there are no bytes, so the canonicality ordering obligation does not apply here). For values that came from verify-ed bytes, follow with verify_content_digest/1.

The 18-member field registry (base §6): data for the generic engine. Field order is the engine's precedence anchor for table-order stages.

The held tagged value — the identity, so the round-trip is byte-exact.

Compare the declared content_digest member against the recomputed digest over the exact received (verified) bytes' canonical form: :digest_mismatch on divergence.

Types

reason()

t()

@type t() :: %AgentBlueprintProtocol.Blueprint{
  value: AgentBlueprintProtocol.Json.value()
}

Functions

canonical_bytes(blueprint)

@spec canonical_bytes(t()) :: {:ok, binary()} | {:error, reason()}

The canonical bytes of the whole artifact.

content_digest(blueprint)

@spec content_digest(t()) :: AgentBlueprintProtocol.Digest.t() | {:error, reason()}

The honest content digest over the covered members' canonical bytes.

decode(binary, bounds \\ Bounds.maximum())

@spec decode(binary(), AgentBlueprintProtocol.Bounds.t() | map()) ::
  {:ok, t()} | {:error, reason()}

Decode and fully verify artifact bytes: canonical verify → registry validation → portability scan → content-digest comparison. Total and never-raising.

digest_covered?(member_name)

@spec digest_covered?(binary()) :: boolean()

Whether member_name (a wire-level member name) is digest-covered.

digest_input(blueprint)

@spec digest_input(t()) :: AgentBlueprintProtocol.Json.value()

The digest input: the artifact minus the three evidence members (§8.2).

from_value(value, opts \\ %{})

@spec from_value(AgentBlueprintProtocol.Json.value(), map()) ::
  {:ok, t()} | {:error, reason()}

Validate an already-decoded tagged value (stages 2-3; no canonicality — there are no bytes, so the canonicality ordering obligation does not apply here). For values that came from verify-ed bytes, follow with verify_content_digest/1.

opts carries :authored_extensions — namespaces whose critical bodies negotiation validated against a digest-pinned host schema. Those bodies are the legitimate channel for encoded content and SKIP the portability value-shape heuristics entirely (mixed-case encoded blobs are the channel's payload — the authored posture alone would still deny them): their controls are the digest-pinned schema validation and the reserved-semantics denylist, both at negotiation. The default ([]) keeps the strict posture everywhere.

table()

The 18-member field registry (base §6): data for the generic engine. Field order is the engine's precedence anchor for table-order stages.

to_value(blueprint)

@spec to_value(t()) :: AgentBlueprintProtocol.Json.value()

The held tagged value — the identity, so the round-trip is byte-exact.

verify_content_digest(blueprint)

@spec verify_content_digest(t()) :: :ok | {:error, reason()}

Compare the declared content_digest member against the recomputed digest over the exact received (verified) bytes' canonical form: :digest_mismatch on divergence.