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
//! Shared document-upload wire types for the ingest pipeline.
//!
//! The document-upload handler reports per-document failures in a structured
//! `conflicts` array rather than failing the whole batch: a conflicted document
//! is silently NOT inserted into the finalized corpus version, so the conflict
//! list is the only signal an operator gets that documents were dropped.
//!
//! [`UploadConflict`] is the single source of truth for that wire shape, shared
//! by the server (which produces it) and the CLI (which must surface it). The
//! JSON representation is exactly `{ "path": ..., "reason": ... }`.
use ;
/// Marker suffix appended to carry-conflict reasons when the failure requires
/// the CLI to re-embed and re-upload the document rather than just retrying.
///
/// The server embeds this string in its conflict messages; the CLI matches
/// against it with `.contains(REEMBED_REQUIRED_MARKER)`. Anchoring both sides
/// to this constant makes the cross-crate contract compiler-checked.
pub const REEMBED_REQUIRED_MARKER: &str = "re-embed required";
/// One per-document conflict surfaced by the document-upload handler.
///
/// A document carrying a conflict was NOT inserted into the corpus version
/// (e.g. a duplicate path within the upload batch, or a store-level insert
/// failure). Callers that ignore conflicts silently lose documents.
///
/// When the document was rejected by ingest-time prompt-injection scanning
/// (issue #103), `reason` is the stable marker [`PROMPT_INJECTION_REASON`] and
/// the optional `final_score` / `reject_threshold` / `pattern` / `model` fields
/// carry the full scan breakdown. For every other (non-injection) conflict those
/// fields are `None` and are omitted from the wire JSON, leaving the historical
/// `{ "path", "reason" }` shape untouched.
/// Stable `reason` value for documents rejected by prompt-injection scanning.
pub const PROMPT_INJECTION_REASON: &str = "prompt_injection";
/// Stable `reason` PREFIX for documents dropped because injection scanning could
/// not complete.
///
/// Used when the model leg was unreachable under [fail-closed] mode. The server
/// may append a parenthetical detail (e.g. `" (fail-closed)"`), so match with
/// `starts_with`, not equality.
///
/// [fail-closed]: crate::injection::FailMode::Closed
pub const PROMPT_INJECTION_UNAVAILABLE_REASON: &str = "prompt_injection_scan_unavailable";