Skip to main content

VerbRegistry

Struct VerbRegistry 

Source
pub struct VerbRegistry { /* private fields */ }
Expand description

Immutable registry that dispatches verb calls to registered packs.

Clone is cheap (Arc-wrapped). Constructed via VerbRegistryBuilder.

Implementations§

Source§

impl VerbRegistry

Source

pub const SIDE_EFFECTING_ASSERTIVE_VERBS: &'static [&'static str]

Verbs classified VerbCategory::Assertive that nonetheless schedule can schedule a persisted write on a successful dispatch, so a caller re-issuing a call in this list after a lost response duplicates that write:

  • memory.recall schedules brain.record_serve, which inserts a serve-ledger row keyed in part on a served_at timestamp captured fresh at dispatch time — a second dispatch inserts a second row rather than colliding with the first.
  • search (the kg pack’s bare verb) appends a search_executed event with a freshly generated id and no natural key at all.
  • telemetry.emit can append a durable stream record with a fresh identity and sequence, depending on the configured channel policy.

The speech-act category alone cannot rule this out — it describes what the verb tells the caller, not what it schedules against storage. Adding a verb here (or removing one because its side effect was made idempotent) is a correctness decision requiring the same scrutiny as the categorization itself.

Source

pub async fn resolve_kg_read_by_id( &self, runtime: &KhiveRuntime, token: &NamespaceToken, id: Uuid, include_deleted: bool, ) -> Result<Option<Resolved>, RuntimeError>

Resolve a KG entity/note handle across the configured backend inventory.

The caller must supply its dispatch-authorized token. By-ID reads do not filter the stored namespace (ADR-007); no new token is minted here. With ordinary single-runtime registration, retain the supplied runtime’s existing behavior. This does not route mutations or pack-private records.

Source

pub async fn resolve_entity_delete_runtime( &self, runtime: &KhiveRuntime, token: &NamespaceToken, id: Uuid, ) -> Result<Option<KhiveRuntime>, RuntimeError>

Find the unique configured backend holding an entity for deletion. Includes tombstones so soft deletion cannot hide a duplicate owner. The dispatch-authorized token is preserved; lookup is namespace-agnostic.

Source

pub async fn cleanup_deleted_entity_attachments( &self, runtime: &KhiveRuntime, token: &NamespaceToken, id: Uuid, ) -> Result<bool, RuntimeError>

Clean main-backend attachments after no live or tombstoned owner remains. A live or tombstoned entity on any configured backend keeps its roots.

Source

pub async fn authorize_effective_kg_read( &self, token: &NamespaceToken, verb: &str, effective_args: Value, effective_id: Uuid, ) -> Result<(), RuntimeError>

Recheck a merged-entity read against the kept id before returning it. The submitted argument shape is the verb’s ordinary shape with the effective id substituted. The dispatch’s original check remains its own audit row; this consultation records the effective target as a second row without changing the public GateRequest schema.

Source

pub async fn resolve_kg_read_prefix( &self, runtime: &KhiveRuntime, _token: &NamespaceToken, prefix: &str, include_deleted: bool, ) -> Result<Option<Uuid>, RuntimeError>

Resolve a prefix across the same inventory, rejecting distinct UUIDs.

Retains the local prefix scanner’s entity/note/event/edge collision domain, including sidecar events. The returned UUID is not a substrate assertion: consumers must still fetch/type-check it. All backend failures propagate.

Source

pub fn default_namespace(&self) -> &str

This registry’s construction-baked default namespace.

Used as the fallback when a request carries no RequestIdentity override (ADR-096 Fork 1) and by transports that need to advertise their own resolved identity when forwarding to a warm daemon.

Source

pub fn actor_id(&self) -> Option<&str>

This registry’s construction-baked actor identity label, if configured (ADR-057). None means dispatch mints ActorRef::anonymous() absent a per-request RequestIdentity override (ADR-096 Fork 1).

Source

pub fn visible_namespaces(&self) -> &[Namespace]

This registry’s construction-baked extra read-visibility namespaces (ADR-007 Rev 4 Rule 3b), used absent a per-request RequestIdentity override (ADR-096 Fork 1).

Source

pub fn event_store(&self) -> Option<Arc<dyn EventStore>>

This registry’s configured audit EventStore, if any (ADR-094).

Lets background tasks that hold a VerbRegistry but do not go through dispatch (e.g. the email channel poll loop) append best-effort lifecycle events to the same sink gate-check audit rows use, without threading a second Option<Arc<dyn EventStore>> field through every caller. None means either the historical tracing-only default or an intentionally read-only audit backend; callers that need to distinguish those cases use Self::audit_persistence_advisory.

Source

pub fn audit_batch_metrics(&self) -> Option<RuntimeAuditBatchMetrics>

Process-lifetime audit-batch health counters for this registry’s ADR-133 seam, if one is configured. None exactly when Self::event_store is None — the same condition under which no batch exists to report on. The db_diagnostics verb feeds this into KhiveRuntime::db_diagnostics_with_audit_metrics so an operator can see flush failures and pure-observability degradation instead of the permanently-unavailable placeholder a bare KhiveRuntime reports.

admission_refused_obligations and admission_unresolved_obligations are sourced separately from audit_admission_refused_obligation_count and audit_admission_unresolved_obligation_count rather than from batch.health_metrics(): they count a decision made in append_audit_event_best_effort (ADR-103 Amendment 3 / ADR-133 Amendment 1), not a property of the batch itself, so they are process-wide like the rest of this struct’s fields rather than per-AuditBatch.

Source

pub fn audit_batch_handle(&self) -> Option<Arc<AuditBatch>>

Test/diagnostic-only accessor for the underlying ADR-133 audit-batch seam. None when no EventStore was configured (the batch is lazily constructed from one). Exposed so admission-pressure mechanism tests can saturate and drain the SAME instance a real dispatch uses (#2117, #2147, #2208, #2217) instead of testing a look-alike.

Source

pub async fn shutdown_audit_batch(&self) -> Result<(), AuditTerminalReason>

Stop admitting new audit rows and wait for every already-accepted row to reach a terminal state (ADR-133).

A no-op returning Ok(()) when no EventStore — and therefore no audit-batch seam — is configured. Callers that own this registry’s shutdown sequence should call this before tearing down the writer or database so no accepted audit row is silently dropped mid-flight.

Source

pub fn audit_persistence_advisory(&self) -> Option<Value>

Advisory for a dispatch whose configured audit sink is read-only.

The MCP transport places this beside successful per-operation results; None means audit persistence is configured normally or was never configured at all.

Source

pub fn is_read_replay_safe(&self, verb: &str) -> bool

Transport replay eligibility from the shared operation-effects table, restricted to trusted canonical public handlers. A read that persists a fresh serve or telemetry row is excluded because the request id is correlation, not deduplication. Custom and mounted handlers cannot inherit safety from a name/category.

Source

pub fn describe_verb(&self, verb: &str) -> Result<Value, RuntimeError>

Return the help schema envelope for a verb.

Walks registered packs for the first matching HandlerDef and returns a structured JSON envelope. Subhandlers carry callable_via_mcp: false. Every envelope carries the shared identifier_resolution contract. link’s envelope additionally carries endpoint_rules — the composed per-relation source/target allowlist (issue #964) — so batch callers can defer to the kernel’s own table instead of re-implementing it locally. Every uuid/array of uuid parameter description has its declared IdResolutionMode’s contract text appended — the same text rendered under identifier_resolution.resolution_modes — so the full-UUID-vs-short-prefix rule is stated once per mode (in resolution_mode_contract) and inherited by every matching param, instead of restating it per param across every HandlerDef in every pack. Parameters whose mode is IdResolutionMode::NotApplicable (every non-identifier parameter) are left unchanged. Unknown verbs return RuntimeError::InvalidInput. Full shape documented in docs/protocol.md §Request Schema.

Source

pub fn authorize_namespace(&self, ns: Namespace) -> Result<(), RuntimeError>

Check whether the gate permits writes into ns.

Performs a gate evaluation with verb "authorize" before any background loop is spawned (ADR-056 §6). Returns Ok(()) when the gate allows the namespace, or Err(RuntimeError::PermissionDenied{..}) when denied. Gate errors (implementation failures) are surfaced as RuntimeError::Internal carrying the stable classified reason; the bounded, masked backend detail goes to the server-side log here, since callers log the returned error.

Source

pub async fn dispatch_intercepted_with_identity<F, Fut>( &self, verb: &str, params: &Value, identity: Option<&RequestIdentity>, dispatch: F, ) -> Result<Value, RuntimeError>
where F: FnOnce(Namespace) -> Fut, Fut: Future<Output = Result<Value, RuntimeError>>,

Gate and execute an operation handled outside normal pack dispatch.

Multi-backend transports use this to route an operation through a coordinator while retaining Self::dispatch_with_identity’s gate and audit lifecycle. Deny is authoritative, gate errors fail closed, and an allowed audit is persisted after the intercepted operation resolves so its outcome and duration reflect the operation result. Successful git.digest interception uses the same strict durable-receipt exception as normal pack dispatch.

Source

pub async fn dispatch_intercepted_with_metadata_with_identity<M, F, Fut>( &self, verb: &str, params: &Value, identity: Option<&RequestIdentity>, dispatch: F, ) -> Result<InterceptedDispatchResult<M>, RuntimeError>
where F: FnOnce(Namespace) -> Fut, Fut: Future<Output = Result<InterceptedDispatchResult<M>, RuntimeError>>,

Gate and execute an intercepted operation whose transport needs typed metadata in addition to the canonical verb result.

Audit accounting always receives outcome.result; outcome.metadata crosses the dispatch seam unchanged for the transport to place beside that result in its own envelope.

Source

pub async fn dispatch_intercepted_with_metadata_and_disposition<M, F, Fut>( &self, verb: &str, params: &Value, identity: Option<&RequestIdentity>, dispatch: F, ) -> Result<InterceptedDispatchResult<M>, DispatchError>
where F: FnOnce(Namespace) -> Fut, Fut: Future<Output = Result<InterceptedDispatchResult<M>, RuntimeError>>,

Execute an intercepted operation while retaining this boundary’s failure provenance. Successful canonical results and typed metadata are returned unchanged.

Source

pub fn allows_note_key_disclosure( &self, token: &NamespaceToken, kind: &str, key: &str, ) -> bool

A create refusal may reveal its key holder only when the same caller can list it.

Source

pub async fn dispatch( &self, verb: &str, params: Value, ) -> Result<Value, RuntimeError>

Dispatch a verb to the first pack that handles it.

Routes through the gate, then invokes the matching pack handler. When params["help"] == true, short-circuits to describe_verb with no side effects. Gate errors fail closed. Full dispatch flow documented in docs/protocol.md.

Equivalent to self.dispatch_with_identity(verb, params, None) — uses this registry’s construction-baked default_namespace / actor_id / visible_namespaces.

Source

pub async fn dispatch_with_identity( &self, verb: &str, params: Value, identity: Option<RequestIdentity>, ) -> Result<Value, RuntimeError>

Dispatch a verb, optionally overriding this registry’s baked identity scalars for exactly this call (ADR-096 Fork 1).

identity = None behaves exactly like Self::dispatch. identity = Some(id) uses id.namespace / id.actor_id / id.visible_namespaces in place of self.default_namespace / self.actor_id / self.visible_namespaces for this call’s namespace resolution, gate request, and token minting. The registry’s own fields are never mutated, so concurrent calls with different (or no) identity are independent. See docs/api/pack.md#dispatch_with_identity for why this enables one warm registry to serve many attribution identities over a shared backend.

Source

pub async fn dispatch_with_disposition( &self, verb: &str, params: Value, identity: Option<RequestIdentity>, ) -> Result<Value, DispatchError>

Dispatch with provenance for this operation’s own domain result. Errors returned by a nested dispatch remain handler errors at this boundary.

Source

pub async fn dispatch_as( &self, verb: &str, params: Value, verified_actor: VerifiedActor, ) -> Result<Value, RuntimeError>

Dispatch a verb under an out-of-band verified actor identity.

verified_actor is a typed VerifiedActor (constructor rejects blank identifiers) — only code holding a VerbRegistry handle can supply it. dispatch_as never reads params["actor"] to derive the effective actor; individual verbs may still accept an actor field for their own documented business semantics, unrelated to the acting principal. Every pack handler that reads “who is calling” resolves it from the NamespaceToken the dispatch boundary mints, so verified_actor becomes exactly the principal those handlers observe.

Equivalent to dispatch_with_identity(verb, params, Some(identity)) with identity.actor_id = Some(verified_actor) and every other identity scalar (namespace, visible namespaces) left at this registry’s construction-baked value. Self::dispatch and Self::dispatch_with_identity are unaffected. See docs/api/pack.md#dispatch_as for the embedding-host use case and the blank-identifier safety rationale.

Source

pub fn resolvers(&self) -> &[(String, Box<dyn PackByIdResolver>)]

Registered pack-level by-ID resolvers, in registration order.

Each element is (pack_name, resolver). The kg get and delete handlers iterate this slice to probe pack-private tables when the standard KG substrates (entity/note/edge/event) return None for a given UUID.

Source

pub fn reference_ring(&self) -> &Arc<ReferenceRing> ⓘ

The daemon-warm recently-referenced ring (unified-verb draft ADR, Slice 1). Consumed by resolve_reference (Layer 0 stage 2) and by the resolve verb handler; admitted-to by every successful by-id dispatch (see the admission block in dispatch_with_identity).

Source

pub fn find_kind_hook(&self, kind: &str) -> Option<Arc<dyn KindHook>>

Find a kind hook among the registered packs.

Walks packs in registration order; the first pack that both owns the kind (declares it in note_kinds() or entity_kinds()) and returns a hook from kind_hook(kind) wins. Returns None if the kind is unknown to all packs or no owning pack registered a hook.

Source

pub fn entity_kind_hooks(&self) -> EntityKindHooks

Every (entity kind, hook) pair for which the owning pack declares the entity kind and registers a KindHook — the entity-scoped subset of Self::find_kind_hook’s ownership check, computed once.

khive-runtime does not hold a VerbRegistry (ownership runs the other way: packs are constructed FROM a runtime handle), so KhiveRuntime::install_entity_kind_hooks is the extension point that carries this aggregate to the runtime layer — the transport calls this after the registry is built, same timing as Self::all_edge_rules. Arc<dyn KindHook> values returned here hold no reference back to the pack or registry that produced them (every production kind_hook() implementation constructs a fresh, stateless hook per call), so installing this aggregate on the runtime creates no ownership cycle.

Source

pub async fn prepare_note_update_hook( &self, runtime: &KhiveRuntime, token: &NamespaceToken, note: &Note, args: &mut Value, ) -> Result<(), RuntimeError>

Run the owning kind’s shared-note-update normalizer/validator, if it declares one.

Compatibility wrapper for callers that only need normalization and validation. Writers use Self::prepare_note_update_policy and attach its returned policy so kind-specific property removals reach storage.

The ordering lives here, at the single dispatch site, rather than in a KindHook method a pack could override: a pack implements the two halves and cannot express a sequence, so it cannot replace the validator by overriding the sequence. See ADR-017.

Source

pub async fn prepare_note_update_policy( &self, runtime: &KhiveRuntime, token: &NamespaceToken, note: &Note, args: &mut Value, ) -> Result<NoteUpdatePolicy, RuntimeError>

Normalize and validate a note update, then carry the owning kind’s property policy into the shared prepared write. Writers must attach the returned policy to their NotePatch or snapshot update preparation; Self::prepare_note_update_hook remains the validation-only wrapper.

Source

pub async fn validate_note_update_hook( &self, runtime: &KhiveRuntime, token: &NamespaceToken, note: &Note, properties: Option<&Value>, ) -> Result<(), RuntimeError>

Run the owning kind’s shared-note-update property validator, if it declares one.

Kept as the validation-only compatibility seam for callers that do not own a mutable request object. Canonical and atomic CRUD use Self::prepare_note_update_hook instead, so a hook’s KindHook::normalize_note_update can run before its validation does. Reaching a hook through this seam therefore runs the validator alone: that is the point of it, and it is why callers that CAN supply a mutable request should not use it.

Run shared-link validators grouped by the owning source-note kind.

Supplying the whole proposed batch lets a kind hook reject an invariant violation formed only by multiple entries in that batch. Sources that are not live notes, or whose kind has no hook, remain the canonical endpoint validator’s responsibility.

Source

pub fn has_verb(&self, verb: &str) -> bool

Whether any registered pack declares a handler with this verb name.

A non-dispatch capability check: callers that would otherwise pay a guaranteed-failed dispatch (and its audit write) when an optional pack is absent can probe first and skip the call entirely.

Source

pub fn mounted_verb_snapshot(&self) -> Vec<Value>

Advisory metadata for synchronous planning and MCP initialization.

Source

pub async fn mounted_verb_catalog(&self) -> Result<Vec<Value>, RuntimeError>

Source

pub async fn apply_profile_section_feedback( &self, token: &NamespaceToken, profile_id: &str, section_signals: Value, target_attribution: Option<String>, ) -> Result<Value, RuntimeError>

Apply section evidence through the installed brain instance. Callers must validate their domain target and authorize their own operation first; this trusted Rust hook adds no handler to dispatch or the wire catalog.

Source

pub fn all_verbs(&self) -> Vec<&'static HandlerDef>

All MCP-exposed handlers across all registered packs (Visibility::Verb only).

Subhandlers (Visibility::Subhandler) are excluded — they are internal pipeline steps not surfaced on the MCP wire. Returned with 'static lifetime since pack handlers are &'static [HandlerDef] constants.

Source

pub fn all_verbs_with_names(&self) -> Vec<(&str, &'static HandlerDef)>

All MCP-exposed handlers paired with the name of the pack that owns them (Visibility::Verb only).

Subhandlers (Visibility::Subhandler) are excluded from the MCP catalog Use all_handlers_with_names when internal handlers must also be enumerated (e.g. runtime introspection).

Source

pub fn all_handlers_with_names(&self) -> Vec<(&str, &'static HandlerDef)>

All handler definitions across all registered packs, including subhandlers.

Unlike all_verbs, this includes Visibility::Subhandler entries. Useful for runtime introspection (e.g. list_handlers) and tooling that needs the complete handler surface.

Source

pub fn all_note_kinds(&self) -> Vec<&'static str>

Merged set of note kinds across all registered packs (deduplicated, first-seen order preserved).

Source

pub fn pack_owned_note_kinds(&self) -> Vec<&'static str>

Note kinds owned by a pack, i.e. every kind in all_note_kinds that is not one of the generic-CRUD pack’s own kinds.

GENERIC_CRUD_PACK declares the general-purpose note kinds the shared CRUD verbs exist to serve (observation, insight, …); every other pack’s kinds are records that pack’s own verbs create and maintain. Derived from the packs’ NOTE_KINDS constants, so a pack that adds or drops a kind moves this set with it — nothing is hardcoded here but the name of the generic pack itself.

Source

pub fn all_entity_kinds(&self) -> Vec<&'static str>

Merged set of entity kinds across all registered packs (deduplicated, first-seen order preserved).

Source

pub fn all_brain_consumer_kinds(&self) -> Vec<&'static str>

Merged set of brain profile consumer kinds requested by registered packs (deduplicated, first-seen order preserved).

Source

pub fn pack_names(&self) -> Vec<&str>

Names of packs in topological load order.

Source

pub fn pack_host_state<T: Any + Send + Sync>( &self, name: &str, ) -> Option<Arc<T>>

Borrow a registered pack’s shared host state without reconstructing that pack. Missing packs, absent state, and type mismatches return None.

Source

pub fn pack_requires(&self, name: &str) -> Option<&'static [&'static str]>

Declared dependencies for a registered pack.

Source

pub fn pack_note_kinds(&self, name: &str) -> Option<&'static [&'static str]>

Note kinds owned by a specific registered pack.

Returns None if no pack with name is registered. The slice is the pack’s NOTE_KINDS constant — 'static lifetime, no allocation.

Source

pub fn pack_entity_kinds(&self, name: &str) -> Option<&'static [&'static str]>

Entity kinds owned by a specific registered pack.

Returns None if no pack with name is registered. The slice is the pack’s ENTITY_KINDS constant — 'static lifetime, no allocation.

Source

pub fn pack_verbs(&self, name: &str) -> Option<&'static [HandlerDef]>

Handlers declared by a specific registered pack.

Returns None if no pack with name is registered. Each HandlerDef carries name + description + visibility — sufficient for introspection clients.

Source

pub fn all_edge_rules(&self) -> Vec<EdgeEndpointRule>

All pack-declared edge endpoint rules across registered packs.

Order follows topological pack registration; duplicates are not deduplicated — validation only checks membership, and an exact-duplicate rule is a harmless restatement.

Source

pub fn all_entity_types(&self) -> Vec<EntityTypeDef>

All pack-declared entity-type subtypes across registered packs.

Order follows topological pack registration; duplicates are not deduplicated here — same posture as all_edge_rules. Consumers compose this with EntityTypeRegistry::builtin() via EntityTypeRegistry::with_extra to get the boot-time composed registry.

Source

pub fn all_note_kind_specs(&self) -> Vec<&'static NoteKindSpec>

Collect all NoteKindSpec declarations from every loaded pack.

Used by the runtime for lifecycle introspection and future enforcement.

Source

pub fn all_validation_rules(&self) -> Vec<&'static ValidationRule>

All pack-contributed validation rules across registered packs.

Returns references into the pack-owned 'static slices — no allocation beyond the outer Vec. Rule IDs are namespaced by pack; callers can group by rule.id.split_once('/') to attribute rules to their packs.

Source

pub fn all_schema_plans(&self) -> Vec<SchemaPlan>

Pack-auxiliary schema plans for all registered packs.

Returns one SchemaPlan per pack. Callers (typically the runtime bootstrap) apply each plan to the pack’s assigned backend. Empty plans are included so the caller can iterate uniformly; callers that want to skip empty plans should check plan.is_empty(). Schema application must use Self::all_schema_plans_with_columns to retain column upgrades.

Source

pub fn all_schema_plans_with_columns( &self, ) -> Vec<(SchemaPlan, &'static [PackColumnAddition])>

Schema plans paired with the same owning pack’s nullable-column upgrades.

Callers applying plans directly must pass both entries to StorageBackend::apply_pack_ddl_statements_with_columns.

Source

pub fn call_register_embedders(&self, runtime: &KhiveRuntime)

Invoke PackRuntime::register_embedders on every registered pack.

Called by the transport during startup, after the registry is built and before the first verb dispatch, so that custom embedding providers contributed by packs are reachable via KhiveRuntime::embedder(name).

Packs whose register_embedders is the default no-op pay no overhead. The method is idempotent when the underlying registry uses last-wins semantics for duplicate provider names.

Source

pub fn call_register_entity_type_validators(&self, runtime: &KhiveRuntime)

Invoke PackRuntime::register_entity_type_validator on every registered pack.

Called by the transport during startup, after the registry is built and before the first verb dispatch, so that entity-type validation at the runtime layer is active for all write paths including direct create_many callers that bypass the handler layer.

Packs whose register_entity_type_validator is the default no-op pay no overhead.

Composes all_entity_types once and passes the same aggregate to every pack, mirroring how install_edge_rules installs one all_edge_rules() aggregate for the whole registry.

Source

pub fn call_register_note_mutation_hooks(&self, runtime: &KhiveRuntime)

Invoke PackRuntime::register_note_mutation_hook on every registered pack.

Called by the transport during startup, after the registry is built and before the first verb dispatch, so that note-mutation notifications at the runtime layer are active for all write paths — including KG’s update/delete verbs reaching a kind="memory" note, which have no crate-level dependency on khive-pack-memory.

Packs whose register_note_mutation_hook is the default no-op pay no overhead.

Source

pub fn call_register_note_write_validators(&self, runtime: &KhiveRuntime)

Invoke PackRuntime::register_note_write_validator on every registered pack.

Called by the transport during startup with the same timing as call_register_note_mutation_hooks, so note-write validation is active at the runtime layer for every write path — the generic create verb, direct Rust callers, and proposal apply, none of which dispatch a pack hook of their own on the note-write.

Source

pub async fn call_warm_all(&self)

Invoke PackRuntime::warm on every registered pack. Called by the daemon at boot (in a background task) so expensive in-memory state (ANN indexes) is pre-loaded without blocking request serving.

Source

pub fn presentation_policy_for(&self, verb: &str) -> VerbPresentationPolicy

Resolve the presentation policy for a verb name.

Walks all registered handlers (including subhandlers) for the first matching name and returns its declared VerbPresentationPolicy. Returns Standard for unknown verbs — unknown verbs will fail at dispatch anyway, so the fallback here is safe.

Source

pub fn verb_category(&self, verb: &str) -> Option<VerbCategory>

Resolve the declared VerbCategory for a verb name.

Walks all registered handlers (including subhandlers) for the first matching name and returns its speech-act category. Returns None for an unregistered verb name, so a caller deciding transport-level behavior (e.g. whether a post-dispatch condition is safe to retry) can fail closed on an unknown verb instead of guessing a category.

Source

pub fn is_retry_safe_after_frame_omission(&self, verb: &str) -> bool

Whether a response lost to the daemon frame budget may be truthfully advertised as safe to re-issue: the verb is VerbCategory::Assertive (no institutional commitment was made) and is not on Self::SIDE_EFFECTING_ASSERTIVE_VERBS (no persisted write to duplicate on a second dispatch). An unregistered verb name resolves to None from Self::verb_category and fails closed here.

Used only by the MCP daemon’s frame-budget omission decision; never for permission checking or return-shape selection.

Source

pub fn is_subhandler_verb(&self, verb: &str) -> bool

Returns true if the named verb exists and is tagged Visibility::Subhandler (internal / operator-only).

Used by the MCP server to gate subhandler invocation at the wire boundary without blocking internal callers that invoke the same verbs through the runtime directly.

Source

pub fn apply_schema_plans(&self, backend: &StorageBackend)

Apply all non-empty pack-auxiliary schema plans to the given backend.

This is the centralized startup hook that replaced the previous lazy per-pack self-bootstrap pattern. Each pack’s SchemaPlan carries idempotent CREATE TABLE IF NOT EXISTS DDL; calling this more than once is safe. Plans with neither SQL nor column upgrades are skipped.

Errors from individual plans are logged via tracing::warn! and not propagated so that a single pack’s schema failure does not prevent the rest from loading. Serving hosts must instead use the fallible Self::apply_schema_plans_with_map (with an empty map for one backend) so a required schema failure cannot leave a pack’s verbs unavailable.

Source

pub fn all_schema_plans_named(&self) -> Vec<(&'static str, SchemaPlan)>

Pack-auxiliary schema plans with their owning pack names.

Returns (pack_name, SchemaPlan) pairs for every registered pack. Used by the multi-backend boot path to apply each plan to the pack’s assigned backend rather than a single shared backend. Direct schema application must use Self::all_schema_plans_with_columns so column upgrades are retained.

Source

pub fn apply_schema_plans_with_map( &self, backend_for_pack: &HashMap<&str, &StorageBackend>, default_backend: &StorageBackend, ) -> Result<(), PackSchemaCollisionError>

Apply pack-auxiliary schema plans using a per-pack backend map.

For each plan and its owning pack’s column additions, applies the full plan to backend_for_pack[plan.pack] when present, falling back to default_backend for any pack not in the map.

Returns an error when two packs on the same backend declare the same auxiliary table (ADR-028 §7 collision policy: boot failure naming both packs and the conflicting table).

Both single- and multi-backend hosts use this boot path (ADR-028). An empty map selects the default backend for every pack. Read-only backends validate declared columns without applying SQL or acquiring a writer; missing or incompatible columns refuse boot with the pack name.

Trait Implementations§

Source§

impl Clone for VerbRegistry

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more