//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `policy/evaluate`. Version: `0.1`.
#[allow(unused_imports)]
use serde::{Deserialize, Serialize};
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
///Discriminator: is this consumer a user-driven Companion or a headless Service?
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ConsumerKind",
/// "description": "Discriminator: is this consumer a user-driven Companion or a headless Service?",
/// "oneOf": [
/// {
/// "title": "Companion",
/// "type": "object",
/// "required": [
/// "formFactor",
/// "kind"
/// ],
/// "properties": {
/// "formFactor": {
/// "type": "string",
/// "enum": [
/// "browser",
/// "mobile",
/// "desktop"
/// ]
/// },
/// "kind": {
/// "const": "companion"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Service",
/// "type": "object",
/// "required": [
/// "kind",
/// "serviceKind"
/// ],
/// "properties": {
/// "kind": {
/// "const": "service"
/// },
/// "serviceKind": {
/// "type": "string",
/// "enum": [
/// "mediator",
/// "ai-agent",
/// "daemon"
/// ]
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", deny_unknown_fields)]
pub enum ConsumerKind {
///Companion
#[serde(rename = "companion")]
Companion {
#[serde(rename = "formFactor")]
form_factor: ConsumerKindFormFactor,
},
///Service
#[serde(rename = "service")]
Service {
#[serde(rename = "serviceKind")]
service_kind: ConsumerKindServiceKind,
},
}
impl ::std::convert::From<&Self> for ConsumerKind {
fn from(value: &ConsumerKind) -> Self {
value.clone()
}
}
///`ConsumerKindFormFactor`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "browser",
/// "mobile",
/// "desktop"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ConsumerKindFormFactor {
#[serde(rename = "browser")]
Browser,
#[serde(rename = "mobile")]
Mobile,
#[serde(rename = "desktop")]
Desktop,
}
impl ::std::convert::From<&Self> for ConsumerKindFormFactor {
fn from(value: &ConsumerKindFormFactor) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for ConsumerKindFormFactor {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Browser => f.write_str("browser"),
Self::Mobile => f.write_str("mobile"),
Self::Desktop => f.write_str("desktop"),
}
}
}
impl ::std::str::FromStr for ConsumerKindFormFactor {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"browser" => Ok(Self::Browser),
"mobile" => Ok(Self::Mobile),
"desktop" => Ok(Self::Desktop),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ConsumerKindFormFactor {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ConsumerKindFormFactor {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ConsumerKindFormFactor {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`ConsumerKindServiceKind`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "mediator",
/// "ai-agent",
/// "daemon"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ConsumerKindServiceKind {
#[serde(rename = "mediator")]
Mediator,
#[serde(rename = "ai-agent")]
AiAgent,
#[serde(rename = "daemon")]
Daemon,
}
impl ::std::convert::From<&Self> for ConsumerKindServiceKind {
fn from(value: &ConsumerKindServiceKind) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for ConsumerKindServiceKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Mediator => f.write_str("mediator"),
Self::AiAgent => f.write_str("ai-agent"),
Self::Daemon => f.write_str("daemon"),
}
}
}
impl ::std::str::FromStr for ConsumerKindServiceKind {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"mediator" => Ok(Self::Mediator),
"ai-agent" => Ok(Self::AiAgent),
"daemon" => Ok(Self::Daemon),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ConsumerKindServiceKind {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ConsumerKindServiceKind {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ConsumerKindServiceKind {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Ext",
/// "description": "Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.",
/// "type": "object",
/// "minProperties": 1,
/// "additionalProperties": true,
/// "propertyNames": {
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
/// }
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Ext(pub ::std::collections::HashMap<ExtKey, ::serde_json::Value>);
impl ::std::ops::Deref for Ext {
type Target = ::std::collections::HashMap<ExtKey, ::serde_json::Value>;
fn deref(&self) -> &::std::collections::HashMap<ExtKey, ::serde_json::Value> {
&self.0
}
}
impl ::std::convert::From<Ext> for ::std::collections::HashMap<ExtKey, ::serde_json::Value> {
fn from(value: Ext) -> Self {
value.0
}
}
impl ::std::convert::From<&Ext> for Ext {
fn from(value: &Ext) -> Self {
value.clone()
}
}
impl ::std::convert::From<::std::collections::HashMap<ExtKey, ::serde_json::Value>> for Ext {
fn from(value: ::std::collections::HashMap<ExtKey, ::serde_json::Value>) -> Self {
Self(value)
}
}
///`ExtKey`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ExtKey(::std::string::String);
impl ::std::ops::Deref for ExtKey {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ExtKey> for ::std::string::String {
fn from(value: ExtKey) -> Self {
value.0
}
}
impl ::std::convert::From<&ExtKey> for ExtKey {
fn from(value: &ExtKey) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for ExtKey {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ExtKey {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for ExtKey {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Dry-run a policy decision against a synthetic PolicyInput. Returns the policy decision plus a trace of which policy modules matched and which rules fired. Used by the policy-editor UI to verify changes before save and by admins to diagnose unexpected deny/allow outcomes.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/policy/evaluate/0.1",
/// "title": "Payload",
/// "description": "Dry-run a policy decision against a synthetic PolicyInput. Returns the policy decision plus a trace of which policy modules matched and which rules fired. Used by the policy-editor UI to verify changes before save and by admins to diagnose unexpected deny/allow outcomes.",
/// "type": "object",
/// "required": [
/// "input"
/// ],
/// "properties": {
/// "candidateModule": {
/// "description": "Optional — when supplied, evaluate as if this Rego source were active (e.g. preview a pending upsert). The candidate is layered into the evaluator at the priority specified by `candidatePriority` (default 1000) for this call only.",
/// "type": "string"
/// },
/// "candidatePriority": {
/// "default": 1000,
/// "type": "integer",
/// "maximum": 1000.0,
/// "minimum": 0.0
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "includeTrace": {
/// "default": false,
/// "type": "boolean"
/// },
/// "input": {
/// "$ref": "#/definitions/PolicyInput"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Payload {
///Optional — when supplied, evaluate as if this Rego source were active (e.g. preview a pending upsert). The candidate is layered into the evaluator at the priority specified by `candidatePriority` (default 1000) for this call only.
#[serde(
rename = "candidateModule",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub candidate_module: ::std::option::Option<::std::string::String>,
#[serde(
rename = "candidatePriority",
default = "defaults::default_u64::<i64, 1000>"
)]
pub candidate_priority: i64,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
#[serde(rename = "includeTrace", default)]
pub include_trace: bool,
pub input: PolicyInput,
}
impl ::std::convert::From<&Payload> for Payload {
fn from(value: &Payload) -> Self {
value.clone()
}
}
///`PolicyDecision`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PolicyDecision",
/// "type": "object",
/// "required": [
/// "decision"
/// ],
/// "properties": {
/// "decision": {
/// "type": "string",
/// "enum": [
/// "allow",
/// "deny",
/// "require_step_up"
/// ]
/// },
/// "explanation": {
/// "description": "Human-readable explanation for diagnostic display.",
/// "type": "string"
/// },
/// "mode": {
/// "description": "When decision == \"allow\", whether the maintainer should proxy-login or release-for-fill. Default: proxy.",
/// "type": "string",
/// "enum": [
/// "proxy",
/// "fill"
/// ]
/// },
/// "stepUp": {
/// "description": "When decision == \"require_step_up\", which method to demand.",
/// "type": "object",
/// "required": [
/// "method"
/// ],
/// "properties": {
/// "method": {
/// "type": "string",
/// "enum": [
/// "webauthn-uv",
/// "push-approval",
/// "totp"
/// ]
/// },
/// "ttlSeconds": {
/// "type": "integer",
/// "minimum": 1.0
/// }
/// },
/// "additionalProperties": false
/// },
/// "ttlSecondsCap": {
/// "description": "When decision == \"allow\", maximum lifetime of the issued session blob / released secret.",
/// "type": "integer",
/// "maximum": 86400.0,
/// "minimum": 1.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PolicyDecision {
pub decision: PolicyDecisionDecision,
///Human-readable explanation for diagnostic display.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub explanation: ::std::option::Option<::std::string::String>,
///When decision == "allow", whether the maintainer should proxy-login or release-for-fill. Default: proxy.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub mode: ::std::option::Option<PolicyDecisionMode>,
#[serde(
rename = "stepUp",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub step_up: ::std::option::Option<PolicyDecisionStepUp>,
///When decision == "allow", maximum lifetime of the issued session blob / released secret.
#[serde(
rename = "ttlSecondsCap",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub ttl_seconds_cap: ::std::option::Option<::std::num::NonZeroU64>,
}
impl ::std::convert::From<&PolicyDecision> for PolicyDecision {
fn from(value: &PolicyDecision) -> Self {
value.clone()
}
}
///`PolicyDecisionDecision`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "allow",
/// "deny",
/// "require_step_up"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyDecisionDecision {
#[serde(rename = "allow")]
Allow,
#[serde(rename = "deny")]
Deny,
#[serde(rename = "require_step_up")]
RequireStepUp,
}
impl ::std::convert::From<&Self> for PolicyDecisionDecision {
fn from(value: &PolicyDecisionDecision) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for PolicyDecisionDecision {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Allow => f.write_str("allow"),
Self::Deny => f.write_str("deny"),
Self::RequireStepUp => f.write_str("require_step_up"),
}
}
}
impl ::std::str::FromStr for PolicyDecisionDecision {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"allow" => Ok(Self::Allow),
"deny" => Ok(Self::Deny),
"require_step_up" => Ok(Self::RequireStepUp),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyDecisionDecision {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyDecisionDecision {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyDecisionDecision {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///When decision == "allow", whether the maintainer should proxy-login or release-for-fill. Default: proxy.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "When decision == \"allow\", whether the maintainer should proxy-login or release-for-fill. Default: proxy.",
/// "type": "string",
/// "enum": [
/// "proxy",
/// "fill"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyDecisionMode {
#[serde(rename = "proxy")]
Proxy,
#[serde(rename = "fill")]
Fill,
}
impl ::std::convert::From<&Self> for PolicyDecisionMode {
fn from(value: &PolicyDecisionMode) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for PolicyDecisionMode {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Proxy => f.write_str("proxy"),
Self::Fill => f.write_str("fill"),
}
}
}
impl ::std::str::FromStr for PolicyDecisionMode {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"proxy" => Ok(Self::Proxy),
"fill" => Ok(Self::Fill),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyDecisionMode {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyDecisionMode {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyDecisionMode {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///When decision == "require_step_up", which method to demand.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "When decision == \"require_step_up\", which method to demand.",
/// "type": "object",
/// "required": [
/// "method"
/// ],
/// "properties": {
/// "method": {
/// "type": "string",
/// "enum": [
/// "webauthn-uv",
/// "push-approval",
/// "totp"
/// ]
/// },
/// "ttlSeconds": {
/// "type": "integer",
/// "minimum": 1.0
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PolicyDecisionStepUp {
pub method: PolicyDecisionStepUpMethod,
#[serde(
rename = "ttlSeconds",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub ttl_seconds: ::std::option::Option<::std::num::NonZeroU64>,
}
impl ::std::convert::From<&PolicyDecisionStepUp> for PolicyDecisionStepUp {
fn from(value: &PolicyDecisionStepUp) -> Self {
value.clone()
}
}
///`PolicyDecisionStepUpMethod`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "webauthn-uv",
/// "push-approval",
/// "totp"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyDecisionStepUpMethod {
#[serde(rename = "webauthn-uv")]
WebauthnUv,
#[serde(rename = "push-approval")]
PushApproval,
#[serde(rename = "totp")]
Totp,
}
impl ::std::convert::From<&Self> for PolicyDecisionStepUpMethod {
fn from(value: &PolicyDecisionStepUpMethod) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for PolicyDecisionStepUpMethod {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::WebauthnUv => f.write_str("webauthn-uv"),
Self::PushApproval => f.write_str("push-approval"),
Self::Totp => f.write_str("totp"),
}
}
}
impl ::std::str::FromStr for PolicyDecisionStepUpMethod {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"webauthn-uv" => Ok(Self::WebauthnUv),
"push-approval" => Ok(Self::PushApproval),
"totp" => Ok(Self::Totp),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyDecisionStepUpMethod {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyDecisionStepUpMethod {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyDecisionStepUpMethod {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The structured input fed to a policy evaluator on every vault/proxy-login, vault/release, and policy/evaluate call.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PolicyInput",
/// "description": "The structured input fed to a policy evaluator on every vault/proxy-login, vault/release, and policy/evaluate call.",
/// "type": "object",
/// "required": [
/// "consumer",
/// "contextId",
/// "request",
/// "site"
/// ],
/// "properties": {
/// "consumer": {
/// "type": "object",
/// "required": [
/// "did"
/// ],
/// "properties": {
/// "deviceId": {
/// "type": "string"
/// },
/// "did": {
/// "type": "string"
/// },
/// "kind": {
/// "$ref": "#/definitions/ConsumerKind"
/// },
/// "lastUserVerificationAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "networkClass": {
/// "type": "string",
/// "enum": [
/// "unknown",
/// "home",
/// "corp",
/// "public",
/// "vpn"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "contextId": {
/// "type": "string",
/// "minLength": 1
/// },
/// "request": {
/// "type": "object",
/// "required": [
/// "kind"
/// ],
/// "properties": {
/// "kind": {
/// "type": "string",
/// "enum": [
/// "proxy_login",
/// "release",
/// "step_up_response"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "site": {
/// "$ref": "#/definitions/SiteTarget"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PolicyInput {
pub consumer: PolicyInputConsumer,
#[serde(rename = "contextId")]
pub context_id: PolicyInputContextId,
pub request: PolicyInputRequest,
pub site: SiteTarget,
}
impl ::std::convert::From<&PolicyInput> for PolicyInput {
fn from(value: &PolicyInput) -> Self {
value.clone()
}
}
///`PolicyInputConsumer`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "did"
/// ],
/// "properties": {
/// "deviceId": {
/// "type": "string"
/// },
/// "did": {
/// "type": "string"
/// },
/// "kind": {
/// "$ref": "#/definitions/ConsumerKind"
/// },
/// "lastUserVerificationAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "networkClass": {
/// "type": "string",
/// "enum": [
/// "unknown",
/// "home",
/// "corp",
/// "public",
/// "vpn"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PolicyInputConsumer {
#[serde(
rename = "deviceId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub device_id: ::std::option::Option<::std::string::String>,
pub did: ::std::string::String,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub kind: ::std::option::Option<ConsumerKind>,
#[serde(
rename = "lastUserVerificationAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub last_user_verification_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
#[serde(
rename = "networkClass",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub network_class: ::std::option::Option<PolicyInputConsumerNetworkClass>,
}
impl ::std::convert::From<&PolicyInputConsumer> for PolicyInputConsumer {
fn from(value: &PolicyInputConsumer) -> Self {
value.clone()
}
}
///`PolicyInputConsumerNetworkClass`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "unknown",
/// "home",
/// "corp",
/// "public",
/// "vpn"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyInputConsumerNetworkClass {
#[serde(rename = "unknown")]
Unknown,
#[serde(rename = "home")]
Home,
#[serde(rename = "corp")]
Corp,
#[serde(rename = "public")]
Public,
#[serde(rename = "vpn")]
Vpn,
}
impl ::std::convert::From<&Self> for PolicyInputConsumerNetworkClass {
fn from(value: &PolicyInputConsumerNetworkClass) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for PolicyInputConsumerNetworkClass {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Unknown => f.write_str("unknown"),
Self::Home => f.write_str("home"),
Self::Corp => f.write_str("corp"),
Self::Public => f.write_str("public"),
Self::Vpn => f.write_str("vpn"),
}
}
}
impl ::std::str::FromStr for PolicyInputConsumerNetworkClass {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"unknown" => Ok(Self::Unknown),
"home" => Ok(Self::Home),
"corp" => Ok(Self::Corp),
"public" => Ok(Self::Public),
"vpn" => Ok(Self::Vpn),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyInputConsumerNetworkClass {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyInputConsumerNetworkClass {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyInputConsumerNetworkClass {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`PolicyInputContextId`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PolicyInputContextId(::std::string::String);
impl ::std::ops::Deref for PolicyInputContextId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PolicyInputContextId> for ::std::string::String {
fn from(value: PolicyInputContextId) -> Self {
value.0
}
}
impl ::std::convert::From<&PolicyInputContextId> for PolicyInputContextId {
fn from(value: &PolicyInputContextId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for PolicyInputContextId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PolicyInputContextId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyInputContextId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyInputContextId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for PolicyInputContextId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`PolicyInputRequest`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "kind"
/// ],
/// "properties": {
/// "kind": {
/// "type": "string",
/// "enum": [
/// "proxy_login",
/// "release",
/// "step_up_response"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct PolicyInputRequest {
pub kind: PolicyInputRequestKind,
}
impl ::std::convert::From<&PolicyInputRequest> for PolicyInputRequest {
fn from(value: &PolicyInputRequest) -> Self {
value.clone()
}
}
///`PolicyInputRequestKind`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "enum": [
/// "proxy_login",
/// "release",
/// "step_up_response"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyInputRequestKind {
#[serde(rename = "proxy_login")]
ProxyLogin,
#[serde(rename = "release")]
Release,
#[serde(rename = "step_up_response")]
StepUpResponse,
}
impl ::std::convert::From<&Self> for PolicyInputRequestKind {
fn from(value: &PolicyInputRequestKind) -> Self {
value.clone()
}
}
impl ::std::fmt::Display for PolicyInputRequestKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::ProxyLogin => f.write_str("proxy_login"),
Self::Release => f.write_str("release"),
Self::StepUpResponse => f.write_str("step_up_response"),
}
}
}
impl ::std::str::FromStr for PolicyInputRequestKind {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"proxy_login" => Ok(Self::ProxyLogin),
"release" => Ok(Self::Release),
"step_up_response" => Ok(Self::StepUpResponse),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyInputRequestKind {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyInputRequestKind {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyInputRequestKind {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///`Response`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "type": "object",
/// "required": [
/// "decision"
/// ],
/// "properties": {
/// "decision": {
/// "$ref": "#/definitions/PolicyDecision"
/// },
/// "ext": {
/// "$ref": "#/definitions/Ext"
/// },
/// "matchedPolicies": {
/// "description": "Ids (or `candidate` for the dry-run module) of the policies that returned a non-null decision, in evaluation order. The first is the winning policy.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "trace": {
/// "description": "Rego evaluator trace lines when `includeTrace: true`. Maintainer-defined format; primarily for human debugging.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
pub struct Response {
pub decision: PolicyDecision,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Ids (or `candidate` for the dry-run module) of the policies that returned a non-null decision, in evaluation order. The first is the winning policy.
#[serde(
rename = "matchedPolicies",
default,
skip_serializing_if = "::std::vec::Vec::is_empty"
)]
pub matched_policies: ::std::vec::Vec<::std::string::String>,
///Rego evaluator trace lines when `includeTrace: true`. Maintainer-defined format; primarily for human debugging.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub trace: ::std::vec::Vec<::std::string::String>,
}
impl ::std::convert::From<&Response> for Response {
fn from(value: &Response) -> Self {
value.clone()
}
}
///A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "SiteTarget",
/// "description": "A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.",
/// "oneOf": [
/// {
/// "title": "WebOrigin",
/// "type": "object",
/// "required": [
/// "kind",
/// "origin"
/// ],
/// "properties": {
/// "kind": {
/// "const": "web-origin"
/// },
/// "origin": {
/// "description": "Web origin per RFC 6454 (scheme + host + optional port), e.g. \"https://github.com\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.",
/// "type": "string",
/// "format": "uri"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "Did",
/// "type": "object",
/// "required": [
/// "did",
/// "kind"
/// ],
/// "properties": {
/// "did": {
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
/// },
/// "kind": {
/// "const": "did"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "IosApp",
/// "type": "object",
/// "required": [
/// "bundleId",
/// "kind"
/// ],
/// "properties": {
/// "bundleId": {
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
/// },
/// "kind": {
/// "const": "ios-app"
/// },
/// "teamId": {
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
/// }
/// },
/// "additionalProperties": false
/// },
/// {
/// "title": "AndroidApp",
/// "type": "object",
/// "required": [
/// "kind",
/// "packageName",
/// "sha256CertFingerprints"
/// ],
/// "properties": {
/// "kind": {
/// "const": "android-app"
/// },
/// "packageName": {
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
/// },
/// "sha256CertFingerprints": {
/// "description": "SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
/// },
/// "minItems": 1,
/// "uniqueItems": true
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(tag = "kind", deny_unknown_fields)]
pub enum SiteTarget {
///WebOrigin
#[serde(rename = "web-origin")]
WebOrigin {
///Web origin per RFC 6454 (scheme + host + optional port), e.g. "https://github.com". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.
origin: ::std::string::String,
},
///Did
#[serde(rename = "did")]
Did {
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
did: SiteTargetDid,
},
///IosApp
#[serde(rename = "ios-app")]
IosApp {
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
#[serde(rename = "bundleId")]
bundle_id: SiteTargetBundleId,
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
#[serde(
rename = "teamId",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
team_id: ::std::option::Option<SiteTargetTeamId>,
},
///AndroidApp
#[serde(rename = "android-app")]
AndroidApp {
///Android package name in reverse-DNS form (e.g. "com.github.android").
#[serde(rename = "packageName")]
package_name: SiteTargetPackageName,
///SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).
#[serde(rename = "sha256CertFingerprints")]
sha256_cert_fingerprints: Vec<SiteTargetSha256CertFingerprintsItem>,
},
}
impl ::std::convert::From<&Self> for SiteTarget {
fn from(value: &SiteTarget) -> Self {
value.clone()
}
}
///iOS bundle identifier in reverse-DNS form (e.g. "com.github.stwalkerster.codehub"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "iOS bundle identifier in reverse-DNS form (e.g. \"com.github.stwalkerster.codehub\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z0-9.-]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetBundleId(::std::string::String);
impl ::std::ops::Deref for SiteTargetBundleId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetBundleId> for ::std::string::String {
fn from(value: SiteTargetBundleId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetBundleId> for SiteTargetBundleId {
fn from(value: &SiteTargetBundleId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetBundleId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Za-z0-9.-]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Za-z0-9.-]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetBundleId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetBundleId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetDid(::std::string::String);
impl ::std::ops::Deref for SiteTargetDid {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetDid> for ::std::string::String {
fn from(value: SiteTargetDid) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetDid> for SiteTargetDid {
fn from(value: &SiteTargetDid) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetDid {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetDid {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetDid {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Android package name in reverse-DNS form (e.g. "com.github.android").
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Android package name in reverse-DNS form (e.g. \"com.github.android\").",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetPackageName(::std::string::String);
impl ::std::ops::Deref for SiteTargetPackageName {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetPackageName> for ::std::string::String {
fn from(value: SiteTargetPackageName) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetPackageName> for SiteTargetPackageName {
fn from(value: &SiteTargetPackageName) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetPackageName {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err(
"doesn't match pattern \"^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)+$\""
.into(),
);
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetPackageName {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetPackageName {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`SiteTargetSha256CertFingerprintsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "pattern": "^[0-9A-F]{2}(:[0-9A-F]{2}){31}$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetSha256CertFingerprintsItem(::std::string::String);
impl ::std::ops::Deref for SiteTargetSha256CertFingerprintsItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetSha256CertFingerprintsItem> for ::std::string::String {
fn from(value: SiteTargetSha256CertFingerprintsItem) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetSha256CertFingerprintsItem>
for SiteTargetSha256CertFingerprintsItem
{
fn from(value: &SiteTargetSha256CertFingerprintsItem) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetSha256CertFingerprintsItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| {
::regress::Regex::new("^[0-9A-F]{2}(:[0-9A-F]{2}){31}$").unwrap()
});
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetSha256CertFingerprintsItem {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetSha256CertFingerprintsItem {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.",
/// "type": "string",
/// "minLength": 1,
/// "pattern": "^[A-Z0-9]+$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct SiteTargetTeamId(::std::string::String);
impl ::std::ops::Deref for SiteTargetTeamId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SiteTargetTeamId> for ::std::string::String {
fn from(value: SiteTargetTeamId) -> Self {
value.0
}
}
impl ::std::convert::From<&SiteTargetTeamId> for SiteTargetTeamId {
fn from(value: &SiteTargetTeamId) -> Self {
value.clone()
}
}
impl ::std::str::FromStr for SiteTargetTeamId {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
static PATTERN: ::std::sync::LazyLock<::regress::Regex> =
::std::sync::LazyLock::new(|| ::regress::Regex::new("^[A-Z0-9]+$").unwrap());
if PATTERN.find(value).is_none() {
return Err("doesn't match pattern \"^[A-Z0-9]+$\"".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for SiteTargetTeamId {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for SiteTargetTeamId {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
/// Generation of default values for serde.
pub mod defaults {
pub(super) fn default_u64<T, const V: u64>() -> T
where
T: ::std::convert::TryFrom<u64>,
<T as ::std::convert::TryFrom<u64>>::Error: ::std::fmt::Debug,
{
T::try_from(V).unwrap()
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/policy/evaluate/0.1";
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/policy/evaluate/0.1#response";
}
#[cfg(feature = "validate")]
impl crate::validate::ValidatedPayload for Payload {
const SCHEMA_JSON: &'static str = "{\n \"$defs\": {\n \"ConsumerKind\": {\n \"description\": \"Discriminator: is this consumer a user-driven Companion or a headless Service?\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"formFactor\": {\n \"enum\": [\n \"browser\",\n \"mobile\",\n \"desktop\"\n ],\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"companion\"\n }\n },\n \"required\": [\n \"kind\",\n \"formFactor\"\n ],\n \"title\": \"Companion\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"service\"\n },\n \"serviceKind\": {\n \"enum\": [\n \"mediator\",\n \"ai-agent\",\n \"daemon\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"serviceKind\"\n ],\n \"title\": \"Service\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"ConsumerKind\"\n },\n \"Ext\": {\n \"additionalProperties\": true,\n \"description\": \"Vendor-namespaced extension object per SPEC.md §4.5.1. Each immediate key MUST be a reverse-DNS namespace; structure under each namespace is opaque to the framework.\",\n \"minProperties\": 1,\n \"propertyNames\": {\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)+$\"\n },\n \"title\": \"Ext\",\n \"type\": \"object\"\n },\n \"PolicyDecision\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"decision\": {\n \"enum\": [\n \"allow\",\n \"deny\",\n \"require_step_up\"\n ],\n \"type\": \"string\"\n },\n \"explanation\": {\n \"description\": \"Human-readable explanation for diagnostic display.\",\n \"type\": \"string\"\n },\n \"mode\": {\n \"description\": \"When decision == \\\"allow\\\", whether the maintainer should proxy-login or release-for-fill. Default: proxy.\",\n \"enum\": [\n \"proxy\",\n \"fill\"\n ],\n \"type\": \"string\"\n },\n \"stepUp\": {\n \"additionalProperties\": false,\n \"description\": \"When decision == \\\"require_step_up\\\", which method to demand.\",\n \"properties\": {\n \"method\": {\n \"enum\": [\n \"webauthn-uv\",\n \"push-approval\",\n \"totp\"\n ],\n \"type\": \"string\"\n },\n \"ttlSeconds\": {\n \"minimum\": 1,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"method\"\n ],\n \"type\": \"object\"\n },\n \"ttlSecondsCap\": {\n \"description\": \"When decision == \\\"allow\\\", maximum lifetime of the issued session blob / released secret.\",\n \"maximum\": 86400,\n \"minimum\": 1,\n \"type\": \"integer\"\n }\n },\n \"required\": [\n \"decision\"\n ],\n \"title\": \"PolicyDecision\",\n \"type\": \"object\"\n },\n \"PolicyInput\": {\n \"additionalProperties\": false,\n \"description\": \"The structured input fed to a policy evaluator on every vault/proxy-login, vault/release, and policy/evaluate call.\",\n \"properties\": {\n \"consumer\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"deviceId\": {\n \"type\": \"string\"\n },\n \"did\": {\n \"type\": \"string\"\n },\n \"kind\": {\n \"$ref\": \"#/$defs/ConsumerKind\"\n },\n \"lastUserVerificationAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"networkClass\": {\n \"enum\": [\n \"unknown\",\n \"home\",\n \"corp\",\n \"public\",\n \"vpn\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"did\"\n ],\n \"type\": \"object\"\n },\n \"contextId\": {\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"request\": {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"enum\": [\n \"proxy_login\",\n \"release\",\n \"step_up_response\"\n ],\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\"\n ],\n \"type\": \"object\"\n },\n \"site\": {\n \"$ref\": \"#/$defs/SiteTarget\"\n }\n },\n \"required\": [\n \"request\",\n \"site\",\n \"contextId\",\n \"consumer\"\n ],\n \"title\": \"PolicyInput\",\n \"type\": \"object\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"properties\": {\n \"decision\": {\n \"$ref\": \"#/$defs/PolicyDecision\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"matchedPolicies\": {\n \"description\": \"Ids (or `candidate` for the dry-run module) of the policies that returned a non-null decision, in evaluation order. The first is the winning policy.\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n },\n \"trace\": {\n \"description\": \"Rego evaluator trace lines when `includeTrace: true`. Maintainer-defined format; primarily for human debugging.\",\n \"items\": {\n \"type\": \"string\"\n },\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"decision\"\n ],\n \"title\": \"Policy Evaluate — response payload\",\n \"type\": \"object\"\n },\n \"SiteTarget\": {\n \"description\": \"A single binding target for a vault entry. Tagged union over the discriminator `kind`. A VaultEntry's `targets` array MAY mix any number of these.\",\n \"oneOf\": [\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"web-origin\"\n },\n \"origin\": {\n \"description\": \"Web origin per RFC 6454 (scheme + host + optional port), e.g. \\\"https://github.com\\\". Compared by exact string equality after canonicalisation (lowercase host, default port elided). Consumers wanting subdomain coverage SHOULD add multiple targets, not encode a wildcard.\",\n \"format\": \"uri\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"origin\"\n ],\n \"title\": \"WebOrigin\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"did\": {\n \"description\": \"DID identifying the relying party (e.g. did:web:rp.example). The vault maintainer is responsible for any DID resolution required to act on this entry.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"did\"\n }\n },\n \"required\": [\n \"kind\",\n \"did\"\n ],\n \"title\": \"Did\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"bundleId\": {\n \"description\": \"iOS bundle identifier in reverse-DNS form (e.g. \\\"com.github.stwalkerster.codehub\\\"). Compared by exact string equality. Matches when an iOS Companion identifies the requesting app via its bundle id (typically via the OS Credential Manager integration).\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z0-9.-]+$\",\n \"type\": \"string\"\n },\n \"kind\": {\n \"const\": \"ios-app\"\n },\n \"teamId\": {\n \"description\": \"Optional Apple Developer Team identifier (10-character alphanumeric). When supplied, the maintainer SHOULD also verify the team id of the requesting app before matching — defense in depth against bundle-id squatting on jailbroken devices.\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Z0-9]+$\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"kind\",\n \"bundleId\"\n ],\n \"title\": \"IosApp\",\n \"type\": \"object\"\n },\n {\n \"additionalProperties\": false,\n \"properties\": {\n \"kind\": {\n \"const\": \"android-app\"\n },\n \"packageName\": {\n \"description\": \"Android package name in reverse-DNS form (e.g. \\\"com.github.android\\\").\",\n \"minLength\": 1,\n \"pattern\": \"^[A-Za-z][A-Za-z0-9_]*(\\\\.[A-Za-z][A-Za-z0-9_]*)+$\",\n \"type\": \"string\"\n },\n \"sha256CertFingerprints\": {\n \"description\": \"SHA-256 fingerprints of the app's signing certificates, in colon-separated hex (the format `apksigner` and the Play Console emit). At least one fingerprint MUST be present. The maintainer matches when ANY of the provided fingerprints matches the requesting app's signature — this supports apps signed by multiple keys (e.g. during certificate rotation via Play App Signing).\",\n \"items\": {\n \"pattern\": \"^[0-9A-F]{2}(:[0-9A-F]{2}){31}$\",\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n }\n },\n \"required\": [\n \"kind\",\n \"packageName\",\n \"sha256CertFingerprints\"\n ],\n \"title\": \"AndroidApp\",\n \"type\": \"object\"\n }\n ],\n \"title\": \"SiteTarget\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/policy/evaluate/0.1\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Dry-run a policy decision against a synthetic PolicyInput. Returns the policy decision plus a trace of which policy modules matched and which rules fired. Used by the policy-editor UI to verify changes before save and by admins to diagnose unexpected deny/allow outcomes.\",\n \"properties\": {\n \"candidateModule\": {\n \"description\": \"Optional — when supplied, evaluate as if this Rego source were active (e.g. preview a pending upsert). The candidate is layered into the evaluator at the priority specified by `candidatePriority` (default 1000) for this call only.\",\n \"type\": \"string\"\n },\n \"candidatePriority\": {\n \"default\": 1000,\n \"maximum\": 1000,\n \"minimum\": 0,\n \"type\": \"integer\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\"\n },\n \"includeTrace\": {\n \"default\": false,\n \"type\": \"boolean\"\n },\n \"input\": {\n \"$ref\": \"#/$defs/PolicyInput\"\n }\n },\n \"required\": [\n \"input\"\n ],\n \"title\": \"Policy Evaluate — payload\",\n \"type\": \"object\"\n}\n";
}