Skip to main content

qa_spec/
answers.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3use serde_cbor::{to_vec, value::to_value};
4use serde_json::Value;
5
6/// Optional metadata paired with an `AnswerSet`.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
8pub struct Meta {
9    #[serde(default, skip_serializing_if = "Option::is_none")]
10    pub created_at: Option<String>,
11    #[serde(default, skip_serializing_if = "Option::is_none")]
12    pub updated_at: Option<String>,
13}
14
15/// Represents in-progress answers for a given form spec version.
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
17pub struct AnswerSet {
18    pub form_id: String,
19    pub spec_version: String,
20    pub answers: Value,
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub meta: Option<Meta>,
23}
24
25impl AnswerSet {
26    /// Creates a fresh empty answer set for a form.
27    pub fn new(form_id: impl Into<String>, spec_version: impl Into<String>) -> Self {
28        Self {
29            form_id: form_id.into(),
30            spec_version: spec_version.into(),
31            answers: Value::Object(Default::default()),
32            meta: None,
33        }
34    }
35
36    /// Serializes the answers set as canonical CBOR bytes.
37    pub fn to_cbor(&self) -> Result<Vec<u8>, serde_cbor::Error> {
38        let canonical = to_value(self)?;
39        to_vec(&canonical)
40    }
41
42    /// Serializes the answers set as indented JSON for debugging.
43    pub fn to_json_pretty(&self) -> Result<String, serde_json::Error> {
44        serde_json::to_string_pretty(self)
45    }
46}
47
48/// Progress tracking state for flows.
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
50pub struct ProgressState {
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub current_step: Option<String>,
53    pub completed: bool,
54    #[serde(default, skip_serializing_if = "Vec::is_empty")]
55    pub history: Vec<String>,
56}
57
58/// Validation error metadata reported by the engine.
59#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
60pub struct ValidationError {
61    #[serde(default, skip_serializing_if = "Option::is_none")]
62    pub question_id: Option<String>,
63    #[serde(default, skip_serializing_if = "Option::is_none")]
64    pub path: Option<String>,
65    pub message: String,
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub code: Option<String>,
68}
69
70/// Result returned from `validate_answers`.
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
72pub struct ValidationResult {
73    pub valid: bool,
74    #[serde(default, skip_serializing_if = "Vec::is_empty")]
75    pub errors: Vec<ValidationError>,
76    #[serde(default, skip_serializing_if = "Vec::is_empty")]
77    pub missing_required: Vec<String>,
78    #[serde(default, skip_serializing_if = "Vec::is_empty")]
79    pub unknown_fields: Vec<String>,
80}