Skip to main content

contextgraph_host/
lib.rs

1//! `contextgraph-host` — the Context Graph Protocol host runtime.
2//!
3//! A Context Graph Protocol **host** is the side of the protocol that asks for context: it
4//! discovers providers, negotiates capabilities, routes a
5//! [`ContextQuery`](contextgraph_types::ContextQuery) to the ones that can answer,
6//! budgets and cites what comes back, and gates what may leave the machine.
7//! This crate is that host runtime: today it is exercised by the Context Graph Protocol
8//! conformance suite and drives the `contextgraph-inspect` tool, and it is usable by
9//! any Rust agent that wants Context Graph Protocol support (`SPEC.md` §1). Note that
10//! the in-tree context providers do **not** yet route through this host —
11//! they share `contextgraph-types` values via in-process calls — so this is the host
12//! runtime and conformance harness for the protocol, not (yet) the path every
13//! built-in source is served through.
14//! `SPEC.md` is the normative
15//! specification; every module cites the section it implements.
16//!
17//! # Shape
18//!
19//! - [`Envelope`] + [`wire`] — the versioned NDJSON message envelope and its
20//!   framing (SPEC.md §2). Version mismatch is a named error, never a hang.
21//! - [`ContextProvider`] — the one trait every source implements, whether
22//!   in-process, a stdio child, or a remote HTTP endpoint (SPEC.md §3, SPEC.md §5).
23//! - [`StdioProvider`] / [`RawStdioConnection`] — child-process transport
24//!   with scrubbed-environment isolation and process-group teardown.
25//!   `StdioProvider` demultiplexes correlated replies on their `id` via a
26//!   dedicated reader task, so a provider that negotiated `correlation` can have
27//!   concurrent queries in flight over one connection while a non-correlating
28//!   provider stays lock-step (ADR 0002).
29//! - [`HttpProvider`] — remote streamable-HTTP transport (SPEC.md §3).
30//! - [`ConsentStore`] — the gate that keeps an egress provider un-queried
31//!   until the user consents, naming what leaves (SPEC.md §4).
32//! - [`ingest`] — the ingestion-side dual of [`compose`]: turns a user's paste
33//!   into a local, egress-free provider serving content-addressed frames, so the
34//!   prompt's biggest un-disciplined input is budgeted and cited like any other
35//!   ([ADR 0006](https://github.com/macanderson/context-graph-protocol/blob/main/docs/adr/0006-prompt-ingestion-as-a-local-provider.md)).
36//! - [`Host`] — registers all three provider kinds behind one handle and
37//!   [`Host::query_all`] fans a query out concurrently, enforcing timeouts,
38//!   consent, and budget honesty (SPEC.md §4 and §7).
39//! - [`trust`] — the keys a host trusts for provenance attestation, and the
40//!   verifier that consumes them (SPEC.md §6.5). The operator is the trust
41//!   root: nothing is discovered and nothing is trusted on first use. An
42//!   attestation the host cannot check degrades its frame to *unattested* and
43//!   never removes it (F9).
44//! - [`verify`] — the *bytes* half of F5: re-reads the local source a `file`
45//!   provenance addresses and checks its declared digest against the actual
46//!   bytes (SPEC.md §6.2). A host API, not an automatic re-read of any provider
47//!   `uri`; the end-to-end harness that calls it is issue #14.
48//!
49//! # Isolation invariants (`SPEC.md` §4 and §10)
50//!
51//! What is enforced today: a stdio child is spawned with a **scrubbed
52//! environment** (`env_clear` plus a `PATH`/`HOME` allowlist), so it inherits
53//! no credentials or secrets the host holds via environment variables; each
54//! call is bounded by a timeout, and on Unix the child leads its own process
55//! group so a crash or hang is contained and reaped without touching its
56//! siblings. An `egress` provider is never auto-enabled. Frame content is
57//! untrusted data; this crate only ever *transports* it — it never executes
58//! frame content, and a host composing frames into a prompt must delimit them
59//! as quoted material.
60//!
61//! **Not yet enforced — filesystem confinement.** A child runs with the
62//! host's working directory and ordinary filesystem access; there is no cwd
63//! jail, chroot, mount namespace, or seccomp sandbox. Environment scrubbing
64//! blocks credentials passed *via env vars*, but a provider can still read
65//! files the host user can read. Treat a stdio provider as trusted code you
66//! chose to run, not as a sandboxed principal — real filesystem isolation is
67//! future work.
68
69pub mod compose;
70pub mod consent;
71pub mod error;
72pub mod host;
73pub mod http;
74pub mod ingest;
75pub mod provider;
76pub mod stdio;
77pub mod trust;
78pub mod verify;
79pub mod wire;
80
81pub use compose::ranking::{
82    PerProviderQuota, RankingStrategy, RoundRobinByRank, ScoreDescending, is_ranking_permutation,
83    rank_with,
84};
85pub use compose::{
86    AuditEntry, Citation, ComposedPrompt, CompositionAudit, DedupDrop, Deduped, ExclusionReason,
87    FrameDisposition, VerificationState, budget_split, compose_context, compose_for_prompt,
88    compose_for_prompt_attested, compose_for_prompt_with, dedup_cross_provider, fold_to_edges,
89    order_by, order_by_value, rendered_token_cost,
90};
91pub use consent::{ConsentDecision, ConsentRecord, ConsentStore};
92/// The one `FrameAttestation` (`SPEC.md` §6.5.5). It is defined in
93/// `contextgraph-types` because it is a **wire** type that rides
94/// [`ContextQueryResult`](contextgraph_types::ContextQueryResult), and it is
95/// re-exported here so a host author has one import rather than two. This crate
96/// briefly defined two more of its own; see #161.
97pub use contextgraph_types::FrameAttestation;
98pub use error::HostError;
99pub use host::{
100    DropReason, DroppedFrame, FanOut, Host, ProviderOutcome, ProviderResult, VerifyOutcome,
101};
102pub use http::{Credential, HttpProvider, refuse_insecure_transport};
103pub use ingest::{
104    IngestBundle, IngestConfig, IngestProvider, PasteIngest, SegmentKind, SegmentOutcome,
105    SegmentReport, ingest_paste,
106};
107pub use provider::{ContextProvider, capability_matches, frame_kind_name};
108pub use stdio::{RawStdioConnection, StdioProvider};
109pub use trust::{
110    AttestationLedger, AttestationState, FrameAttestationOutcome, TrustStore, TrustedKey,
111};
112pub use verify::{DigestVerification, verify_file_provenance, verify_provenance_digest};
113pub use wire::{
114    AttesterKey, Envelope, decode_line, encode_line, envelope_kind, versions_compatible,
115};
116
117/// The Context Graph Protocol version this host speaks, re-exported from `contextgraph-types`
118/// (`SPEC.md`).
119pub use contextgraph_types::PROTOCOL_VERSION;