pub struct Host { /* private fields */ }Expand description
Registers in-process, stdio, and HTTP providers behind one handle and fans queries out across them.
Implementations§
Source§impl Host
impl Host
Sourcepub fn with_timeout(per_provider_timeout: Duration) -> Self
pub fn with_timeout(per_provider_timeout: Duration) -> Self
A host with a custom per-provider timeout.
Sourcepub fn register(&mut self, provider: Box<dyn ContextProvider>)
pub fn register(&mut self, provider: Box<dyn ContextProvider>)
Register an in-process provider (a built-in, e.g. the code graph).
Sourcepub async fn add_stdio(
&mut self,
id: impl Into<String>,
program: &str,
args: &[String],
) -> Result<(), HostError>
pub async fn add_stdio( &mut self, id: impl Into<String>, program: &str, args: &[String], ) -> Result<(), HostError>
Spawn and register a child-process provider over stdio, completing the
handshake (SPEC.md §3).
Sourcepub async fn add_http(
&mut self,
id: impl Into<String>,
url: impl Into<String>,
credential: Option<Credential>,
) -> Result<(), HostError>
pub async fn add_http( &mut self, id: impl Into<String>, url: impl Into<String>, credential: Option<Credential>, ) -> Result<(), HostError>
Connect and register a remote HTTP provider, completing the handshake.
credential is an optional bearer Credential
attached to every request; pass None for an unauthenticated provider.
A plaintext (http://) transport to a non-loopback provider is refused
before any bytes leave the host (HostError::InsecureTransport, C7),
and the credential is never logged (C8).
Sourcepub fn record_consent(&mut self, record: ConsentRecord)
pub fn record_consent(&mut self, record: ConsentRecord)
Record legacy boolean consent for a provider, unlocking an egress provider that declares no scopes for querying (§3.5).
Sourcepub fn record_receipt(&mut self, receipt: ConsentReceipt)
pub fn record_receipt(&mut self, receipt: ConsentReceipt)
Append a scope-level ConsentReceipt to the audit ledger, authorizing
one egress scope for one provider (docs/context-reuse.md §3). A
provider that declares off-machine egress scopes stays gated until every
such scope has a receipt.
Sourcepub fn consent(&self) -> &ConsentStore
pub fn consent(&self) -> &ConsentStore
The consent store (read-only), e.g. to persist decisions.
Sourcepub fn trust_key(&mut self, provider_id: impl Into<String>, key: TrustedKey)
pub fn trust_key(&mut self, provider_id: impl Into<String>, key: TrustedKey)
Trust key for provider_id’s provenance attestations
(ADR 0016).
The operator is the trust root: there is no discovery and no
trust-on-first-use, so a key is here because a person put it here, from
the same material as the provider’s own configuration. A host with a UI
shows TrustedKey::fingerprint beside the consent prompt, so “I
consent to this provider” and “I trust this key” are one decision.
A host that calls this for nobody verifies nothing and loses nothing:
every signed frame reads as
NoTrustedKey and is still
served (SPEC.md F9).
Sourcepub fn trust(&self) -> &TrustStore
pub fn trust(&self) -> &TrustStore
The trust store (read-only), e.g. to persist it beside the consent ledger or to render what an operator has trusted.
Sourcepub fn set_trust_store(&mut self, trust: TrustStore)
pub fn set_trust_store(&mut self, trust: TrustStore)
Replace the whole trust store — for a host restoring one it persisted.
Sourcepub fn provider_ids(&self) -> Vec<&str>
pub fn provider_ids(&self) -> Vec<&str>
The ids of every registered provider, in registration order.
Sourcepub fn provider(&self, id: &str) -> Option<&dyn ContextProvider>
pub fn provider(&self, id: &str) -> Option<&dyn ContextProvider>
Borrow a registered provider by id, e.g. to read its cached capabilities.
pub fn is_empty(&self) -> bool
Sourcepub async fn verify_frames(&self, held: &[FrameId]) -> VerifyOutcome
pub async fn verify_frames(&self, held: &[FrameId]) -> VerifyOutcome
Revalidate frames this host already holds, so unchanged context can be
reused without re-querying it (docs/context-reuse.md §4).
Identities are grouped by provider and each capable provider is asked
once. The rule is default-deny: a frame is retained only on an
explicit Verdict::Valid, and every other outcome — a negative
verdict, a missing digest, a provider that doesn’t support verify, an
unregistered provider, a failed request — drops the frame with a reason
(requirement V2). Reasons that
warrant a re-query tell the host which
dropped frames are worth fetching again.
This method holds no state: it neither caches frames nor tracks turn boundaries. When to re-verify is the host’s policy (§4 gives informative guidance); the protocol’s job is only to answer the question when asked. No frame body travels in either direction.
Sourcepub async fn query_provider(
&self,
id: &str,
query: &ContextQuery,
) -> Result<ContextQueryResult, HostError>
pub async fn query_provider( &self, id: &str, query: &ContextQuery, ) -> Result<ContextQueryResult, HostError>
Query a single provider by id, honoring the consent gate and the
per-provider timeout. Querying an unconsented egress provider is
HostError::ConsentRequired (legacy boolean) or
HostError::ConsentScopeRequired (an off-machine scope with no
receipt, §3), and the payload is never transmitted (§3.5).
Sourcepub async fn query_provider_attested(
&self,
id: &str,
query: &ContextQuery,
) -> Result<(ContextQueryResult, Vec<FrameAttestationOutcome>), HostError>
pub async fn query_provider_attested( &self, id: &str, query: &ContextQuery, ) -> Result<(ContextQueryResult, Vec<FrameAttestationOutcome>), HostError>
query_provider, plus what the host found when
it checked the provider’s attestations against its
TrustStore (SPEC.md §6.5,
ADR 0016).
Returns the result exactly as the provider served it and one
FrameAttestationOutcome per frame in it — including the frames no
attestation covered. No frame is ever withheld for failing the check
(SPEC.md F9): the outcomes are a fact recorded beside the evidence, not
a filter over it.
Sourcepub async fn query_all(&self, query: &ContextQuery) -> FanOut
pub async fn query_all(&self, query: &ContextQuery) -> FanOut
Fan a query out to every capability-matching provider concurrently, collecting a per-provider outcome. Each provider is consent-gated, timed out, and budget-audited independently — the crash-consistency contract means one provider’s failure never affects another (task deliverables 3 + 5).
Sourcepub async fn query_all_budgeted(
&self,
template: &ContextQuery,
global_budget: u32,
) -> FanOut
pub async fn query_all_budgeted( &self, template: &ContextQuery, global_budget: u32, ) -> FanOut
Fan a query out under a global token budget, splitting it into a
per-provider max_tokens share before building each provider’s query
(issue #15). Where query_all hands the same
max_tokens to every provider — so N honest providers can each spend the
whole budget and the honest total is N× the intended prompt budget — this
gives each capability-matching provider a slice of global_budget, so the
honest legs sum to <= global_budget.
template supplies every field of the query except max_tokens, which
is overwritten per provider with its share from
compose::budget_split — an equal split
by default, documented there as swappable for a weighted one. Only
capability-matching providers (the same filter query_all applies) count
toward the split and receive a query. Each leg is still consent-gated,
timed out, and budget-audited exactly as in query_all, so a provider
that overspends its share is dropped with a report by the existing B2
audit — the split composes with per-leg honesty rather than replacing it.
query_all stays the un-budgeted legacy path.