Skip to main content

nxd_core/domain/contract/
config.rs

1use super::{ArtifactSet, Resource, SecretBinding};
2use crate::domain::host_lifecycle::LifecycleIntent;
3use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
7#[serde(rename_all = "camelCase", deny_unknown_fields)]
8pub struct CanonicalConfig {
9	pub api_version: String,
10	pub kind: CanonicalKind,
11	pub metadata: ConfigMetadata,
12	pub spec: ConfigSpec,
13}
14
15#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
16#[serde(deny_unknown_fields)]
17pub struct ConfigMetadata {
18	pub name: String,
19}
20
21#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
22#[serde(rename_all = "camelCase", deny_unknown_fields)]
23pub struct ConfigSpec {
24	#[serde(default)]
25	pub provider_instances: Vec<ProviderInstance>,
26	#[serde(default)]
27	pub resources: Vec<Resource>,
28	#[serde(default)]
29	pub secret_bindings: Vec<SecretBinding>,
30	/// Pinned secret resolver/sink executables. Not infrastructure providers:
31	/// they receive only bindings and approved action identity.
32	#[serde(default)]
33	pub secret_resolvers: Vec<SecretResolverInstance>,
34	#[serde(default)]
35	pub artifact_sets: Vec<ArtifactSet>,
36	#[serde(default)]
37	pub operation_sets: BTreeMap<String, OperationSet>,
38}
39
40#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
41#[serde(rename_all = "camelCase", deny_unknown_fields)]
42pub struct OperationSet {
43	pub selectors: Vec<String>,
44	#[serde(default, skip_serializing_if = "Option::is_none")]
45	pub lifecycle_intent: Option<LifecycleIntent>,
46	#[serde(default, skip_serializing_if = "Option::is_none")]
47	pub artifact_set: Option<String>,
48}
49
50#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
51pub enum CanonicalKind {
52	CanonicalConfig,
53}
54
55#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
56#[serde(rename_all = "camelCase", deny_unknown_fields)]
57pub struct ProviderInstance {
58	pub id: String,
59	pub kind: String,
60	#[serde(default)]
61	pub depends_on: Vec<String>,
62	/// Absolute immutable path to the provider executable.
63	///
64	/// Required for external-protocol providers. When present, `protocol` must
65	/// also be present and composition verifies the executable exists.
66	#[serde(default, skip_serializing_if = "Option::is_none")]
67	pub command: Option<String>,
68	/// Protocol identity such as `nxd.plugin.v1`.
69	#[serde(default, skip_serializing_if = "Option::is_none")]
70	pub protocol: Option<String>,
71	/// Non-secret fixed arguments passed to the provider executable.
72	#[serde(default, skip_serializing_if = "Vec::is_empty")]
73	pub arguments: Vec<String>,
74	/// Binding IDs resolved only for this provider's supervised session.
75	#[serde(default, skip_serializing_if = "Vec::is_empty")]
76	pub secret_bindings: Vec<String>,
77	#[serde(default)]
78	pub config: BTreeMap<String, serde_json::Value>,
79}
80
81/// Pinned secret resolver/sink executable declared in canonical configuration.
82#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
83#[serde(rename_all = "camelCase", deny_unknown_fields)]
84pub struct SecretResolverInstance {
85	/// Matches [`super::SecretBinding::resolver`].
86	pub id: String,
87	/// Absolute immutable path to the secret executable.
88	pub command: String,
89	/// Protocol identity such as `nxd.secret.v1`.
90	pub protocol: String,
91	/// Non-secret fixed arguments (for example `--secrets-root` store path).
92	#[serde(default, skip_serializing_if = "Vec::is_empty")]
93	pub arguments: Vec<String>,
94	#[serde(default)]
95	pub config: BTreeMap<String, serde_json::Value>,
96}
97
98/// Supported provider protocol identifiers in canonical configuration.
99pub const PROVIDER_PROTOCOL_V1: &str = "nxd.plugin.v1";
100/// Supported secret resolver protocol identifier in canonical configuration.
101pub const SECRET_PROTOCOL_V1: &str = "nxd.secret.v1";