All notable changes to the Concordia Protocol reference implementation are documented in this file.
The format is based on Keep a Changelog.
Attestation context is validated fail-closed at issuance (audit
2026-06-09 finding L3). generate_attestation previously persisted and
exported caller-supplied value_range and category free text verbatim,
letting a party stuff its own raw deal terms into a signed attestation in
violation of the SPEC 9.6.6 privacy invariant (behavioral signals only,
never deal terms). value_range is now restricted to an enumerated
logarithmic bucket vocabulary plus a 3-letter uppercase currency code
(e.g. 1000-5000_USD); category must be a dotted lowercase taxonomy
path of at most 64 chars. Invalid values raise ValueError and are never
coerced or echoed back. references[] entries are now capped at 32 per
attestation with length caps on every string field and a 2048
canonical-JSON-byte cap on each extensions map. Reference string
fields (type, id, relationship, version, signed_at,
signer_did) additionally reject any whitespace, both at issuance and
in all three schema files, so identifier-shaped fields cannot carry
prose deal terms. extensions maps are structurally pre-checked
(nesting depth at most 8, at most 256 nodes) with an early-bailing
walk before canonicalization, so an oversized object is never fully
serialized just to be rejected by the byte cap. Schema validation
errors from validate_message, validate_attestation,
validate_fulfillment_attestation, and validate_approval_receipt
now report the JSON path and the violated constraint (validator
keyword plus schema-side limit) instead of jsonschema’s default
message, which embedded the rejected instance value and could echo
raw deal text into logs and MCP responses.
BREAKING for issuers that previously passed free-form values, and for
schema validation of stored artifacts: validate_attestation /
is_valid_attestation now reject previously issued attestations whose
meta.category or meta.value_range carry legacy free-form values.
Signature verification of previously issued attestations is unchanged
(party signatures cover each party’s own behavior record, not meta),
and the reputation read/ingest path (AttestationStore.ingest) is
also unchanged: it verifies signatures and structure but does not
schema-validate meta, so stored legacy attestations continue to
ingest and score.
validity_temporal / ValidityWindow shape
(sequence / windowed / state_bound) to its originators: the framing was
proposed by @nanookclaw (with @douglasborthwick-crypto) in A2A discussion
#1734 (April 2026) and adopted here. Overdue provenance note; no behavior
change.RevocationRecord and
RevocationScope to concordia.cmpc.types for artifact-side revocation.schemas/revocation_record.schema.json plus
validate_revocation_record() with Draft 2020-12 validation.sign_revocation_record(), verify_revocation_record(), and
canonicalize_revocation_record() using RFC 8785 JCS canonical bytes.cascade_revocation() plus
CandidateArtifact, CascadeResult, and InadmissibleArtifact.verify_predicate() accepts optional
revocation_records and returns PredicateFailureReason.REVOKED for
revoked references.verify_approval_receipt()
accepts optional revocation_records and returns revoked for revoked
referenced mandates or sessions.giskard09-mid-execution-rotation fixture vectors.urn:concordia:revocation:<id> URN row, the revokes relationship value,
docs/cmpc_revocation.md, and a RevocationRecord composition note in
docs/revocation_resolver.md.urn:concordia:predicate:<id>). Signed
authority artifact evaluating authority/scope/policy/eligibility/bounds
conditions. Composes with mandate, attestation, and ApprovalReceipt
without coupling. RFC 8785 JCS canonicalization via
concordia.canonicalization.canonicalize_predicate() produces the
signing bytes; EdDSA (Ed25519) is the v0.6 reference signer
(concordia.predicate.sign_predicate). Verification surface
(verify_predicate) returns a stable PredicateVerificationResult
consumable by policy gates. 13 executable canonicalization fixture
vectors at tests/fixtures/predicate_canonical/ (vectors 1-12 plus
vector_13_deterministic_gate_failure).scripts/js-parity/).
Proves byte-level parity with the Python canonicalizer across all 13
predicate fixture vectors, giving non-Python implementers an
executable conformance check.PredicateVerificationResult with 8 stable failure reasons.
PredicateFailureReason enum in concordia.predicate:
schema_invalid, bad_signature, expired, revoked,
unknown_authority, ref_mismatch, wrong_subject, resolver_miss.
Result also carries per-check booleans (schema, profile_condition,
resolver_binding, signature, lifecycle, subject_binding,
reference_binding) for policy-readable introspection.concordia.predicate_type_profiles
ships four profiles: authority_gate, policy_gate,
procurement_eligibility, and non_deterministic_test (the explicit
forward-compat holdout that rejects predicates whose condition
cannot be evaluated deterministically). Unknown type values
validate cleanly today but verifiers MAY refuse to act on
non-deterministic conditions per the v0.6 profile-gate semantics.concordia.ctef.predicate_to_ctef_claim() emits a CTEF claim with
claim_subtype: "predicate_evaluation", artifact_ref set to the
predicate_id URN, allowing predicate outcomes to flow into the
CTEF audit substrate alongside mandate and attestation claims.importlib only when a
receipt-typed fulfills reference is present
(_call_approval_receipt_verifier in concordia.predicate). Absent
module surfaces a warnings entry rather than a hard failure,
preserving the non-dependency principle between primitives.DELIVERY_ACKNOWLEDGED). Distinct from the in-line
fulfillment block on a reputation attestation (§9.6.4) — the
standalone shape links back to the agreement attestation via
references[] with relationship: "fulfills" and uses the
A2CN-aligned status enum (fulfilled_clean,
fulfilled_with_mediation, failed, disputed_unresolved).
Schema at schemas/fulfillment_attestation.schema.json ($id
urn:concordia:schema:fulfillment_attestation:v0.5).schemas/approval_receipt.schema.json ($id
urn:concordia:schema:approval_receipt:v0.5). Spec coverage at
SPEC §9.6.4b with the Draft A worked example reproduced verbatim
so public-draft readers and the in-tree spec line up. Extends the
§11.5.5 relationship vocabulary with approves (artifact-specific;
preserved by the §11.5.3 forward-compat rule).docs/A2CN_FULFILLMENT.md. Integrator walkthrough for emitting
a Fulfillment Attestation on DELIVERY_ACKNOWLEDGED, the canonical
mapping between the standalone shape and the §9.6.4 in-line block,
and the v0.5 ApprovalReceipt shape with worked JSON examples for
each status enum value.schemas/reference.schema.json
and the embedded attestation reference schema now accept non-empty
strings for type and relationship, while documenting the canonical
emit vocabulary. Non-canonical values are preserved and warned on per
SPEC §11.5.5 and §11.5.8.FormatChecker, enforces exact
64-character hexadecimal transaction_record_hash values, and rejects
semantic misbinding before applying mediated fulfillment to an attestation.predicate is an opaque reference type only in v0.5.2. The standalone
predicate primitive is deferred to v0.6 pending signed artifact shape,
schema, canonical signing, verification, resolver hooks, and CTEF claim
mapping.docs/A2CN_FULFILLMENT.md.
Producers MUST NOT emit both a standalone artifact and an in-line
block for the same logical settlement (double-counting risk for
reputation scorers).Review/Concordia/V0.6_Predicate_Primitive_Spec_Draft_2026-05-14.md
captures the predicate shape, condition profiles, canonicalization
rules, verification surface, and composition contracts with mandate,
attestation, and ApprovalReceipt. Public-draft promotion follows the
v0.6.0 PyPI cut.references[] shape shipped in v0.4.0. Layering boundary documented
explicitly: envelope-level references are cryptographic (provenance,
supersession of envelopes); attestation-level references are semantic
(content linkage between attestations). Verifiers MUST NOT conflate
the two surfaces in any verification step.supersedes (MUST), extends (SHOULD),
fulfills (SHOULD), references (MAY, weak generic association;
use only when no stronger relationship applies).urn:concordia:attestation, urn:concordia:mandate,
urn:concordia:offer, urn:concordia:session) and references the
linked-protocol URN schemes for A2A, AP2, x402, and ERC-8004.schemas/reference.schema.json. Canonical machine-readable schema
for the attestation-level reference object. $id
urn:concordia:schema:reference:v0.5. Required keys id, type,
relationship. Optional keys version, signed_at, signer_did,
and a forward-compatibility extensions map for v0.x extension
preservation.version,
signed_at, signer_did, and extensions keys are now schema-allowed
on each attestation-level reference entry. v0.4.x emitters that omit
these continue to validate cleanly.schemas/attestation.schema.json $id bumped to
urn:concordia:schema:attestation:v0.5. Embedded reference $def
mirrors schemas/reference.schema.json.attestation.schema.json synced byte-for-byte with
schemas/attestation.schema.json.0.5.0-draft.pyproject.toml version bumped from 0.4.0 to 0.5.0.concordia.__version__ bumped from 0.4.0 to 0.5.0.concordia.attestation._validate_reference() error text aligned with
SPEC §11.5 section references for operator legibility (citing
§11.5.6 for shape and §11.5.5 for relationship vocabulary).concordia.attestation._validate_reference() now preserves unknown
type and relationship values as opaque strings per SPEC §11.5.8
MUST forward-compat clause. v0.4.x callers passing only canonical
values are unchanged. Callers passing extension values previously got
ValueError and now roundtrip cleanly. This is strictly more
permissive; existing tests pass unchanged.version, signed_at,
signer_did, extensions) are now passed through _validate_reference()
on the attestation generation path so callers can roundtrip extension
data per SPEC §11.5.6.concordia.attestation.generate_attestation() docstring updated to
point at SPEC §11.5 with one-line summary of the layering boundary.concordia.envelope.build_trust_evidence_envelope() envelope-level
reference validation cites SPEC §11.5.2 in its error text and inline
comments document the §11.5.4 layering boundary.No breaking API changes. v0.4.0-shaped attestations continue to validate cleanly against the v0.5 JSON Schema (forward-compat is structural: every v0.4 reference is a valid v0.5 reference; the v0.5 optional fields are additive and absent on v0.4 emissions).
Beta-3 (separate PR) cuts the PyPI v0.5.0 release with tag and GitHub Release.
resolve_algorithm() env-var precedence helper. Single helper
in concordia.signing that resolves the JWS algorithm by precedence:
explicit arg > CONCORDIA_JWS_ALG env var > EdDSA default.
ES256 signing/verification itself (ES256KeyPair,
sign_message(alg="ES256"), verify_signature(alg="ES256"), cross-
algorithm rejection) was already shipped in the pre-v0.4.0 trust-
evidence-format envelope and mandate primitive work; this WP adds
only the missing env-var layer.references[] on attestations. Top-level
references array on generate_attestation() output with shape
{type, id, relationship}. type ∈
{receipt, chain_session, predicate, mandate}. relationship ∈
{supersedes, extends, fulfills, references}. chain_session,
predicate, and mandate are reserved for CMPC primitives in v0.5
and accepted today as opaque refs so v0.5 is a pure add rather than
a breaking schema change. Distinct from the envelope-level
{kind, urn, verified_at, verifier_did, hash} #1734 shape — both
coexist at different layers.validity_temporal on attestations. Optional
tagged union with modes absolute/relative/window:
{mode: "absolute", from, until},
{mode: "relative", from, duration_seconds}, or
{mode: "window", start, end, duration_seconds}. Adds
concordia.is_valid_now(attestation) helper. Attestations without
the field return True (no temporal constraint). Distinct from
models/mandate.py::ValidityWindow (sequence/windowed/
state_bound, #1734 envelope shape); unification is v0.5+.Session.on_terminal is a publicly assignable
Callable[[Session], None] that fires exactly once when a session
reaches AGREED / REJECTED / EXPIRED. Exceptions inside the callback
are swallowed — reputation reporting never blocks a transition.
concordia.make_verascore_auto_hook(key_pair, agent_did, ...)
produces a callback gated by VERASCORE_ENABLED=true. Endpoint
precedence: explicit arg > VERASCORE_ENDPOINT env > default
https://verascore.ai. Default report_on=("agreed",); widen to
("agreed", "rejected", "expired") as desired. Payload carries
session_id as the Verascore-side idempotency key
(prisma.concordiaReceipt.upsert({where: {sessionId}})).docs/A2A_COMPOSITION.md alignment. Rewrote the
“Verascore as the reputation layer” paragraph to describe the v0.4.0
auto-hook surface accurately — reporting is opt-in via
VERASCORE_ENABLED, idempotency is keyed on session_id, receipts
are the substrate.mandate_verification (build-plan work package) — deferred
to v0.4.1 pending A2CN mandate-shape coordination with cmagorr1.
A standalone mandate primitive already ships (concordia.mandate)
and is orthogonal to WP4’s attestation-side verification path.server.json manifest for MCP Registry
submission with ownership tag in README. Submission docs and
awesome-mcp-servers PR template at review/. (c2d6176)concordia.envelope
module producing signed TEF v1.0.0 envelopes with ES256 signing support
alongside existing EdDSA. Three MCP tools added:
concordia_export_tef_envelope, concordia_verify_tef_envelope,
concordia_list_tef_envelopes. 542 envelope tests. (e7c69de)concordia.mandate and concordia.models.mandate
modules implementing the Mandate model (schema URN
urn:concordia:schema:mandate:v1). SD-JWT-adjacent structure with
three-mode validity (sequence/windowed/state_bound), delegation
chains, revocation endpoints, and constraint patterns
(max_spend/allowed_categories/geographic_bounds/temporal_budget).
Three MCP tools: concordia_create_mandate, concordia_verify_mandate,
concordia_revoke_mandate. 1,077 mandate tests. (4266269)0.3.1. (cce3fc6)concordia.agent_profile package with
AgentProfile model and ProfileStore for capability-based search and
filtering. 86 discovery tests. (ae8621b)concordia_register_agent,
concordia_search_agents, concordia_get_agent_profile,
concordia_update_agent_profile. Version bump to 0.3.0. (d83b75b)concordia_verascore_report tool. Push negotiation receipts to
Verascore with Ed25519-signed payloads. Auth token required,
fulfillment_status validated, session must be terminal. (9eed527)~/.concordia/bridge-config.json at startup.
Manual configuration via concordia_sanctuary_bridge_configure
still works. (bbe48b5)v* tags for automated releases. (b9b6447)public: bool = False flag; session_public_view
redacts counterparty agent_ids to role-only stubs unless the
session has been explicitly marked public.http:// API base
unless the page origin is localhost or ?dev=1 is passed, enforces
same-origin lock between page and API base, and shows a persistent
red warning banner on plaintext HTTP.kty==="OKP", crv==="Ed25519", and that both
d and x are non-empty strings before calling
crypto.subtle.importKey.canonical_json and the JS canonicalJson embedded
in respond.html produce byte-identical output across 20 shared
vectors (unicode, floats, nested objects, arrays, null, key
ordering, escapes). 40 assertions total.ReceiptBundle.summary()), suitable for UI rendering and
agent-to-agent status exchange.session_public_view MCP tool — exposes a redacted view of a session
(state, participants, message count, terms hash) without revealing raw deal
terms. Enables lightweight discovery without breaching the “attestations
never contain deal terms” privacy invariant.concordia/static/)
for manual session acceptance during demos and first-handshake debugging.docs/EFFICIENCY.md explaining how Concordia’s structured
offers reduce round-trips vs. free-form negotiation.0.2.0.