nodedb_crdt/validator/types.rs
1// SPDX-License-Identifier: BUSL-1.1
2
3//! Validator input/output types.
4
5use crate::dead_letter::CompensationHint;
6use loro::LoroValue;
7use nodedb_types::Surrogate;
8
9/// Outcome of validating a proposed change against constraints.
10#[derive(Debug)]
11pub enum ValidationOutcome {
12 /// All constraints satisfied — safe to commit.
13 Accepted,
14 /// One or more constraints violated — delta rejected.
15 Rejected(Vec<Violation>),
16}
17
18/// A single constraint violation.
19#[derive(Debug, Clone)]
20pub struct Violation {
21 /// The constraint that was violated.
22 pub constraint_name: String,
23 /// Human-readable reason.
24 pub reason: String,
25 /// Suggested fix.
26 pub hint: CompensationHint,
27}
28
29/// A proposed row change to validate.
30#[derive(Debug, Clone)]
31pub struct ProposedChange {
32 /// Target collection.
33 pub collection: String,
34 /// Row ID being inserted/updated.
35 pub row_id: String,
36 /// Stable cross-engine identity assigned at the boundary.
37 ///
38 /// `Surrogate::ZERO` is the in-test sentinel and is also accepted
39 /// for legacy callers that have not yet plumbed an assigner. UNIQUE
40 /// and FK checks key on this when non-zero, so cross-engine bitmap
41 /// joins reference the same row identity.
42 pub surrogate: Surrogate,
43 /// Field values being set.
44 ///
45 /// For bitemporal collections, the reserved columns `_ts_valid_from`
46 /// and `_ts_valid_until` appear in this vec alongside user fields;
47 /// constraint validation inspects them via
48 /// [`crate::validator::bitemporal`] helpers.
49 pub fields: Vec<(String, LoroValue)>,
50}