Skip to main content

qa_spec/spec/
form.rs

1use crate::spec::question::QuestionSpec;
2use crate::spec::validation::CrossFieldValidation;
3use crate::store::StoreOp;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7/// Presentation hints for a form.
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
9pub struct FormPresentation {
10    #[serde(default, skip_serializing_if = "Option::is_none")]
11    pub intro: Option<String>,
12    #[serde(default, skip_serializing_if = "Option::is_none")]
13    pub theme: Option<String>,
14    #[serde(default, skip_serializing_if = "Option::is_none")]
15    pub default_locale: Option<String>,
16}
17
18/// Execution policies shared by question navigation.
19#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
20pub struct ProgressPolicy {
21    #[serde(default)]
22    pub skip_answered: bool,
23    #[serde(default)]
24    pub autofill_defaults: bool,
25    #[serde(default)]
26    pub treat_default_as_answered: bool,
27}
28
29/// Secrets policy for the form.
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
31pub struct SecretsPolicy {
32    #[serde(default)]
33    pub enabled: bool,
34    #[serde(default)]
35    pub read_enabled: bool,
36    #[serde(default)]
37    pub write_enabled: bool,
38    #[serde(default, skip_serializing_if = "Vec::is_empty")]
39    pub allow: Vec<String>,
40    #[serde(default, skip_serializing_if = "Vec::is_empty")]
41    pub deny: Vec<String>,
42}
43
44/// Include reference for composing forms from a registry.
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
46pub struct IncludeSpec {
47    pub form_ref: String,
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub prefix: Option<String>,
50}
51
52/// Top-level QA form definition.
53#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
54pub struct FormSpec {
55    pub id: String,
56    pub title: String,
57    pub version: String,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub description: Option<String>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub presentation: Option<FormPresentation>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub progress_policy: Option<ProgressPolicy>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub secrets_policy: Option<SecretsPolicy>,
66    #[serde(default, skip_serializing_if = "Vec::is_empty")]
67    pub store: Vec<StoreOp>,
68    #[serde(default, skip_serializing_if = "Vec::is_empty")]
69    pub validations: Vec<CrossFieldValidation>,
70    #[serde(default, skip_serializing_if = "Vec::is_empty")]
71    pub includes: Vec<IncludeSpec>,
72    pub questions: Vec<QuestionSpec>,
73}