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//! - [`verify`] — the *bytes* half of F5: re-reads the local source a `file`
40//! provenance addresses and checks its declared digest against the actual
41//! bytes (SPEC.md §6.2). A host API, not an automatic re-read of any provider
42//! `uri`; the end-to-end harness that calls it is issue #14.
43//!
44//! # Isolation invariants (`SPEC.md` §4 and §10)
45//!
46//! What is enforced today: a stdio child is spawned with a **scrubbed
47//! environment** (`env_clear` plus a `PATH`/`HOME` allowlist), so it inherits
48//! no credentials or secrets the host holds via environment variables; each
49//! call is bounded by a timeout, and on Unix the child leads its own process
50//! group so a crash or hang is contained and reaped without touching its
51//! siblings. An `egress` provider is never auto-enabled. Frame content is
52//! untrusted data; this crate only ever *transports* it — it never executes
53//! frame content, and a host composing frames into a prompt must delimit them
54//! as quoted material.
55//!
56//! **Not yet enforced — filesystem confinement.** A child runs with the
57//! host's working directory and ordinary filesystem access; there is no cwd
58//! jail, chroot, mount namespace, or seccomp sandbox. Environment scrubbing
59//! blocks credentials passed *via env vars*, but a provider can still read
60//! files the host user can read. Treat a stdio provider as trusted code you
61//! chose to run, not as a sandboxed principal — real filesystem isolation is
62//! future work.
63
64pub mod compose;
65pub mod consent;
66pub mod error;
67pub mod host;
68pub mod http;
69pub mod ingest;
70pub mod provider;
71pub mod stdio;
72pub mod verify;
73pub mod wire;
74
75pub use compose::{
76 AuditEntry, Citation, ComposedPrompt, CompositionAudit, DedupDrop, Deduped, ExclusionReason,
77 FrameDisposition, VerificationState, budget_split, compose_context, compose_for_prompt,
78 dedup_cross_provider, order_by_value,
79};
80pub use consent::{ConsentDecision, ConsentRecord, ConsentStore};
81pub use error::HostError;
82pub use host::{
83 DropReason, DroppedFrame, FanOut, Host, ProviderOutcome, ProviderResult, VerifyOutcome,
84};
85pub use http::{Credential, HttpProvider, refuse_insecure_transport};
86pub use ingest::{
87 IngestBundle, IngestConfig, IngestProvider, PasteIngest, SegmentKind, SegmentOutcome,
88 SegmentReport, ingest_paste,
89};
90pub use provider::{ContextProvider, capability_matches, frame_kind_name};
91pub use stdio::{RawStdioConnection, StdioProvider};
92pub use verify::{DigestVerification, verify_file_provenance, verify_provenance_digest};
93pub use wire::{Envelope, decode_line, encode_line, envelope_kind, versions_compatible};
94
95/// The Context Graph Protocol version this host speaks, re-exported from `contextgraph-types`
96/// (`SPEC.md`).
97pub use contextgraph_types::PROTOCOL_VERSION;