1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! 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.
use crateMetadata;
/// Default hop budget for `why` traversal when the caller supplies none.
pub const DEFAULT_WHY_HOPS: usize = 2;
/// Maximum accepted fact size (1 MiB) — prevents allocating huge embeddings.
pub const MAX_FACT_BYTES: usize = 1_048_576;
/// 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 than [`MAX_FACT_BYTES`]: without one, a caller could smuggle
/// an arbitrarily large JSON blob through `metadata` on every write path
/// (`remember`, `remember_with_ttl`, `remember_extracted`, and each
/// context-compiler fragment's own `metadata`) and force the same unbounded
/// allocation and storage growth the fact-size cap exists to prevent.
pub const MAX_METADATA_BYTES: usize = 64 * 1024;
/// The serialized JSON size of `meta`, in bytes. Returns `usize::MAX` if the
/// map somehow fails to serialize (it never should — `Metadata` is always
/// valid JSON), so a serialization hiccup fails a size check closed rather
/// than silently passing an unmeasured payload.
/// Cap on a `recall` limit — prevents unbounded vector scans (core does not
/// cap `k`, so the adapters do).
pub const MAX_RECALL_LIMIT: usize = 1_000;
/// Cap on `why` hop depth — prevents exponential graph fan-out.
pub const MAX_WHY_HOPS: usize = 10;
/// 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.
pub const MAX_FRAGMENT_BYTES: usize = 1_048_576;
/// Cap on the number of fragments in one compile request — bounds the work a
/// single call can demand across every adapter.
pub const MAX_FRAGMENTS: usize = 1_024;
/// 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 measures [`crate::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 against
/// `bytes_b64.len()` (the encoded string), so the cap can reject an
/// oversized payload before any base64 decoding is attempted.
pub const MAX_MEDIA_BYTES: usize = 4 * 1024 * 1024;
/// Aggregate cap on ALL media payloads of one request (base64 length,
/// summed). Without it, `MAX_FRAGMENTS` fragments each at [`MAX_MEDIA_BYTES`]
/// would 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.
pub const MAX_TOTAL_MEDIA_BYTES: usize = 64 * 1024 * 1024;
/// Maximum accepted size of a single file read through a `path`-referenced
/// context fragment (V2b-1 path ingestion) — 1 MiB, the same ceiling as
/// [`MAX_FRAGMENT_BYTES`]: an ingested file becomes an ordinary fragment's
/// `content`, so it must not exceed what a fragment is allowed to carry.
/// Checked from `fs::metadata` BEFORE the file is read, and re-checked after
/// (`fs::read` can race a concurrent write) — never clamped, always refused,
/// so a truncated read can never silently masquerade as the whole file.
pub const MAX_INGEST_FILE_BYTES: usize = 1_048_576;
/// 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 to [`MAX_FRAGMENTS`] for inline fragments.
pub const MAX_INGEST_FILES: usize = 64;
/// Aggregate cap on the bytes read across every `path`-referenced fragment of
/// one request (64 MiB) — symmetric to [`MAX_TOTAL_MEDIA_BYTES`]. Without it,
/// [`MAX_INGEST_FILES`] fragments each at [`MAX_INGEST_FILE_BYTES`] would
/// 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.
pub const MAX_TOTAL_INGEST_BYTES: usize = 64 * 1024 * 1024;
/// Maximum accepted size of a `compile_transcript` transcript (V2b-2), inline
/// or `path`-referenced — 8 MiB. The ONE caller-facing shape allowed to read
/// past the ordinary [`MAX_INGEST_FILE_BYTES`]/[`MAX_FRAGMENT_BYTES`] 1 MiB
/// ceiling: a transcript is segmented into sub-1-MiB pieces immediately after
/// being read (see `context::segment`), so it is never itself compiled as one
/// oversized fragment — only the raw pre-segmentation read gets the wider cap.
pub const MAX_TRANSCRIPT_BYTES: usize = 8 * 1024 * 1024;
/// 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.
pub const MAX_TOKEN_BUDGET: u64 = 10_000_000;
/// Clamp a caller-supplied token budget to [`MAX_TOKEN_BUDGET`].
/// Clamp a caller-supplied recall limit to [`MAX_RECALL_LIMIT`].
/// Clamp a caller-supplied `why` hop budget to [`MAX_WHY_HOPS`].