Expand description
Resource caps (DoS limits) shared by every adapter — the single source of
truth for fact size, recall limit, and why hop depth.
Resource caps shared by every adapter (the MCP server and the language
bindings).
These are security-relevant DoS limits. They live here — not inside any one
adapter — so every transport enforces the same numbers without a manual
“keep in sync” comment, and so a build without the mcp feature still sees
them. Each adapter formats its own transport-native error; only the values
and the clamping policy are shared.
Constants§
- DEFAULT_
WHY_ HOPS - Default hop budget for
whytraversal when the caller supplies none. - MAX_
AUTOGRAPH_ QUEUE - Bound on the background autograph queue (#1846): how many just-stored
facts may wait for their graph enrichment before new enrichments are
DROPPED (counted by
MemoryService::autograph_dropped, logged, never blocking the write path). 64 outstanding generations is already minutes of extractor work — a burst deeper than this is the extractor falling behind for good, and stallingrememberbehind it is exactly what #1846 removed. The fact itself is always stored; a dropped enrichment is rebuilt by re-remembering. - MAX_
EMBEDDABLE_ TEXT_ BYTES - Maximum accepted size of a fact that has to be embedded (2 KiB).
- MAX_
ENTITY_ RELATIONS - Maximum typed edges an
entityprofile resolves and returns PER DIRECTION (relationsandrelations_ineach) — the same width grammar asMAX_WHY_NODE_DEGREE, on the surface #1743 never covered: resolving an entity followed every non-scaffolding edge of its hub, full target content included, soentity("X")on a name mentioned by thousands of facts was a constructible multi-megabyte response (#1820). Truncation is REPORTED (relations_truncated/relations_in_truncatedon the profile), never silent: a profile with exactly this many edges is otherwise indistinguishable from a cut one. - MAX_
ENTITY_ SCAN_ EDGES - Maximum RAW edges an
entityprofile may scan per direction while looking for itsMAX_ENTITY_RELATIONStyped ones. A hub’s edges are mostly bipartite scaffolding (mentions/about, one per mentioning fact), filtered out AFTER the store hands them over — so the resolution cap alone would leave the scan O(degree), and a scan capped at the resolution cap would return scaffolding-only windows on any busy hub. Two named numbers, one per concern: this one bounds the transient scan (the #1743 cost class), the other bounds the resolved response. A typed edge sitting past this window is not found — that blindness is declared by the same truncation flags, not masked. - MAX_
FACT_ BYTES - Maximum accepted fact size (1 MiB) — prevents allocating huge embeddings.
- MAX_
FRAGMENTS - Cap on the number of fragments in one compile request — bounds the work a single call can demand across every adapter.
- MAX_
FRAGMENT_ BYTES - Maximum accepted size of a single context-compiler fragment (1 MiB, the
same ceiling as
MAX_FACT_BYTES) — prevents a single fragment from forcing huge allocations in the compile pipeline. - MAX_
INGEST_ FILES - Maximum number of
path-referenced fragments accepted in one compile request — bounds the filesystem work (and open-file churn) a single call can demand, symmetric toMAX_FRAGMENTSfor inline fragments. - MAX_
INGEST_ FILE_ BYTES - Maximum accepted size of a single file read through a
path-referenced context fragment (V2b-1 path ingestion) — 1 MiB, the same ceiling asMAX_FRAGMENT_BYTES: an ingested file becomes an ordinary fragment’scontent, so it must not exceed what a fragment is allowed to carry. Checked fromfs::metadataBEFORE the file is read, and re-checked after (fs::readcan race a concurrent write) — never clamped, always refused, so a truncated read can never silently masquerade as the whole file. - MAX_
MEDIA_ BYTES - Maximum accepted size of a fragment’s base64-encoded media payload
(US-009, PR1: inline images) — 4 MiB of base64 text, roughly 3 MiB of raw
bytes once decoded. Deliberately separate from
MAX_FRAGMENT_BYTES, which only ever measurescrate::context::model::ContextFragment::content(the caption): a screenshot is not text, and capping it at the 1 MiB text ceiling would reject ordinary screenshots outright. Measured againstbytes_b64.len()(the encoded string), so the cap can reject an oversized payload before any base64 decoding is attempted. - MAX_
METADATA_ BYTES - Maximum accepted size of caller-supplied
metadata(64 KiB), measured as its serialized JSON form. Metadata is a keyed lookup facet (project, author, status, …) — a porte-clés, not a payload — so it gets a much tighter ceiling thanMAX_FACT_BYTES: without one, a caller could smuggle an arbitrarily large JSON blob throughmetadataon every write path (remember,remember_with_ttl,remember_extracted, and each context-compiler fragment’s ownmetadata) and force the same unbounded allocation and storage growth the fact-size cap exists to prevent. - MAX_
RECALL_ LIMIT - Cap on a
recalllimit — prevents unbounded vector scans (core does not capk, so the adapters do). - MAX_
TOKEN_ BUDGET - Cap on a caller-supplied token budget. A budget cannot force allocations by itself, but an absurd value would make the savings arithmetic meaningless, so adapters clamp to this ceiling instead of erroring.
- MAX_
TOTAL_ INGEST_ BYTES - Aggregate cap on the bytes read across every
path-referenced fragment of one request (64 MiB) — symmetric toMAX_TOTAL_MEDIA_BYTES. Without it,MAX_INGEST_FILESfragments each atMAX_INGEST_FILE_BYTESwould still admit 64 MiB (the two caps happen to coincide at these values), but this cap is checked independently and first — a future change to either per-item constant must not silently loosen the aggregate ceiling. - MAX_
TOTAL_ MEDIA_ BYTES - Aggregate cap on ALL media payloads of one request (base64 length,
summed). Without it,
MAX_FRAGMENTSfragments each atMAX_MEDIA_BYTESwould let a single request carry 4 GiB of media — far past the ~1 GiB worst case the text caps allow. 64 MiB comfortably fits a real screenshot-heavy session while bounding decode work. - MAX_
TRANSCRIPT_ BYTES - Maximum accepted size of a
compile_transcripttranscript (V2b-2), inline orpath-referenced — 8 MiB. The ONE caller-facing shape allowed to read past the ordinaryMAX_INGEST_FILE_BYTES/MAX_FRAGMENT_BYTES1 MiB ceiling: a transcript is segmented into sub-1-MiB pieces immediately after being read (seecontext::segment), so it is never itself compiled as one oversized fragment — only the raw pre-segmentation read gets the wider cap. - MAX_
WHY_ EDGES - Maximum edges one
why/recall_fusedgraph walk may record. - MAX_
WHY_ HOPS - Cap on
why/recall_fusedhop depth. Bounds DEPTH only: an entity hub reached at any hop is, by construction, a super-node whose degree scales with the whole store, so this alone does not bound how much a walk returns — seeMAX_WHY_NODE_DEGREEandMAX_WHY_NODESfor the width budget (issue #1743: a hub dumped its entire neighborhood, full fact content included, into a single response). - MAX_
WHY_ NODES - Maximum number of nodes one
why/recall_fusedgraph walk may collect, seed included.MAX_WHY_NODE_DEGREEbounds any single node’s contribution; this bounds the walk’s total size across every node it expands, so many hubs each under the per-node cap still cannot together grow a response past a fixed ceiling. - MAX_
WHY_ NODE_ DEGREE - Maximum outgoing edges a
why/recall_fusedgraph walk follows from any ONE node. Without this, expanding a single entity hub pushes one edge (and, for each unseen target, a full-content node) per fact that ever mentioned it — the walk’s cost is thenO(store size)at a single hop, no matter how shallowMAX_WHY_HOPSis set.
Functions§
- clamp_
hops - Clamp a caller-supplied
whyhop budget toMAX_WHY_HOPS. - clamp_
recall_ limit - Clamp a caller-supplied recall limit to
MAX_RECALL_LIMIT. - clamp_
token_ budget - Clamp a caller-supplied token budget to
MAX_TOKEN_BUDGET. - metadata_
bytes - The serialized JSON size of
meta, in bytes. Returnsusize::MAXif the map somehow fails to serialize (it never should —Metadatais always valid JSON), so a serialization hiccup fails a size check closed rather than silently passing an unmeasured payload.