Status: implemented and merged to main (2026-07-03). This is the
architecture reference — how the shipped system works. The design rationale is
docs/roadmap/TIER_5.2_TRUST_MEMBRANE.md; the
per-artefact validator model is TIER_5.2_VALIDATORS.md;
marketplace portability is TIER_5.2_PORTABILITY.md.
1. The idea in one paragraph
Trust is a visible, cryptographically-verifiable badge on an artefact, and the agent is the primary unit: a signed agent is trusted exactly when its whole composition is — its active ontology and skills must each be signed 🟢. Trust is computed, never re-derived; sharing stays fully open (badge, not gate). Three states: ⚪ unsigned, 🟢 trusted (signed & intact), 🟠 changed (signed, but content drifted since). Default (no attestations) = a byte-identical baseline — every artefact is ⚪.
2. Module map (src/trusted_data_agent/core/trust/)
| Module | Responsibility |
|---|---|
attestation.py |
Pure core: TrustState, content_hash, id- & order-independent composition_hash, resolve_state, resolve_agent_trust, agent_signable (bottom-up rule), the validator registry, ValidationVerdict + SignBand (clean/partial/blocked). Zero I/O. |
scanners.py |
Deterministic 0-token safety scanners: content_safety_scan (injection), code_safety_scan (AST), sql_safety_scan, markup_safety_scan (XSS), aggregate_verdict. ScanResult splits findings into blocking vs caveats. |
validators.py |
The 8 per-kind validators (ontology · skill · extension · knowledge · planner · flow · dashboard · canvas), each returning a ValidationVerdict, registered by kind. The remaining 2 signable categories (agent, agent_pack) are the aggregate/composition path — signed only when all their parts are, with no per-kind register_validator. 8 per-kind + 2 aggregate = the 10 signable categories in §3. |
content.py |
Canonical per-kind content + version_hash resolver (skill/ontology/extension/knowledge/planner/flow/dashboard/canvas). One definition, shared by sign-off, badge state, and portability. |
composition.py |
A real profile → its ingredients (active KG + active skills) → live AgentTrust. |
pack.py |
Agent-pack composition resolver — a pack is "an agent whose ingredients are its members". |
store.py |
The trust_attestations table (self-applying), Ed25519 sign/verify reusing the platform provenance key, content-bound signatures + the signer public key carried for cross-instance verification. |
portability.py |
Marketplace capture / reinstate / claim_state + the honesty gate. |
validators registry |
register_validator(kind, fn) — new kind = one function, no forks. |
REST seam: api/trust_routes.py (GET /v1/trust/agent/<id>, GET/POST /v1/trust/artifact(s),
POST /v1/trust/<kind>/<id>/sign-off, POST /v1/trust/verify). UI: static/js/handlers/trustBadge.js.
3. The validator model (all 10 categories)
Every signable kind maps onto one closed archetype set — the two shipped poles (conformance, content-safety) plus code-safety, query-safety, provenance-integrity, and aggregate. Each validator is pure, deterministic, 0-token, and maps its result onto the harmonised band clean · partial · blocked.
| Artefact | kind |
Signable content | Archetype |
|---|---|---|---|
| Ontology (KG) | ontology |
entities + relationships | conformance (Tier 4.3 gate) |
| Skill | skill |
instruction text | content-safety |
| Agent (profile) | agent |
composition over ingredients | aggregate |
| Extension | extension |
handler source + manifest | code + content-safety |
| Knowledge repo | knowledge |
sorted(per-doc hash) + embedding |
integrity + content-safety |
| Planner repo | planner |
sorted(per-case hash) |
integrity + query-safety |
| Agent pack | agent_pack |
composition over members | aggregate |
| Flow | flow |
node/edge logic (positions excluded) | code + query + content |
| Dashboard | dashboard |
tile structure + data source | query-safety |
| Canvas | canvas |
markup | markup/XSS + content |
Full detail: TIER_5.2_VALIDATORS.md §6. Config artefacts
(MCP servers, LLM configs, vector/graph backends) are not-attestable by design — their
content is credentials, and trust ≠ access.
4. The bottom-up sign gate
agent_signable(ingredients) refuses to sign an agent unless every ingredient is already
🟢; the blocking list drives the guided "sign these first" flow. The same rule composes for
agent packs (pack.member_refs → agent_signable). Verdicts are Ed25519-signed and
bound to the exact content version (store.sign).
5. Badges + sign-off UX
trustBadge.js provides the reusable primitives:
- mountArtifactBadges(root) — fills [data-trust-artifact-*] slots with a signer-aware
seal (green intact · amber changed · faint "sign off" for signers on unsigned; nothing for
non-signers). Wired across Skills, Extensions, KGs, Repos, Agent Packs, and Workspace
instances (flow/dashboard/canvas).
- mountAgentBadges(root) — the compositional agent shield on the profiles list.
- openArtifactTrust(kind, id) — the trust popover: state · offline Verify · signer-only
Sign off / Re-sign (surfaces an agent-pack's blocking members).
- mountMarketplaceTrust(root) — read-only "publisher signed" seal on marketplace cards.
6. Marketplace portability
Trust travels with content, not ids: signatures are content-bound (kind|version_hash),
so an attestation survives an id remap. Every marketplace surface uses the same two calls —
capture(kind, id) at publish, reinstate(kind, new_id, claim) at materialize — and the
honesty gate re-establishes a signature only if the copy's live hash equals what was
signed. The claim carries the signer's public key, so a cross-instance consumer verifies with
the publisher's key. Wired into KG · agent-pack (+ per-member) · skill · extension ·
component-instance; collections inherit trust free via the reference model. Full detail:
TIER_5.2_PORTABILITY.md.
7. Packaging + isolation (the Ontology Suite)
The Trust Membrane ships bundled with the Platform Ontology UX as one physically-isolatable
enterprise feature — the Ontology Suite — governed by a single switch
(core/enterprise.py, ON for all tiers today; a one-line flip makes it Enterprise-only).
Removal manifest + absence-tolerance contract: src/trusted_data_agent/core/trust/README.md.
Canonical suite description: PLATFORM_ONTOLOGY_ARCHITECTURE.md §11.
8. Guarantees & scope
- Byte-identical baseline — with no attestations, every artefact is ⚪; nothing changes.
- Tamper-evident — any content edit flips 🟢 → 🟠 (hash mismatch).
- Offline-verifiable — Ed25519 signatures verify with only the signer's public key.
- Honest portability — a shared copy is 🟢 only if byte-identical to the signed original.
- Trust ≠ access — a signed artefact is validated, not authorized; secrets never travel.
Downstream consumers (Jul 2026): the membrane's integrity state now feeds two live
surfaces beyond the badge — (1) Behavioral Trust Score
(AGENT_OPS_EVAL_ARCHITECTURE.md §6c): the composite
per-agent trust state = live conduct capped by this integrity reading (unsigned caps at
"proven", changed caps at "watch" — a signature never promotes bad conduct), rendered as a
seal+ring glyph on the Agents roster; (2) trust-aware routing
(coordinate_engine.py: genieConfig.requireTrustedExperts) — a coordinator can require its
experts to resolve 🟢 at routing time, making compositional trust operative, not just visible.
Both resolve via composition.resolve_profile_trust defensively (suite absent → unknown /
loud fail-open warning), preserving the removability contract.
Remaining (minor): a cross-instance trusted-publisher policy (verification works; the allow-list is a config choice); Model B grounding (opt-in runtime enforcement that a turn only executes signed ingredients).
Tests: test/test_trust_membrane.py (132 assertions — three-state truth, hashing,
compositional truth table, all 10 validators, scanners, bands, portability incl. cross-instance
pubkey round-trip).