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
impl VerbRegistry
Sourcepub const SIDE_EFFECTING_ASSERTIVE_VERBS: &'static [&'static str]
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.recallschedulesbrain.record_serve, which inserts a serve-ledger row keyed in part on aserved_attimestamp captured fresh at dispatch time — a second dispatch inserts a second row rather than colliding with the first.search(thekgpack’s bare verb) appends asearch_executedevent with a freshly generated id and no natural key at all.telemetry.emitcan 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.
Sourcepub async fn resolve_kg_read_by_id(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
id: Uuid,
include_deleted: bool,
) -> Result<Option<Resolved>, RuntimeError>
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.
Sourcepub async fn resolve_entity_delete_runtime(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
id: Uuid,
) -> Result<Option<KhiveRuntime>, RuntimeError>
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.
Sourcepub async fn cleanup_deleted_entity_attachments(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
id: Uuid,
) -> Result<bool, RuntimeError>
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.
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.
Sourcepub async fn resolve_kg_read_prefix(
&self,
runtime: &KhiveRuntime,
_token: &NamespaceToken,
prefix: &str,
include_deleted: bool,
) -> Result<Option<Uuid>, RuntimeError>
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.
Sourcepub fn default_namespace(&self) -> &str
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.
Sourcepub fn actor_id(&self) -> Option<&str>
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).
Sourcepub fn visible_namespaces(&self) -> &[Namespace]
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).
Sourcepub fn event_store(&self) -> Option<Arc<dyn EventStore>>
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.
Sourcepub fn audit_batch_metrics(&self) -> Option<RuntimeAuditBatchMetrics>
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.
Sourcepub fn audit_batch_handle(&self) -> Option<Arc<AuditBatch>>
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.
Sourcepub async fn shutdown_audit_batch(&self) -> Result<(), AuditTerminalReason>
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.
Sourcepub fn audit_persistence_advisory(&self) -> Option<Value>
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.
Sourcepub fn is_read_replay_safe(&self, verb: &str) -> bool
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.
Sourcepub fn describe_verb(&self, verb: &str) -> Result<Value, RuntimeError>
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.
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.
Sourcepub async fn dispatch_intercepted_with_identity<F, Fut>(
&self,
verb: &str,
params: &Value,
identity: Option<&RequestIdentity>,
dispatch: F,
) -> Result<Value, RuntimeError>
pub async fn dispatch_intercepted_with_identity<F, Fut>( &self, verb: &str, params: &Value, identity: Option<&RequestIdentity>, dispatch: F, ) -> 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.
Sourcepub 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>>,
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.
Sourcepub 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>>,
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.
Sourcepub fn allows_note_key_disclosure(
&self,
token: &NamespaceToken,
kind: &str,
key: &str,
) -> bool
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.
Sourcepub async fn dispatch(
&self,
verb: &str,
params: Value,
) -> Result<Value, RuntimeError>
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.
Sourcepub async fn dispatch_with_identity(
&self,
verb: &str,
params: Value,
identity: Option<RequestIdentity>,
) -> Result<Value, RuntimeError>
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.
Sourcepub async fn dispatch_with_disposition(
&self,
verb: &str,
params: Value,
identity: Option<RequestIdentity>,
) -> Result<Value, DispatchError>
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.
Sourcepub async fn dispatch_as(
&self,
verb: &str,
params: Value,
verified_actor: VerifiedActor,
) -> Result<Value, RuntimeError>
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.
Sourcepub fn resolvers(&self) -> &[(String, Box<dyn PackByIdResolver>)]
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.
Sourcepub fn reference_ring(&self) -> &Arc<ReferenceRing> ⓘ
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).
Sourcepub fn find_kind_hook(&self, kind: &str) -> Option<Arc<dyn KindHook>>
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.
Sourcepub fn entity_kind_hooks(&self) -> EntityKindHooks
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.
Sourcepub async fn prepare_note_update_hook(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
note: &Note,
args: &mut Value,
) -> Result<(), RuntimeError>
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.
Sourcepub async fn prepare_note_update_policy(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
note: &Note,
args: &mut Value,
) -> Result<NoteUpdatePolicy, RuntimeError>
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.
Sourcepub async fn validate_note_update_hook(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
note: &Note,
properties: Option<&Value>,
) -> Result<(), RuntimeError>
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.
Sourcepub async fn validate_link_hooks(
&self,
runtime: &KhiveRuntime,
token: &NamespaceToken,
specs: &[LinkSpec],
) -> Result<(), RuntimeError>
pub async fn validate_link_hooks( &self, runtime: &KhiveRuntime, token: &NamespaceToken, specs: &[LinkSpec], ) -> Result<(), RuntimeError>
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.
Sourcepub fn has_verb(&self, verb: &str) -> bool
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.
Sourcepub fn mounted_verb_snapshot(&self) -> Vec<Value>
pub fn mounted_verb_snapshot(&self) -> Vec<Value>
Advisory metadata for synchronous planning and MCP initialization.
pub async fn mounted_verb_catalog(&self) -> Result<Vec<Value>, RuntimeError>
Sourcepub async fn apply_profile_section_feedback(
&self,
token: &NamespaceToken,
profile_id: &str,
section_signals: Value,
target_attribution: Option<String>,
) -> Result<Value, RuntimeError>
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.
Sourcepub fn all_verbs(&self) -> Vec<&'static HandlerDef>
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.
Sourcepub fn all_verbs_with_names(&self) -> Vec<(&str, &'static HandlerDef)>
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).
Sourcepub fn all_handlers_with_names(&self) -> Vec<(&str, &'static HandlerDef)>
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.
Sourcepub fn all_note_kinds(&self) -> Vec<&'static str>
pub fn all_note_kinds(&self) -> Vec<&'static str>
Merged set of note kinds across all registered packs (deduplicated, first-seen order preserved).
Sourcepub fn pack_owned_note_kinds(&self) -> Vec<&'static str>
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.
Sourcepub fn all_entity_kinds(&self) -> Vec<&'static str>
pub fn all_entity_kinds(&self) -> Vec<&'static str>
Merged set of entity kinds across all registered packs (deduplicated, first-seen order preserved).
Sourcepub fn all_brain_consumer_kinds(&self) -> Vec<&'static str>
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).
Sourcepub fn pack_names(&self) -> Vec<&str>
pub fn pack_names(&self) -> Vec<&str>
Names of packs in topological load order.
Sourcepub fn pack_host_state<T: Any + Send + Sync>(
&self,
name: &str,
) -> Option<Arc<T>>
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.
Sourcepub fn pack_requires(&self, name: &str) -> Option<&'static [&'static str]>
pub fn pack_requires(&self, name: &str) -> Option<&'static [&'static str]>
Declared dependencies for a registered pack.
Sourcepub fn pack_note_kinds(&self, name: &str) -> Option<&'static [&'static str]>
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.
Sourcepub fn pack_entity_kinds(&self, name: &str) -> Option<&'static [&'static str]>
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.
Sourcepub fn pack_verbs(&self, name: &str) -> Option<&'static [HandlerDef]>
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.
Sourcepub fn all_edge_rules(&self) -> Vec<EdgeEndpointRule>
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.
Sourcepub fn all_entity_types(&self) -> Vec<EntityTypeDef>
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.
Sourcepub fn all_note_kind_specs(&self) -> Vec<&'static NoteKindSpec>
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.
Sourcepub fn all_validation_rules(&self) -> Vec<&'static ValidationRule>
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.
Sourcepub fn all_schema_plans(&self) -> Vec<SchemaPlan>
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.
Sourcepub fn all_schema_plans_with_columns(
&self,
) -> Vec<(SchemaPlan, &'static [PackColumnAddition])>
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.
Sourcepub fn call_register_embedders(&self, runtime: &KhiveRuntime)
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.
Sourcepub fn call_register_entity_type_validators(&self, runtime: &KhiveRuntime)
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.
Sourcepub fn call_register_note_mutation_hooks(&self, runtime: &KhiveRuntime)
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.
Sourcepub fn call_register_note_write_validators(&self, runtime: &KhiveRuntime)
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.
Sourcepub async fn call_warm_all(&self)
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.
Sourcepub fn presentation_policy_for(&self, verb: &str) -> VerbPresentationPolicy
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.
Sourcepub fn verb_category(&self, verb: &str) -> Option<VerbCategory>
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.
Sourcepub fn is_retry_safe_after_frame_omission(&self, verb: &str) -> bool
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.
Sourcepub fn is_subhandler_verb(&self, verb: &str) -> bool
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.
Sourcepub fn apply_schema_plans(&self, backend: &StorageBackend)
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.
Sourcepub fn all_schema_plans_named(&self) -> Vec<(&'static str, SchemaPlan)>
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.
Sourcepub fn apply_schema_plans_with_map(
&self,
backend_for_pack: &HashMap<&str, &StorageBackend>,
default_backend: &StorageBackend,
) -> Result<(), PackSchemaCollisionError>
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§
Auto Trait Implementations§
impl !RefUnwindSafe for VerbRegistry
impl !UnwindSafe for VerbRegistry
impl Freeze for VerbRegistry
impl Send for VerbRegistry
impl Sync for VerbRegistry
impl Unpin for VerbRegistry
impl UnsafeUnpin for VerbRegistry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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