Phase 3 — Enforce trust tiers in capability registration and routing #298

Closed
opened 2026-09-17 05:49:07 +00:00 by Mark · 0 comments
Owner

Source

  • Vikunja task #196 (Phase 3 follow-up)
  • Parent: Mark/mesh-seed#56 (Phase 3 umbrella, closed)
  • Prior Phase 3 slice: PR #297 (GPU capability class, merged 2026-09-16) — established the precedent of treating tier/class as first-class fields on capability records and routing inputs.

Goal

Carry trust_tier through capability registration and make routing enforce the tier required by an intent/pathway. The substrate already has substrate/trust_tiers.py with TrustTier (LOW/MEDIUM/HIGH) and TrustTierManager (resolve_tier, contract_requirement, calculate_required_tier, find_execution_tier, allows_contract). What's missing is the integration on the registry + router side so trust becomes a real gate, not just a hint.

Scope

  1. Registration — first-class trust_tier field on capabilities

    • Add trust_tier (str | None) to PrimitiveRecord and to the canonical capability schema (schemas/capability.schema.json).
    • PrimitiveRegistry._register_template and register(...) must validate the value (via TrustTierManager.resolve_tier); unknown strings raise a clear error, not a silent default.
    • Backward compatibility: records with no trust_tier field must continue to load (defaulting to a documented "unverified" value, e.g. TrustTier.LOW so they fail closed on stricter intents but remain routable on intents that don't require trust). Surface this default explicitly in the schema description and the field docstring.
    • Round-trip must hold: PrimitiveRecord.from_dict(record.to_dict()) works whether trust_tier is set or unset.
  2. Intent/Pathway — declared required tier

    • Add an optional required_trust_tier (or min_trust_tier) field to the intent schema (schemas/intent.schema.json) and document the convention for pathways (runtime/pathway_manager.py).
    • TrustTierManager.intent_minimum_tier already reads min_trust_level / min_trust / trust_tier from intent dicts; extend it to also read required_trust_tier so both names work.
    • When the intent declares no tier and the contract has no requirement, the router must default to a documented behavior (currently: LOW/none) — not silently bypass trust.
  3. Router — enforce, score, reject

    • runtime/intent_router.py::_route_standard already calls trust_manager.calculate_required_tier(...) and find_execution_tier(...); verify the trust-block path (reason=trust_level_unavailable) actually surfaces in _route_standard, _route_gpu, and any other routing entry point. Today it only runs in _route_standard — the GPU path and pathway path need the same gate.
    • Tie-breaking: when multiple candidates survive trust + resource scoring, the router must prefer higher trust_tier first (HIGH > MEDIUM > LOW) so a HIGH-trust capability is preferred over an equally-scored LOW-trust one. The exact rule belongs as a docstring + comment block next to the scoring code.
    • Missing metadata: if a capability record has no trust_tier, the router must NOT silently assume HIGH; it must treat the candidate as LOW (or the documented default) so a stricter intent still rejects it. This is the "no silent bypass" requirement.
  4. Tests (tests/unit/)

    • test_capability_registry_trust.py — registration with valid tier, invalid tier (raises), missing tier (loads as default), round-trip, schema validation.
    • test_router_trust_enforcement.py — required-tier match routes, insufficient trust blocks with trust_level_unavailable, missing metadata is treated as LOW, tie-break picks HIGH over LOW at equal score, GPU route also enforces trust, intent without tier + contract without requirement defaults consistently.
    • Update existing test_trust_tiers.py and test_router.py if any assertions change.
  5. Docs

    • docs/reference/TRUST_TIERS.md (or extend an existing reference) documenting:
      • the three tiers and their policies (already in trust_tiers.py),
      • how a capability declares trust_tier,
      • how an intent declares its minimum tier,
      • the eligibility rule (≥ required tier, prefer higher tier on ties, no silent bypass on missing metadata),
      • the single-node boundary (no federation policy here).

Acceptance criteria

  • Registered capabilities expose a validated trust_tier and preserve backward compatibility for legacy records.
  • Router behavior is tested for required-tier match, insufficient trust, and missing metadata.
  • The scoring/eligibility rule is documented next to the routing code.
  • No trust decision is silently bypassed when metadata is absent.
  • Single-node only — no federation policy in this slice.

Out of scope

  • Cross-mesh / federation policy.
  • Changing the policy table in substrate/trust_tiers.py.
  • Reworking runtime/capability_watcher.py beyond what schema changes require.
  • The mesh-seed#56 umbrella tasks that are still open elsewhere.

Reference

  • substrate/trust_tiers.py — existing tier definitions + manager.
  • runtime/capability_registry.py — wraps PrimitiveRegistry.
  • runtime/primitive_registry.py — PrimitiveRecord + template loader.
  • runtime/intent_router.py — _route_standard, _route_gpu, _route_via_planner.
  • runtime/pathway_manager.py — pathway spec (where required-tier should also surface).
  • schemas/capability.schema.json + schemas/intent.schema.json — schemas.
  • tests/unit/test_trust_tiers.py — existing tests to extend.

## Source - Vikunja task #196 (Phase 3 follow-up) - Parent: Mark/mesh-seed#56 (Phase 3 umbrella, closed) - Prior Phase 3 slice: PR #297 (GPU capability class, merged 2026-09-16) — established the precedent of treating `tier`/`class` as first-class fields on capability records and routing inputs. ## Goal Carry `trust_tier` through capability registration and make routing enforce the tier required by an intent/pathway. The substrate already has `substrate/trust_tiers.py` with `TrustTier` (LOW/MEDIUM/HIGH) and `TrustTierManager` (resolve_tier, contract_requirement, calculate_required_tier, find_execution_tier, allows_contract). What's missing is the *integration* on the registry + router side so trust becomes a real gate, not just a hint. ## Scope 1. **Registration — first-class `trust_tier` field on capabilities** - Add `trust_tier` (str | None) to `PrimitiveRecord` and to the canonical capability schema (`schemas/capability.schema.json`). - `PrimitiveRegistry._register_template` and `register(...)` must validate the value (via `TrustTierManager.resolve_tier`); unknown strings raise a clear error, not a silent default. - **Backward compatibility:** records with no `trust_tier` field must continue to load (defaulting to a documented "unverified" value, e.g. `TrustTier.LOW` so they fail closed on stricter intents but remain routable on intents that don't require trust). Surface this default explicitly in the schema description and the field docstring. - Round-trip must hold: `PrimitiveRecord.from_dict(record.to_dict())` works whether `trust_tier` is set or unset. 2. **Intent/Pathway — declared required tier** - Add an optional `required_trust_tier` (or `min_trust_tier`) field to the intent schema (`schemas/intent.schema.json`) and document the convention for pathways (`runtime/pathway_manager.py`). - `TrustTierManager.intent_minimum_tier` already reads `min_trust_level` / `min_trust` / `trust_tier` from intent dicts; extend it to also read `required_trust_tier` so both names work. - When the intent declares no tier and the contract has no requirement, the router must default to a documented behavior (currently: `LOW`/`none`) — not silently bypass trust. 3. **Router — enforce, score, reject** - `runtime/intent_router.py::_route_standard` already calls `trust_manager.calculate_required_tier(...)` and `find_execution_tier(...)`; verify the trust-block path (`reason=trust_level_unavailable`) actually surfaces in `_route_standard`, `_route_gpu`, and any other routing entry point. Today it only runs in `_route_standard` — the GPU path and pathway path need the same gate. - **Tie-breaking:** when multiple candidates survive trust + resource scoring, the router must prefer higher trust_tier first (HIGH > MEDIUM > LOW) so a HIGH-trust capability is preferred over an equally-scored LOW-trust one. The exact rule belongs as a docstring + comment block next to the scoring code. - **Missing metadata:** if a capability record has no `trust_tier`, the router must NOT silently assume HIGH; it must treat the candidate as `LOW` (or the documented default) so a stricter intent still rejects it. This is the "no silent bypass" requirement. 4. **Tests** (`tests/unit/`) - `test_capability_registry_trust.py` — registration with valid tier, invalid tier (raises), missing tier (loads as default), round-trip, schema validation. - `test_router_trust_enforcement.py` — required-tier match routes, insufficient trust blocks with `trust_level_unavailable`, missing metadata is treated as LOW, tie-break picks HIGH over LOW at equal score, GPU route also enforces trust, intent without tier + contract without requirement defaults consistently. - Update existing `test_trust_tiers.py` and `test_router.py` if any assertions change. 5. **Docs** - `docs/reference/TRUST_TIERS.md` (or extend an existing reference) documenting: - the three tiers and their policies (already in `trust_tiers.py`), - how a capability declares `trust_tier`, - how an intent declares its minimum tier, - the eligibility rule (≥ required tier, prefer higher tier on ties, no silent bypass on missing metadata), - the single-node boundary (no federation policy here). ## Acceptance criteria - [ ] Registered capabilities expose a validated `trust_tier` and preserve backward compatibility for legacy records. - [ ] Router behavior is tested for required-tier match, insufficient trust, and missing metadata. - [ ] The scoring/eligibility rule is documented next to the routing code. - [ ] No trust decision is silently bypassed when metadata is absent. - [ ] Single-node only — no federation policy in this slice. ## Out of scope - Cross-mesh / federation policy. - Changing the policy table in `substrate/trust_tiers.py`. - Reworking `runtime/capability_watcher.py` beyond what schema changes require. - The `mesh-seed#56` umbrella tasks that are still open elsewhere. ## Reference - `substrate/trust_tiers.py` — existing tier definitions + manager. - `runtime/capability_registry.py` — wraps `PrimitiveRegistry`. - `runtime/primitive_registry.py` — `PrimitiveRecord` + template loader. - `runtime/intent_router.py` — `_route_standard`, `_route_gpu`, `_route_via_planner`. - `runtime/pathway_manager.py` — pathway spec (where required-tier should also surface). - `schemas/capability.schema.json` + `schemas/intent.schema.json` — schemas. - `tests/unit/test_trust_tiers.py` — existing tests to extend. --- <!-- forgejo-id: Mark/mesh-seed:trust-tier-routing-phase3 -->
Mark closed this issue 2026-09-18 01:17:08 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/mesh-seed#298
No description provided.