//! Generated by `trust-tasks-codegen` — do not edit by hand.
//!
//! Spec slug: `acl/revoke`. Version: `0.2`.
#[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())
}
}
}
/**
One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).
The act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer "may this subject do X"; `approve` + `approveCapabilities` answer "may this subject ratify someone else doing X". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.*/
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AclEntry",
/// "description": "One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\n\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \"may this subject do X\"; `approve` + `approveCapabilities` answer \"may this subject ratify someone else doing X\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.",
/// "type": "object",
/// "required": [
/// "act",
/// "capabilities",
/// "keys",
/// "role",
/// "subject"
/// ],
/// "properties": {
/// "act": {
/// "description": "REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\"scope\": \"all\"}` (unrestricted — every context the maintainer has), `{\"scope\": \"none\"}` (may act nowhere), or `{\"scope\": \"contexts\", \"contexts\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.",
/// "$ref": "#/definitions/AuthorityScope"
/// },
/// "approve": {
/// "description": "OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\"scope\": \"none\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.",
/// "$ref": "#/definitions/AuthorityScope"
/// },
/// "approveCapabilities": {
/// "description": "OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\"scope\": \"ceiling\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\"scope\": \"none\"}`, or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\"scope\": \"none\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.",
/// "$ref": "#/definitions/ApproveCapabilityScope"
/// },
/// "capabilities": {
/// "description": "REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\"scope\": \"ceiling\"}` (the role's full ceiling, unnarrowed), `{\"scope\": \"none\"}` (no capabilities), or `{\"scope\": \"listed\", \"grants\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.",
/// "$ref": "#/definitions/CapabilityScope"
/// },
/// "createdAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "createdBy": {
/// "description": "VID of the party that originally wrote this entry.",
/// "type": "string"
/// },
/// "delegatedBy": {
/// "description": "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).",
/// "type": "string",
/// "minLength": 1
/// },
/// "expiresAt": {
/// "description": "Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.",
/// "$ref": "#/definitions/Ext"
/// },
/// "keys": {
/// "description": "REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\"scope\": \"all\"}` (every key the entry's act scope reaches), `{\"scope\": \"none\"}` (no keys), or `{\"scope\": \"listed\", \"keys\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\"scope\": \"none\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.",
/// "$ref": "#/definitions/KeyScope"
/// },
/// "label": {
/// "description": "Optional human-readable label. Confers nothing.",
/// "type": "string",
/// "maxLength": 256
/// },
/// "role": {
/// "description": "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.",
/// "type": "string",
/// "minLength": 1
/// },
/// "stepUp": {
/// "description": "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.",
/// "type": "object",
/// "properties": {
/// "approver": {
/// "description": "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.",
/// "type": "string"
/// },
/// "require": {
/// "description": "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).",
/// "type": "string",
/// "enum": [
/// "self",
/// "delegated"
/// ]
/// }
/// },
/// "additionalProperties": false
/// },
/// "subject": {
/// "description": "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.",
/// "type": "string",
/// "minLength": 1
/// },
/// "updatedAt": {
/// "type": "string",
/// "format": "date-time"
/// },
/// "updatedBy": {
/// "description": "VID of the party that last modified this entry.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AclEntry {
///REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{"scope": "all"}` (unrestricted — every context the maintainer has), `{"scope": "none"}` (may act nowhere), or `{"scope": "contexts", "contexts": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.
pub act: AuthorityScope,
///OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{"scope": "none"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub approve: ::std::option::Option<AuthorityScope>,
///OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{"scope": "ceiling"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{"scope": "none"}`, or `{"scope": "listed", "grants": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{"scope": "none"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.
#[serde(
rename = "approveCapabilities",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub approve_capabilities: ::std::option::Option<ApproveCapabilityScope>,
///REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{"scope": "ceiling"}` (the role's full ceiling, unnarrowed), `{"scope": "none"}` (no capabilities), or `{"scope": "listed", "grants": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.
pub capabilities: CapabilityScope,
#[serde(
rename = "createdAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub created_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///VID of the party that originally wrote this entry.
#[serde(
rename = "createdBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub created_by: ::std::option::Option<::std::string::String>,
///VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).
#[serde(
rename = "delegatedBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub delegated_by: ::std::option::Option<AclEntryDelegatedBy>,
///Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.
#[serde(
rename = "expiresAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub expires_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{"scope": "all"}` (every key the entry's act scope reaches), `{"scope": "none"}` (no keys), or `{"scope": "listed", "keys": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{"scope": "none"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.
pub keys: KeyScope,
///Optional human-readable label. Confers nothing.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub label: ::std::option::Option<AclEntryLabel>,
///Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.
pub role: AclEntryRole,
#[serde(
rename = "stepUp",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub step_up: ::std::option::Option<AclEntryStepUp>,
///VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.
pub subject: AclEntrySubject,
#[serde(
rename = "updatedAt",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub updated_at: ::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
///VID of the party that last modified this entry.
#[serde(
rename = "updatedBy",
default,
skip_serializing_if = "::std::option::Option::is_none"
)]
pub updated_by: ::std::option::Option<::std::string::String>,
}
impl AclEntry {
pub fn builder() -> builder::AclEntry {
Default::default()
}
}
///VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AclEntryDelegatedBy(::std::string::String);
impl ::std::ops::Deref for AclEntryDelegatedBy {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AclEntryDelegatedBy> for ::std::string::String {
fn from(value: AclEntryDelegatedBy) -> Self {
value.0
}
}
impl ::std::str::FromStr for AclEntryDelegatedBy {
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 AclEntryDelegatedBy {
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 AclEntryDelegatedBy {
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 AclEntryDelegatedBy {
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 AclEntryDelegatedBy {
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 human-readable label. Confers nothing.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional human-readable label. Confers nothing.",
/// "type": "string",
/// "maxLength": 256
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AclEntryLabel(::std::string::String);
impl ::std::ops::Deref for AclEntryLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AclEntryLabel> for ::std::string::String {
fn from(value: AclEntryLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for AclEntryLabel {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 256usize {
return Err("longer than 256 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for AclEntryLabel {
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 AclEntryLabel {
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 AclEntryLabel {
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 AclEntryLabel {
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())
})
}
}
///Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AclEntryRole(::std::string::String);
impl ::std::ops::Deref for AclEntryRole {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AclEntryRole> for ::std::string::String {
fn from(value: AclEntryRole) -> Self {
value.0
}
}
impl ::std::str::FromStr for AclEntryRole {
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 AclEntryRole {
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 AclEntryRole {
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 AclEntryRole {
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 AclEntryRole {
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())
})
}
}
///Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.",
/// "type": "object",
/// "properties": {
/// "approver": {
/// "description": "VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.",
/// "type": "string"
/// },
/// "require": {
/// "description": "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).",
/// "type": "string",
/// "enum": [
/// "self",
/// "delegated"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AclEntryStepUp {
///VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub approver: ::std::option::Option<::std::string::String>,
///Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub require: ::std::option::Option<AclEntryStepUpRequire>,
}
impl ::std::default::Default for AclEntryStepUp {
fn default() -> Self {
Self {
approver: Default::default(),
require: Default::default(),
}
}
}
impl AclEntryStepUp {
pub fn builder() -> builder::AclEntryStepUp {
Default::default()
}
}
///Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).",
/// "type": "string",
/// "enum": [
/// "self",
/// "delegated"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
#[non_exhaustive]
pub enum AclEntryStepUpRequire {
#[serde(rename = "self")]
Self_,
#[serde(rename = "delegated")]
Delegated,
}
impl ::std::fmt::Display for AclEntryStepUpRequire {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Self_ => f.write_str("self"),
Self::Delegated => f.write_str("delegated"),
}
}
}
impl ::std::str::FromStr for AclEntryStepUpRequire {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"self" => Ok(Self::Self_),
"delegated" => Ok(Self::Delegated),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for AclEntryStepUpRequire {
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 AclEntryStepUpRequire {
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 AclEntryStepUpRequire {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct AclEntrySubject(::std::string::String);
impl ::std::ops::Deref for AclEntrySubject {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AclEntrySubject> for ::std::string::String {
fn from(value: AclEntrySubject) -> Self {
value.0
}
}
impl ::std::str::FromStr for AclEntrySubject {
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 AclEntrySubject {
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 AclEntrySubject {
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 AclEntrySubject {
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 AclEntrySubject {
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())
})
}
}
///An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ApproveCapabilityScope",
/// "description": "An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/CapabilityScopeCeiling"
/// },
/// {
/// "$ref": "#/definitions/CapabilityScopeNone"
/// },
/// {
/// "$ref": "#/definitions/ApproveCapabilityScopeListed"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum ApproveCapabilityScope {
CapabilityScopeCeiling(CapabilityScopeCeiling),
CapabilityScopeNone(CapabilityScopeNone),
ApproveCapabilityScopeListed(ApproveCapabilityScopeListed),
}
impl ::std::convert::From<CapabilityScopeCeiling> for ApproveCapabilityScope {
fn from(value: CapabilityScopeCeiling) -> Self {
Self::CapabilityScopeCeiling(value)
}
}
impl ::std::convert::From<CapabilityScopeNone> for ApproveCapabilityScope {
fn from(value: CapabilityScopeNone) -> Self {
Self::CapabilityScopeNone(value)
}
}
impl ::std::convert::From<ApproveCapabilityScopeListed> for ApproveCapabilityScope {
fn from(value: ApproveCapabilityScopeListed) -> Self {
Self::ApproveCapabilityScopeListed(value)
}
}
///Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ApproveCapabilityScopeListed",
/// "description": "Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.",
/// "type": "object",
/// "required": [
/// "grants",
/// "scope"
/// ],
/// "properties": {
/// "grants": {
/// "description": "Non-empty list of approvable capabilities. An empty array is invalid.",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/CapabilityRef"
/// },
/// "minItems": 1
/// },
/// "scope": {
/// "const": "listed"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct ApproveCapabilityScopeListed {
///Non-empty list of approvable capabilities. An empty array is invalid.
pub grants: ::std::vec::Vec<CapabilityRef>,
pub scope: ::serde_json::Value,
}
impl ApproveCapabilityScopeListed {
pub fn builder() -> builder::ApproveCapabilityScopeListed {
Default::default()
}
}
///An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AuthorityScope",
/// "description": "An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/AuthorityScopeAll"
/// },
/// {
/// "$ref": "#/definitions/AuthorityScopeNone"
/// },
/// {
/// "$ref": "#/definitions/AuthorityScopeContexts"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum AuthorityScope {
All(AuthorityScopeAll),
None(AuthorityScopeNone),
Contexts(AuthorityScopeContexts),
}
impl ::std::convert::From<AuthorityScopeAll> for AuthorityScope {
fn from(value: AuthorityScopeAll) -> Self {
Self::All(value)
}
}
impl ::std::convert::From<AuthorityScopeNone> for AuthorityScope {
fn from(value: AuthorityScopeNone) -> Self {
Self::None(value)
}
}
impl ::std::convert::From<AuthorityScopeContexts> for AuthorityScope {
fn from(value: AuthorityScopeContexts) -> Self {
Self::Contexts(value)
}
}
///Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AuthorityScopeAll",
/// "description": "Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "all"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AuthorityScopeAll {
pub scope: ::serde_json::Value,
}
impl AuthorityScopeAll {
pub fn builder() -> builder::AuthorityScopeAll {
Default::default()
}
}
///The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AuthorityScopeContexts",
/// "description": "The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.",
/// "type": "object",
/// "required": [
/// "contexts",
/// "scope"
/// ],
/// "properties": {
/// "contexts": {
/// "description": "Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/ContextPath"
/// },
/// "minItems": 1,
/// "uniqueItems": true
/// },
/// "scope": {
/// "const": "contexts"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AuthorityScopeContexts {
///Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).
pub contexts: Vec<ContextPath>,
pub scope: ::serde_json::Value,
}
impl AuthorityScopeContexts {
pub fn builder() -> builder::AuthorityScopeContexts {
Default::default()
}
}
///No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "AuthorityScopeNone",
/// "description": "No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "none"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct AuthorityScopeNone {
pub scope: ::serde_json::Value,
}
impl AuthorityScopeNone {
pub fn builder() -> builder::AuthorityScopeNone {
Default::default()
}
}
///Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Capability",
/// "description": "Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.",
/// "type": "string",
/// "maxLength": 128,
/// "minLength": 1,
/// "pattern": "^[a-z][a-z0-9-]*(\\.[a-z0-9-]+)*$"
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct Capability(::std::string::String);
impl ::std::ops::Deref for Capability {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Capability> for ::std::string::String {
fn from(value: Capability) -> Self {
value.0
}
}
impl ::std::str::FromStr for Capability {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 128usize {
return Err("longer than 128 characters".into());
}
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-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 Capability {
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 Capability {
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 Capability {
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 Capability {
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())
})
}
}
///A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityGrant",
/// "description": "A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.",
/// "type": "object",
/// "required": [
/// "capability"
/// ],
/// "properties": {
/// "additive": {
/// "description": "`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.",
/// "type": "boolean"
/// },
/// "capability": {
/// "$ref": "#/definitions/Capability"
/// },
/// "resource": {
/// "description": "Optional qualifier. Absent covers every resource of the capability's kind.",
/// "$ref": "#/definitions/ResourceQualifier"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CapabilityGrant {
///`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub additive: ::std::option::Option<bool>,
pub capability: Capability,
///Optional qualifier. Absent covers every resource of the capability's kind.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub resource: ::std::option::Option<ResourceQualifier>,
}
impl CapabilityGrant {
pub fn builder() -> builder::CapabilityGrant {
Default::default()
}
}
///A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityRef",
/// "description": "A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.",
/// "type": "object",
/// "required": [
/// "capability"
/// ],
/// "properties": {
/// "capability": {
/// "$ref": "#/definitions/Capability"
/// },
/// "resource": {
/// "description": "Optional qualifier. Absent covers every resource of the capability's kind.",
/// "$ref": "#/definitions/ResourceQualifier"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CapabilityRef {
pub capability: Capability,
///Optional qualifier. Absent covers every resource of the capability's kind.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub resource: ::std::option::Option<ResourceQualifier>,
}
impl CapabilityRef {
pub fn builder() -> builder::CapabilityRef {
Default::default()
}
}
///An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityScope",
/// "description": "An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/CapabilityScopeCeiling"
/// },
/// {
/// "$ref": "#/definitions/CapabilityScopeNone"
/// },
/// {
/// "$ref": "#/definitions/CapabilityScopeListed"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum CapabilityScope {
Ceiling(CapabilityScopeCeiling),
None(CapabilityScopeNone),
Listed(CapabilityScopeListed),
}
impl ::std::convert::From<CapabilityScopeCeiling> for CapabilityScope {
fn from(value: CapabilityScopeCeiling) -> Self {
Self::Ceiling(value)
}
}
impl ::std::convert::From<CapabilityScopeNone> for CapabilityScope {
fn from(value: CapabilityScopeNone) -> Self {
Self::None(value)
}
}
impl ::std::convert::From<CapabilityScopeListed> for CapabilityScope {
fn from(value: CapabilityScopeListed) -> Self {
Self::Listed(value)
}
}
///The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of "no narrowing".
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityScopeCeiling",
/// "description": "The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \"no narrowing\".",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "ceiling"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CapabilityScopeCeiling {
pub scope: ::serde_json::Value,
}
impl CapabilityScopeCeiling {
pub fn builder() -> builder::CapabilityScopeCeiling {
Default::default()
}
}
///Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityScopeListed",
/// "description": "Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.",
/// "type": "object",
/// "required": [
/// "grants",
/// "scope"
/// ],
/// "properties": {
/// "grants": {
/// "description": "Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).",
/// "type": "array",
/// "items": {
/// "$ref": "#/definitions/CapabilityGrant"
/// },
/// "minItems": 1
/// },
/// "scope": {
/// "const": "listed"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CapabilityScopeListed {
///Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).
pub grants: ::std::vec::Vec<CapabilityGrant>,
pub scope: ::serde_json::Value,
}
impl CapabilityScopeListed {
pub fn builder() -> builder::CapabilityScopeListed {
Default::default()
}
}
///No capabilities on this axis.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "CapabilityScopeNone",
/// "description": "No capabilities on this axis.",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "none"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct CapabilityScopeNone {
pub scope: ::serde_json::Value,
}
impl CapabilityScopeNone {
pub fn builder() -> builder::CapabilityScopeNone {
Default::default()
}
}
///Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ContextPath",
/// "description": "Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.",
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ContextPath(::std::string::String);
impl ::std::ops::Deref for ContextPath {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ContextPath> for ::std::string::String {
fn from(value: ContextPath) -> Self {
value.0
}
}
impl ::std::str::FromStr for ContextPath {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ContextPath {
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 ContextPath {
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 ContextPath {
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 ContextPath {
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())
})
}
}
///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<::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::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())
})
}
}
///An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "KeyScope",
/// "description": "An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/KeyScopeAll"
/// },
/// {
/// "$ref": "#/definitions/KeyScopeNone"
/// },
/// {
/// "$ref": "#/definitions/KeyScopeListed"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum KeyScope {
All(KeyScopeAll),
None(KeyScopeNone),
Listed(KeyScopeListed),
}
impl ::std::convert::From<KeyScopeAll> for KeyScope {
fn from(value: KeyScopeAll) -> Self {
Self::All(value)
}
}
impl ::std::convert::From<KeyScopeNone> for KeyScope {
fn from(value: KeyScopeNone) -> Self {
Self::None(value)
}
}
impl ::std::convert::From<KeyScopeListed> for KeyScope {
fn from(value: KeyScopeListed) -> Self {
Self::Listed(value)
}
}
///Every key the entry's act scope reaches.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "KeyScopeAll",
/// "description": "Every key the entry's act scope reaches.",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "all"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct KeyScopeAll {
pub scope: ::serde_json::Value,
}
impl KeyScopeAll {
pub fn builder() -> builder::KeyScopeAll {
Default::default()
}
}
///Exactly the listed keys, intersected with the entry's act scope.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "KeyScopeListed",
/// "description": "Exactly the listed keys, intersected with the entry's act scope.",
/// "type": "object",
/// "required": [
/// "keys",
/// "scope"
/// ],
/// "properties": {
/// "keys": {
/// "description": "Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).",
/// "type": "array",
/// "items": {
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
/// },
/// "minItems": 1,
/// "uniqueItems": true
/// },
/// "scope": {
/// "const": "listed"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct KeyScopeListed {
///Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).
pub keys: Vec<KeyScopeListedKeysItem>,
pub scope: ::serde_json::Value,
}
impl KeyScopeListed {
pub fn builder() -> builder::KeyScopeListed {
Default::default()
}
}
///`KeyScopeListedKeysItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct KeyScopeListedKeysItem(::std::string::String);
impl ::std::ops::Deref for KeyScopeListedKeysItem {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<KeyScopeListedKeysItem> for ::std::string::String {
fn from(value: KeyScopeListedKeysItem) -> Self {
value.0
}
}
impl ::std::str::FromStr for KeyScopeListedKeysItem {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for KeyScopeListedKeysItem {
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 KeyScopeListedKeysItem {
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 KeyScopeListedKeysItem {
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 KeyScopeListedKeysItem {
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())
})
}
}
///No keys.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "KeyScopeNone",
/// "description": "No keys.",
/// "type": "object",
/// "required": [
/// "scope"
/// ],
/// "properties": {
/// "scope": {
/// "const": "none"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct KeyScopeNone {
pub scope: ::serde_json::Value,
}
impl KeyScopeNone {
pub fn builder() -> builder::KeyScopeNone {
Default::default()
}
}
///Narrow the entry's act scope to `act`, which MUST be strictly narrower than the stored act scope (a subset of its contexts, or `none`). The entry, and every other axis of it, remains.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "NarrowAct",
/// "description": "Narrow the entry's act scope to `act`, which MUST be strictly narrower than the stored act scope (a subset of its contexts, or `none`). The entry, and every other axis of it, remains.",
/// "type": "object",
/// "required": [
/// "act",
/// "kind"
/// ],
/// "properties": {
/// "act": {
/// "description": "The resulting act scope, in the explicit form. Stating the result rather than a list of contexts to remove means the producer and the maintainer cannot disagree about what remains.",
/// "$ref": "#/definitions/AuthorityScope"
/// },
/// "kind": {
/// "const": "act"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct NarrowAct {
///The resulting act scope, in the explicit form. Stating the result rather than a list of contexts to remove means the producer and the maintainer cannot disagree about what remains.
pub act: AuthorityScope,
pub kind: ::serde_json::Value,
}
impl NarrowAct {
pub fn builder() -> builder::NarrowAct {
Default::default()
}
}
///Remove a subject's AclEntry 0.2, or narrow its act scope. What is revoked is stated explicitly in `revocation` — there is no form in which the absence of a member selects full removal. Narrowing of other axes (capabilities, approvable capabilities, approve scope, keys) is carried by acl/update/0.2 as a privilege reduction. The outer document members are owned by the framework — SPEC §6.3.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "$id": "https://trusttasks.org/spec/acl/revoke/0.2",
/// "title": "Payload",
/// "description": "Remove a subject's AclEntry 0.2, or narrow its act scope. What is revoked is stated explicitly in `revocation` — there is no form in which the absence of a member selects full removal. Narrowing of other axes (capabilities, approvable capabilities, approve scope, keys) is carried by acl/update/0.2 as a privilege reduction. The outer document members are owned by the framework — SPEC §6.3.",
/// "type": "object",
/// "required": [
/// "revocation",
/// "subject"
/// ],
/// "properties": {
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// },
/// "reason": {
/// "description": "Optional human-readable rationale for the revocation.",
/// "type": "string",
/// "maxLength": 1024
/// },
/// "revocation": {
/// "description": "What is revoked: the whole entry, or act scope down to a stated narrower one.",
/// "$ref": "#/definitions/Revocation"
/// },
/// "subject": {
/// "description": "VID of the subject whose entry is removed or narrowed.",
/// "type": "string",
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Payload {
///Ecosystem-defined extension members per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
///Optional human-readable rationale for the revocation.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<PayloadReason>,
///What is revoked: the whole entry, or act scope down to a stated narrower one.
pub revocation: Revocation,
///VID of the subject whose entry is removed or narrowed.
pub subject: PayloadSubject,
}
impl Payload {
pub fn builder() -> builder::Payload {
Default::default()
}
}
///Optional human-readable rationale for the revocation.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Optional human-readable rationale for the revocation.",
/// "type": "string",
/// "maxLength": 1024
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadReason(::std::string::String);
impl ::std::ops::Deref for PayloadReason {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadReason> for ::std::string::String {
fn from(value: PayloadReason) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadReason {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 1024usize {
return Err("longer than 1024 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for PayloadReason {
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 PayloadReason {
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 PayloadReason {
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 PayloadReason {
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())
})
}
}
///VID of the subject whose entry is removed or narrowed.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "VID of the subject whose entry is removed or narrowed.",
/// "type": "string",
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct PayloadSubject(::std::string::String);
impl ::std::ops::Deref for PayloadSubject {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PayloadSubject> for ::std::string::String {
fn from(value: PayloadSubject) -> Self {
value.0
}
}
impl ::std::str::FromStr for PayloadSubject {
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 PayloadSubject {
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 PayloadSubject {
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 PayloadSubject {
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 PayloadSubject {
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())
})
}
}
///Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ResourceQualifier",
/// "description": "Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.",
/// "type": "string",
/// "maxLength": 512,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct ResourceQualifier(::std::string::String);
impl ::std::ops::Deref for ResourceQualifier {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ResourceQualifier> for ::std::string::String {
fn from(value: ResourceQualifier) -> Self {
value.0
}
}
impl ::std::str::FromStr for ResourceQualifier {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 512usize {
return Err("longer than 512 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for ResourceQualifier {
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 ResourceQualifier {
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 ResourceQualifier {
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 ResourceQualifier {
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())
})
}
}
///The success response to an acl/revoke/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/revoke/0.2#response.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Response",
/// "description": "The success response to an acl/revoke/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/revoke/0.2#response.",
/// "type": "object",
/// "required": [
/// "entry"
/// ],
/// "properties": {
/// "entry": {
/// "description": "null for a removal; the resulting AclEntry for an act-scope narrowing.",
/// "oneOf": [
/// {
/// "type": "null"
/// },
/// {
/// "$ref": "#/definitions/AclEntry"
/// }
/// ]
/// },
/// "ext": {
/// "description": "Ecosystem-defined extension members per SPEC.md §4.5.1.",
/// "$ref": "#/definitions/Ext"
/// }
/// },
/// "additionalProperties": false,
/// "$anchor": "response"
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct Response {
///null for a removal; the resulting AclEntry for an act-scope narrowing.
pub entry: ::std::option::Option<AclEntry>,
///Ecosystem-defined extension members per SPEC.md §4.5.1.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ext: ::std::option::Option<Ext>,
}
impl Response {
pub fn builder() -> builder::Response {
Default::default()
}
}
///Exactly one of: `{"kind": "entry"}` — remove the entry entirely; `{"kind": "act", "act": AuthorityScope}` — replace the entry's act scope with the stated, strictly narrower one, keeping the entry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "Revocation",
/// "description": "Exactly one of: `{\"kind\": \"entry\"}` — remove the entry entirely; `{\"kind\": \"act\", \"act\": AuthorityScope}` — replace the entry's act scope with the stated, strictly narrower one, keeping the entry.",
/// "oneOf": [
/// {
/// "$ref": "#/definitions/RevokeEntry"
/// },
/// {
/// "$ref": "#/definitions/NarrowAct"
/// }
/// ]
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(untagged)]
#[non_exhaustive]
pub enum Revocation {
RevokeEntry(RevokeEntry),
NarrowAct(NarrowAct),
}
impl ::std::convert::From<RevokeEntry> for Revocation {
fn from(value: RevokeEntry) -> Self {
Self::RevokeEntry(value)
}
}
impl ::std::convert::From<NarrowAct> for Revocation {
fn from(value: NarrowAct) -> Self {
Self::NarrowAct(value)
}
}
///Remove the subject's entry entirely.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "RevokeEntry",
/// "description": "Remove the subject's entry entirely.",
/// "type": "object",
/// "required": [
/// "kind"
/// ],
/// "properties": {
/// "kind": {
/// "const": "entry"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(deny_unknown_fields)]
#[non_exhaustive]
pub struct RevokeEntry {
pub kind: ::serde_json::Value,
}
impl RevokeEntry {
pub fn builder() -> builder::RevokeEntry {
Default::default()
}
}
/// Types for composing complex structures.
pub mod builder {
#[derive(Clone, Debug)]
pub struct AclEntry {
act: ::std::result::Result<super::AuthorityScope, ::std::string::String>,
approve: ::std::result::Result<
::std::option::Option<super::AuthorityScope>,
::std::string::String,
>,
approve_capabilities: ::std::result::Result<
::std::option::Option<super::ApproveCapabilityScope>,
::std::string::String,
>,
capabilities: ::std::result::Result<super::CapabilityScope, ::std::string::String>,
created_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
created_by: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
delegated_by: ::std::result::Result<
::std::option::Option<super::AclEntryDelegatedBy>,
::std::string::String,
>,
expires_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
keys: ::std::result::Result<super::KeyScope, ::std::string::String>,
label: ::std::result::Result<
::std::option::Option<super::AclEntryLabel>,
::std::string::String,
>,
role: ::std::result::Result<super::AclEntryRole, ::std::string::String>,
step_up: ::std::result::Result<
::std::option::Option<super::AclEntryStepUp>,
::std::string::String,
>,
subject: ::std::result::Result<super::AclEntrySubject, ::std::string::String>,
updated_at: ::std::result::Result<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
::std::string::String,
>,
updated_by: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
}
impl ::std::default::Default for AclEntry {
fn default() -> Self {
Self {
act: Err("no value supplied for act".to_string()),
approve: Ok(Default::default()),
approve_capabilities: Ok(Default::default()),
capabilities: Err("no value supplied for capabilities".to_string()),
created_at: Ok(Default::default()),
created_by: Ok(Default::default()),
delegated_by: Ok(Default::default()),
expires_at: Ok(Default::default()),
ext: Ok(Default::default()),
keys: Err("no value supplied for keys".to_string()),
label: Ok(Default::default()),
role: Err("no value supplied for role".to_string()),
step_up: Ok(Default::default()),
subject: Err("no value supplied for subject".to_string()),
updated_at: Ok(Default::default()),
updated_by: Ok(Default::default()),
}
}
}
impl AclEntry {
pub fn act<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AuthorityScope>,
T::Error: ::std::fmt::Display,
{
self.act = value
.try_into()
.map_err(|e| format!("error converting supplied value for act: {e}"));
self
}
pub fn approve<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AuthorityScope>>,
T::Error: ::std::fmt::Display,
{
self.approve = value
.try_into()
.map_err(|e| format!("error converting supplied value for approve: {e}"));
self
}
pub fn approve_capabilities<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ApproveCapabilityScope>>,
T::Error: ::std::fmt::Display,
{
self.approve_capabilities = value.try_into().map_err(|e| {
format!("error converting supplied value for approve_capabilities: {e}")
});
self
}
pub fn capabilities<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::CapabilityScope>,
T::Error: ::std::fmt::Display,
{
self.capabilities = value
.try_into()
.map_err(|e| format!("error converting supplied value for capabilities: {e}"));
self
}
pub fn created_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.created_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_at: {e}"));
self
}
pub fn created_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.created_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for created_by: {e}"));
self
}
pub fn delegated_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AclEntryDelegatedBy>>,
T::Error: ::std::fmt::Display,
{
self.delegated_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for delegated_by: {e}"));
self
}
pub fn expires_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.expires_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for expires_at: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn keys<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::KeyScope>,
T::Error: ::std::fmt::Display,
{
self.keys = value
.try_into()
.map_err(|e| format!("error converting supplied value for keys: {e}"));
self
}
pub fn label<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AclEntryLabel>>,
T::Error: ::std::fmt::Display,
{
self.label = value
.try_into()
.map_err(|e| format!("error converting supplied value for label: {e}"));
self
}
pub fn role<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AclEntryRole>,
T::Error: ::std::fmt::Display,
{
self.role = value
.try_into()
.map_err(|e| format!("error converting supplied value for role: {e}"));
self
}
pub fn step_up<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AclEntryStepUp>>,
T::Error: ::std::fmt::Display,
{
self.step_up = value
.try_into()
.map_err(|e| format!("error converting supplied value for step_up: {e}"));
self
}
pub fn subject<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AclEntrySubject>,
T::Error: ::std::fmt::Display,
{
self.subject = value
.try_into()
.map_err(|e| format!("error converting supplied value for subject: {e}"));
self
}
pub fn updated_at<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<
::std::option::Option<::chrono::DateTime<::chrono::offset::Utc>>,
>,
T::Error: ::std::fmt::Display,
{
self.updated_at = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_at: {e}"));
self
}
pub fn updated_by<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.updated_by = value
.try_into()
.map_err(|e| format!("error converting supplied value for updated_by: {e}"));
self
}
}
impl ::std::convert::TryFrom<AclEntry> for super::AclEntry {
type Error = super::error::ConversionError;
fn try_from(value: AclEntry) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
act: value.act?,
approve: value.approve?,
approve_capabilities: value.approve_capabilities?,
capabilities: value.capabilities?,
created_at: value.created_at?,
created_by: value.created_by?,
delegated_by: value.delegated_by?,
expires_at: value.expires_at?,
ext: value.ext?,
keys: value.keys?,
label: value.label?,
role: value.role?,
step_up: value.step_up?,
subject: value.subject?,
updated_at: value.updated_at?,
updated_by: value.updated_by?,
})
}
}
impl ::std::convert::From<super::AclEntry> for AclEntry {
fn from(value: super::AclEntry) -> Self {
Self {
act: Ok(value.act),
approve: Ok(value.approve),
approve_capabilities: Ok(value.approve_capabilities),
capabilities: Ok(value.capabilities),
created_at: Ok(value.created_at),
created_by: Ok(value.created_by),
delegated_by: Ok(value.delegated_by),
expires_at: Ok(value.expires_at),
ext: Ok(value.ext),
keys: Ok(value.keys),
label: Ok(value.label),
role: Ok(value.role),
step_up: Ok(value.step_up),
subject: Ok(value.subject),
updated_at: Ok(value.updated_at),
updated_by: Ok(value.updated_by),
}
}
}
#[derive(Clone, Debug)]
pub struct AclEntryStepUp {
approver: ::std::result::Result<
::std::option::Option<::std::string::String>,
::std::string::String,
>,
require: ::std::result::Result<
::std::option::Option<super::AclEntryStepUpRequire>,
::std::string::String,
>,
}
impl ::std::default::Default for AclEntryStepUp {
fn default() -> Self {
Self {
approver: Ok(Default::default()),
require: Ok(Default::default()),
}
}
}
impl AclEntryStepUp {
pub fn approver<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<::std::string::String>>,
T::Error: ::std::fmt::Display,
{
self.approver = value
.try_into()
.map_err(|e| format!("error converting supplied value for approver: {e}"));
self
}
pub fn require<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AclEntryStepUpRequire>>,
T::Error: ::std::fmt::Display,
{
self.require = value
.try_into()
.map_err(|e| format!("error converting supplied value for require: {e}"));
self
}
}
impl ::std::convert::TryFrom<AclEntryStepUp> for super::AclEntryStepUp {
type Error = super::error::ConversionError;
fn try_from(
value: AclEntryStepUp,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
approver: value.approver?,
require: value.require?,
})
}
}
impl ::std::convert::From<super::AclEntryStepUp> for AclEntryStepUp {
fn from(value: super::AclEntryStepUp) -> Self {
Self {
approver: Ok(value.approver),
require: Ok(value.require),
}
}
}
#[derive(Clone, Debug)]
pub struct ApproveCapabilityScopeListed {
grants: ::std::result::Result<::std::vec::Vec<super::CapabilityRef>, ::std::string::String>,
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for ApproveCapabilityScopeListed {
fn default() -> Self {
Self {
grants: Err("no value supplied for grants".to_string()),
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl ApproveCapabilityScopeListed {
pub fn grants<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::CapabilityRef>>,
T::Error: ::std::fmt::Display,
{
self.grants = value
.try_into()
.map_err(|e| format!("error converting supplied value for grants: {e}"));
self
}
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<ApproveCapabilityScopeListed> for super::ApproveCapabilityScopeListed {
type Error = super::error::ConversionError;
fn try_from(
value: ApproveCapabilityScopeListed,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
grants: value.grants?,
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::ApproveCapabilityScopeListed> for ApproveCapabilityScopeListed {
fn from(value: super::ApproveCapabilityScopeListed) -> Self {
Self {
grants: Ok(value.grants),
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct AuthorityScopeAll {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for AuthorityScopeAll {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl AuthorityScopeAll {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<AuthorityScopeAll> for super::AuthorityScopeAll {
type Error = super::error::ConversionError;
fn try_from(
value: AuthorityScopeAll,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::AuthorityScopeAll> for AuthorityScopeAll {
fn from(value: super::AuthorityScopeAll) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct AuthorityScopeContexts {
contexts: ::std::result::Result<Vec<super::ContextPath>, ::std::string::String>,
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for AuthorityScopeContexts {
fn default() -> Self {
Self {
contexts: Err("no value supplied for contexts".to_string()),
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl AuthorityScopeContexts {
pub fn contexts<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<Vec<super::ContextPath>>,
T::Error: ::std::fmt::Display,
{
self.contexts = value
.try_into()
.map_err(|e| format!("error converting supplied value for contexts: {e}"));
self
}
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<AuthorityScopeContexts> for super::AuthorityScopeContexts {
type Error = super::error::ConversionError;
fn try_from(
value: AuthorityScopeContexts,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
contexts: value.contexts?,
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::AuthorityScopeContexts> for AuthorityScopeContexts {
fn from(value: super::AuthorityScopeContexts) -> Self {
Self {
contexts: Ok(value.contexts),
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct AuthorityScopeNone {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for AuthorityScopeNone {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl AuthorityScopeNone {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<AuthorityScopeNone> for super::AuthorityScopeNone {
type Error = super::error::ConversionError;
fn try_from(
value: AuthorityScopeNone,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::AuthorityScopeNone> for AuthorityScopeNone {
fn from(value: super::AuthorityScopeNone) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct CapabilityGrant {
additive: ::std::result::Result<::std::option::Option<bool>, ::std::string::String>,
capability: ::std::result::Result<super::Capability, ::std::string::String>,
resource: ::std::result::Result<
::std::option::Option<super::ResourceQualifier>,
::std::string::String,
>,
}
impl ::std::default::Default for CapabilityGrant {
fn default() -> Self {
Self {
additive: Ok(Default::default()),
capability: Err("no value supplied for capability".to_string()),
resource: Ok(Default::default()),
}
}
}
impl CapabilityGrant {
pub fn additive<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<bool>>,
T::Error: ::std::fmt::Display,
{
self.additive = value
.try_into()
.map_err(|e| format!("error converting supplied value for additive: {e}"));
self
}
pub fn capability<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Capability>,
T::Error: ::std::fmt::Display,
{
self.capability = value
.try_into()
.map_err(|e| format!("error converting supplied value for capability: {e}"));
self
}
pub fn resource<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ResourceQualifier>>,
T::Error: ::std::fmt::Display,
{
self.resource = value
.try_into()
.map_err(|e| format!("error converting supplied value for resource: {e}"));
self
}
}
impl ::std::convert::TryFrom<CapabilityGrant> for super::CapabilityGrant {
type Error = super::error::ConversionError;
fn try_from(
value: CapabilityGrant,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
additive: value.additive?,
capability: value.capability?,
resource: value.resource?,
})
}
}
impl ::std::convert::From<super::CapabilityGrant> for CapabilityGrant {
fn from(value: super::CapabilityGrant) -> Self {
Self {
additive: Ok(value.additive),
capability: Ok(value.capability),
resource: Ok(value.resource),
}
}
}
#[derive(Clone, Debug)]
pub struct CapabilityRef {
capability: ::std::result::Result<super::Capability, ::std::string::String>,
resource: ::std::result::Result<
::std::option::Option<super::ResourceQualifier>,
::std::string::String,
>,
}
impl ::std::default::Default for CapabilityRef {
fn default() -> Self {
Self {
capability: Err("no value supplied for capability".to_string()),
resource: Ok(Default::default()),
}
}
}
impl CapabilityRef {
pub fn capability<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Capability>,
T::Error: ::std::fmt::Display,
{
self.capability = value
.try_into()
.map_err(|e| format!("error converting supplied value for capability: {e}"));
self
}
pub fn resource<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::ResourceQualifier>>,
T::Error: ::std::fmt::Display,
{
self.resource = value
.try_into()
.map_err(|e| format!("error converting supplied value for resource: {e}"));
self
}
}
impl ::std::convert::TryFrom<CapabilityRef> for super::CapabilityRef {
type Error = super::error::ConversionError;
fn try_from(
value: CapabilityRef,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
capability: value.capability?,
resource: value.resource?,
})
}
}
impl ::std::convert::From<super::CapabilityRef> for CapabilityRef {
fn from(value: super::CapabilityRef) -> Self {
Self {
capability: Ok(value.capability),
resource: Ok(value.resource),
}
}
}
#[derive(Clone, Debug)]
pub struct CapabilityScopeCeiling {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for CapabilityScopeCeiling {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl CapabilityScopeCeiling {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<CapabilityScopeCeiling> for super::CapabilityScopeCeiling {
type Error = super::error::ConversionError;
fn try_from(
value: CapabilityScopeCeiling,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::CapabilityScopeCeiling> for CapabilityScopeCeiling {
fn from(value: super::CapabilityScopeCeiling) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct CapabilityScopeListed {
grants:
::std::result::Result<::std::vec::Vec<super::CapabilityGrant>, ::std::string::String>,
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for CapabilityScopeListed {
fn default() -> Self {
Self {
grants: Err("no value supplied for grants".to_string()),
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl CapabilityScopeListed {
pub fn grants<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::vec::Vec<super::CapabilityGrant>>,
T::Error: ::std::fmt::Display,
{
self.grants = value
.try_into()
.map_err(|e| format!("error converting supplied value for grants: {e}"));
self
}
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<CapabilityScopeListed> for super::CapabilityScopeListed {
type Error = super::error::ConversionError;
fn try_from(
value: CapabilityScopeListed,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
grants: value.grants?,
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::CapabilityScopeListed> for CapabilityScopeListed {
fn from(value: super::CapabilityScopeListed) -> Self {
Self {
grants: Ok(value.grants),
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct CapabilityScopeNone {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for CapabilityScopeNone {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl CapabilityScopeNone {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<CapabilityScopeNone> for super::CapabilityScopeNone {
type Error = super::error::ConversionError;
fn try_from(
value: CapabilityScopeNone,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::CapabilityScopeNone> for CapabilityScopeNone {
fn from(value: super::CapabilityScopeNone) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct KeyScopeAll {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for KeyScopeAll {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl KeyScopeAll {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<KeyScopeAll> for super::KeyScopeAll {
type Error = super::error::ConversionError;
fn try_from(
value: KeyScopeAll,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::KeyScopeAll> for KeyScopeAll {
fn from(value: super::KeyScopeAll) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct KeyScopeListed {
keys: ::std::result::Result<Vec<super::KeyScopeListedKeysItem>, ::std::string::String>,
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for KeyScopeListed {
fn default() -> Self {
Self {
keys: Err("no value supplied for keys".to_string()),
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl KeyScopeListed {
pub fn keys<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<Vec<super::KeyScopeListedKeysItem>>,
T::Error: ::std::fmt::Display,
{
self.keys = value
.try_into()
.map_err(|e| format!("error converting supplied value for keys: {e}"));
self
}
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<KeyScopeListed> for super::KeyScopeListed {
type Error = super::error::ConversionError;
fn try_from(
value: KeyScopeListed,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
keys: value.keys?,
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::KeyScopeListed> for KeyScopeListed {
fn from(value: super::KeyScopeListed) -> Self {
Self {
keys: Ok(value.keys),
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct KeyScopeNone {
scope: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for KeyScopeNone {
fn default() -> Self {
Self {
scope: Err("no value supplied for scope".to_string()),
}
}
}
impl KeyScopeNone {
pub fn scope<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.scope = value
.try_into()
.map_err(|e| format!("error converting supplied value for scope: {e}"));
self
}
}
impl ::std::convert::TryFrom<KeyScopeNone> for super::KeyScopeNone {
type Error = super::error::ConversionError;
fn try_from(
value: KeyScopeNone,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
scope: value.scope?,
})
}
}
impl ::std::convert::From<super::KeyScopeNone> for KeyScopeNone {
fn from(value: super::KeyScopeNone) -> Self {
Self {
scope: Ok(value.scope),
}
}
}
#[derive(Clone, Debug)]
pub struct NarrowAct {
act: ::std::result::Result<super::AuthorityScope, ::std::string::String>,
kind: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for NarrowAct {
fn default() -> Self {
Self {
act: Err("no value supplied for act".to_string()),
kind: Err("no value supplied for kind".to_string()),
}
}
}
impl NarrowAct {
pub fn act<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::AuthorityScope>,
T::Error: ::std::fmt::Display,
{
self.act = value
.try_into()
.map_err(|e| format!("error converting supplied value for act: {e}"));
self
}
pub fn kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for kind: {e}"));
self
}
}
impl ::std::convert::TryFrom<NarrowAct> for super::NarrowAct {
type Error = super::error::ConversionError;
fn try_from(
value: NarrowAct,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
act: value.act?,
kind: value.kind?,
})
}
}
impl ::std::convert::From<super::NarrowAct> for NarrowAct {
fn from(value: super::NarrowAct) -> Self {
Self {
act: Ok(value.act),
kind: Ok(value.kind),
}
}
}
#[derive(Clone, Debug)]
pub struct Payload {
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
reason: ::std::result::Result<
::std::option::Option<super::PayloadReason>,
::std::string::String,
>,
revocation: ::std::result::Result<super::Revocation, ::std::string::String>,
subject: ::std::result::Result<super::PayloadSubject, ::std::string::String>,
}
impl ::std::default::Default for Payload {
fn default() -> Self {
Self {
ext: Ok(Default::default()),
reason: Ok(Default::default()),
revocation: Err("no value supplied for revocation".to_string()),
subject: Err("no value supplied for subject".to_string()),
}
}
}
impl Payload {
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
pub fn reason<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::PayloadReason>>,
T::Error: ::std::fmt::Display,
{
self.reason = value
.try_into()
.map_err(|e| format!("error converting supplied value for reason: {e}"));
self
}
pub fn revocation<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::Revocation>,
T::Error: ::std::fmt::Display,
{
self.revocation = value
.try_into()
.map_err(|e| format!("error converting supplied value for revocation: {e}"));
self
}
pub fn subject<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<super::PayloadSubject>,
T::Error: ::std::fmt::Display,
{
self.subject = value
.try_into()
.map_err(|e| format!("error converting supplied value for subject: {e}"));
self
}
}
impl ::std::convert::TryFrom<Payload> for super::Payload {
type Error = super::error::ConversionError;
fn try_from(value: Payload) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
ext: value.ext?,
reason: value.reason?,
revocation: value.revocation?,
subject: value.subject?,
})
}
}
impl ::std::convert::From<super::Payload> for Payload {
fn from(value: super::Payload) -> Self {
Self {
ext: Ok(value.ext),
reason: Ok(value.reason),
revocation: Ok(value.revocation),
subject: Ok(value.subject),
}
}
}
#[derive(Clone, Debug)]
pub struct Response {
entry: ::std::result::Result<::std::option::Option<super::AclEntry>, ::std::string::String>,
ext: ::std::result::Result<::std::option::Option<super::Ext>, ::std::string::String>,
}
impl ::std::default::Default for Response {
fn default() -> Self {
Self {
entry: Err("no value supplied for entry".to_string()),
ext: Ok(Default::default()),
}
}
}
impl Response {
pub fn entry<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::AclEntry>>,
T::Error: ::std::fmt::Display,
{
self.entry = value
.try_into()
.map_err(|e| format!("error converting supplied value for entry: {e}"));
self
}
pub fn ext<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::std::option::Option<super::Ext>>,
T::Error: ::std::fmt::Display,
{
self.ext = value
.try_into()
.map_err(|e| format!("error converting supplied value for ext: {e}"));
self
}
}
impl ::std::convert::TryFrom<Response> for super::Response {
type Error = super::error::ConversionError;
fn try_from(value: Response) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self {
entry: value.entry?,
ext: value.ext?,
})
}
}
impl ::std::convert::From<super::Response> for Response {
fn from(value: super::Response) -> Self {
Self {
entry: Ok(value.entry),
ext: Ok(value.ext),
}
}
}
#[derive(Clone, Debug)]
pub struct RevokeEntry {
kind: ::std::result::Result<::serde_json::Value, ::std::string::String>,
}
impl ::std::default::Default for RevokeEntry {
fn default() -> Self {
Self {
kind: Err("no value supplied for kind".to_string()),
}
}
}
impl RevokeEntry {
pub fn kind<T>(mut self, value: T) -> Self
where
T: ::std::convert::TryInto<::serde_json::Value>,
T::Error: ::std::fmt::Display,
{
self.kind = value
.try_into()
.map_err(|e| format!("error converting supplied value for kind: {e}"));
self
}
}
impl ::std::convert::TryFrom<RevokeEntry> for super::RevokeEntry {
type Error = super::error::ConversionError;
fn try_from(
value: RevokeEntry,
) -> ::std::result::Result<Self, super::error::ConversionError> {
Ok(Self { kind: value.kind? })
}
}
impl ::std::convert::From<super::RevokeEntry> for RevokeEntry {
fn from(value: super::RevokeEntry) -> Self {
Self {
kind: Ok(value.kind),
}
}
}
}
impl crate::Payload for Payload {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/acl/revoke/0.2";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"AclEntry\": {\n \"additionalProperties\": false,\n \"description\": \"One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\\n\\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \\\"may this subject do X\\\"; `approve` + `approveCapabilities` answer \\\"may this subject ratify someone else doing X\\\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.\",\n \"properties\": {\n \"act\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\\\"scope\\\": \\\"all\\\"}` (unrestricted — every context the maintainer has), `{\\\"scope\\\": \\\"none\\\"}` (may act nowhere), or `{\\\"scope\\\": \\\"contexts\\\", \\\"contexts\\\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.\"\n },\n \"approve\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\\\"scope\\\": \\\"none\\\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.\"\n },\n \"approveCapabilities\": {\n \"$ref\": \"#/$defs/ApproveCapabilityScope\",\n \"description\": \"OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\\\"scope\\\": \\\"ceiling\\\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\\\"scope\\\": \\\"none\\\"}`, or `{\\\"scope\\\": \\\"listed\\\", \\\"grants\\\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\\\"scope\\\": \\\"none\\\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.\"\n },\n \"capabilities\": {\n \"$ref\": \"#/$defs/CapabilityScope\",\n \"description\": \"REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\\\"scope\\\": \\\"ceiling\\\"}` (the role's full ceiling, unnarrowed), `{\\\"scope\\\": \\\"none\\\"}` (no capabilities), or `{\\\"scope\\\": \\\"listed\\\", \\\"grants\\\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.\"\n },\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"createdBy\": {\n \"description\": \"VID of the party that originally wrote this entry.\",\n \"type\": \"string\"\n },\n \"delegatedBy\": {\n \"description\": \"VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"description\": \"Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.\"\n },\n \"keys\": {\n \"$ref\": \"#/$defs/KeyScope\",\n \"description\": \"REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\\\"scope\\\": \\\"all\\\"}` (every key the entry's act scope reaches), `{\\\"scope\\\": \\\"none\\\"}` (no keys), or `{\\\"scope\\\": \\\"listed\\\", \\\"keys\\\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\\\"scope\\\": \\\"none\\\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.\"\n },\n \"label\": {\n \"description\": \"Optional human-readable label. Confers nothing.\",\n \"maxLength\": 256,\n \"type\": \"string\"\n },\n \"role\": {\n \"description\": \"Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"stepUp\": {\n \"additionalProperties\": false,\n \"description\": \"Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.\",\n \"properties\": {\n \"approver\": {\n \"description\": \"VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.\",\n \"type\": \"string\"\n },\n \"require\": {\n \"description\": \"Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).\",\n \"enum\": [\n \"self\",\n \"delegated\"\n ],\n \"type\": \"string\"\n }\n },\n \"type\": \"object\"\n },\n \"subject\": {\n \"description\": \"VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"updatedBy\": {\n \"description\": \"VID of the party that last modified this entry.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"subject\",\n \"role\",\n \"act\",\n \"keys\",\n \"capabilities\"\n ],\n \"title\": \"AclEntry\",\n \"type\": \"object\"\n },\n \"ApproveCapabilityScope\": {\n \"description\": \"An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/CapabilityScopeCeiling\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/ApproveCapabilityScopeListed\"\n }\n ],\n \"title\": \"ApproveCapabilityScope\"\n },\n \"ApproveCapabilityScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.\",\n \"properties\": {\n \"grants\": {\n \"description\": \"Non-empty list of approvable capabilities. An empty array is invalid.\",\n \"items\": {\n \"$ref\": \"#/$defs/CapabilityRef\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"grants\"\n ],\n \"title\": \"ApproveCapabilityScopeListed\",\n \"type\": \"object\"\n },\n \"AuthorityScope\": {\n \"description\": \"An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/AuthorityScopeAll\"\n },\n {\n \"$ref\": \"#/$defs/AuthorityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/AuthorityScopeContexts\"\n }\n ],\n \"title\": \"AuthorityScope\"\n },\n \"AuthorityScopeAll\": {\n \"additionalProperties\": false,\n \"description\": \"Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).\",\n \"properties\": {\n \"scope\": {\n \"const\": \"all\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"AuthorityScopeAll\",\n \"type\": \"object\"\n },\n \"AuthorityScopeContexts\": {\n \"additionalProperties\": false,\n \"description\": \"The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.\",\n \"properties\": {\n \"contexts\": {\n \"description\": \"Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).\",\n \"items\": {\n \"$ref\": \"#/$defs/ContextPath\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"scope\": {\n \"const\": \"contexts\"\n }\n },\n \"required\": [\n \"scope\",\n \"contexts\"\n ],\n \"title\": \"AuthorityScopeContexts\",\n \"type\": \"object\"\n },\n \"AuthorityScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"AuthorityScopeNone\",\n \"type\": \"object\"\n },\n \"Capability\": {\n \"description\": \"Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)*$\",\n \"title\": \"Capability\",\n \"type\": \"string\"\n },\n \"CapabilityGrant\": {\n \"additionalProperties\": false,\n \"description\": \"A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.\",\n \"properties\": {\n \"additive\": {\n \"description\": \"`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.\",\n \"type\": \"boolean\"\n },\n \"capability\": {\n \"$ref\": \"#/$defs/Capability\"\n },\n \"resource\": {\n \"$ref\": \"#/$defs/ResourceQualifier\",\n \"description\": \"Optional qualifier. Absent covers every resource of the capability's kind.\"\n }\n },\n \"required\": [\n \"capability\"\n ],\n \"title\": \"CapabilityGrant\",\n \"type\": \"object\"\n },\n \"CapabilityRef\": {\n \"additionalProperties\": false,\n \"description\": \"A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.\",\n \"properties\": {\n \"capability\": {\n \"$ref\": \"#/$defs/Capability\"\n },\n \"resource\": {\n \"$ref\": \"#/$defs/ResourceQualifier\",\n \"description\": \"Optional qualifier. Absent covers every resource of the capability's kind.\"\n }\n },\n \"required\": [\n \"capability\"\n ],\n \"title\": \"CapabilityRef\",\n \"type\": \"object\"\n },\n \"CapabilityScope\": {\n \"description\": \"An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/CapabilityScopeCeiling\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeListed\"\n }\n ],\n \"title\": \"CapabilityScope\"\n },\n \"CapabilityScopeCeiling\": {\n \"additionalProperties\": false,\n \"description\": \"The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \\\"no narrowing\\\".\",\n \"properties\": {\n \"scope\": {\n \"const\": \"ceiling\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"CapabilityScopeCeiling\",\n \"type\": \"object\"\n },\n \"CapabilityScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.\",\n \"properties\": {\n \"grants\": {\n \"description\": \"Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).\",\n \"items\": {\n \"$ref\": \"#/$defs/CapabilityGrant\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"grants\"\n ],\n \"title\": \"CapabilityScopeListed\",\n \"type\": \"object\"\n },\n \"CapabilityScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No capabilities on this axis.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"CapabilityScopeNone\",\n \"type\": \"object\"\n },\n \"ContextPath\": {\n \"description\": \"Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"ContextPath\",\n \"type\": \"string\"\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 \"KeyScope\": {\n \"description\": \"An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/KeyScopeAll\"\n },\n {\n \"$ref\": \"#/$defs/KeyScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/KeyScopeListed\"\n }\n ],\n \"title\": \"KeyScope\"\n },\n \"KeyScopeAll\": {\n \"additionalProperties\": false,\n \"description\": \"Every key the entry's act scope reaches.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"all\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"KeyScopeAll\",\n \"type\": \"object\"\n },\n \"KeyScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed keys, intersected with the entry's act scope.\",\n \"properties\": {\n \"keys\": {\n \"description\": \"Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).\",\n \"items\": {\n \"maxLength\": 512,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"keys\"\n ],\n \"title\": \"KeyScopeListed\",\n \"type\": \"object\"\n },\n \"KeyScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No keys.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"KeyScopeNone\",\n \"type\": \"object\"\n },\n \"NarrowAct\": {\n \"additionalProperties\": false,\n \"description\": \"Narrow the entry's act scope to `act`, which MUST be strictly narrower than the stored act scope (a subset of its contexts, or `none`). The entry, and every other axis of it, remains.\",\n \"properties\": {\n \"act\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"The resulting act scope, in the explicit form. Stating the result rather than a list of contexts to remove means the producer and the maintainer cannot disagree about what remains.\"\n },\n \"kind\": {\n \"const\": \"act\"\n }\n },\n \"required\": [\n \"kind\",\n \"act\"\n ],\n \"title\": \"NarrowAct\",\n \"type\": \"object\"\n },\n \"ResourceQualifier\": {\n \"description\": \"Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"ResourceQualifier\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to an acl/revoke/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/revoke/0.2#response.\",\n \"properties\": {\n \"entry\": {\n \"description\": \"null for a removal; the resulting AclEntry for an act-scope narrowing.\",\n \"oneOf\": [\n {\n \"type\": \"null\"\n },\n {\n \"$ref\": \"#/$defs/AclEntry\"\n }\n ]\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n }\n },\n \"required\": [\n \"entry\"\n ],\n \"title\": \"ACL Revoke 0.2 — response payload\",\n \"type\": \"object\"\n },\n \"Revocation\": {\n \"description\": \"Exactly one of: `{\\\"kind\\\": \\\"entry\\\"}` — remove the entry entirely; `{\\\"kind\\\": \\\"act\\\", \\\"act\\\": AuthorityScope}` — replace the entry's act scope with the stated, strictly narrower one, keeping the entry.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/RevokeEntry\"\n },\n {\n \"$ref\": \"#/$defs/NarrowAct\"\n }\n ],\n \"title\": \"Revocation\"\n },\n \"RevokeEntry\": {\n \"additionalProperties\": false,\n \"description\": \"Remove the subject's entry entirely.\",\n \"properties\": {\n \"kind\": {\n \"const\": \"entry\"\n }\n },\n \"required\": [\n \"kind\"\n ],\n \"title\": \"RevokeEntry\",\n \"type\": \"object\"\n }\n },\n \"$id\": \"https://trusttasks.org/spec/acl/revoke/0.2\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"additionalProperties\": false,\n \"description\": \"Remove a subject's AclEntry 0.2, or narrow its act scope. What is revoked is stated explicitly in `revocation` — there is no form in which the absence of a member selects full removal. Narrowing of other axes (capabilities, approvable capabilities, approve scope, keys) is carried by acl/update/0.2 as a privilege reduction. The outer document members are owned by the framework — SPEC §6.3.\",\n \"properties\": {\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n },\n \"reason\": {\n \"description\": \"Optional human-readable rationale for the revocation.\",\n \"maxLength\": 1024,\n \"type\": \"string\"\n },\n \"revocation\": {\n \"$ref\": \"#/$defs/Revocation\",\n \"description\": \"What is revoked: the whole entry, or act scope down to a stated narrower one.\"\n },\n \"subject\": {\n \"description\": \"VID of the subject whose entry is removed or narrowed.\",\n \"minLength\": 1,\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"subject\",\n \"revocation\"\n ],\n \"title\": \"ACL Revoke 0.2 — payload\",\n \"type\": \"object\"\n}\n",
);
}
impl crate::Payload for Response {
const TYPE_URI: &'static str = "https://trusttasks.org/spec/acl/revoke/0.2#response";
const IS_PROOF_REQUIRED: bool = true;
const IS_ISSUED_AT_REQUIRED: bool = true;
const IS_RECIPIENT_REQUIRED: bool = true;
const PAYLOAD_SCHEMA: Option<&'static str> = Some(
"{\n \"$defs\": {\n \"AclEntry\": {\n \"additionalProperties\": false,\n \"description\": \"One access-control entry: who the grant is for (`subject`), the ceiling it is held under (`role`), where the subject may act (`act`) and approve (`approve`), and which capabilities it may exercise (`capabilities`) and approve (`approveCapabilities`).\\n\\nThe act axis and the approve axis are independent and a consumer MUST resolve them separately: `act` + `capabilities` (+ `keys`) answer \\\"may this subject do X\\\"; `approve` + `approveCapabilities` answer \\\"may this subject ratify someone else doing X\\\". Neither implies the other. An entry with `act: {scope: none}` and an approve scope other than none is a least-privilege approver — able to satisfy an approval and unable to initiate any change.\",\n \"properties\": {\n \"act\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"REQUIRED explicit act scope: where this subject may make a change itself. Exactly one of `{\\\"scope\\\": \\\"all\\\"}` (unrestricted — every context the maintainer has), `{\\\"scope\\\": \\\"none\\\"}` (may act nowhere), or `{\\\"scope\\\": \\\"contexts\\\", \\\"contexts\\\": [...]}` with at least one context path (the named contexts and, where the maintainer's contexts are hierarchical, their descendants). There is no default and no implicit form: an entry without `act`, or with an empty `contexts` list, is malformed and MUST be refused, never read as `all` and never read as `none`. A maintainer that has no contexts (for example a community node that narrows authority with resource qualifiers instead) states `all` or `none` only. Replaces 0.1's `scopes`.\"\n },\n \"approve\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"OPTIONAL approve scope: where this subject may ratify a change made by someone else (a step-up ratification, a consent decision, an N-of-M approval). Same three shapes as `act`, resolved independently of it. ABSENT MEANS NONE — the subject may ratify nothing — so a consumer that has not implemented the member confers less than the producer intended, never more. A producer SHOULD state `{\\\"scope\\\": \\\"none\\\"}` explicitly rather than rely on omission. A subject MUST NOT confer approve authority wider than the approve authority it holds itself (see acl/grant `approveWiderThanGranter`). Replaces 0.1's `approve {all, scopes}`.\"\n },\n \"approveCapabilities\": {\n \"$ref\": \"#/$defs/ApproveCapabilityScope\",\n \"description\": \"OPTIONAL explicit approvable-capability scope: which capabilities this subject may APPROVE an action needing — independent of what it may do itself, so an approver can ratify a capability it does not hold (the least-privilege approver). One of `{\\\"scope\\\": \\\"ceiling\\\"}` (the role's full approve ceiling; at a maintainer whose roles define no capability-level approve ceiling, any action within `approve`), `{\\\"scope\\\": \\\"none\\\"}`, or `{\\\"scope\\\": \\\"listed\\\", \\\"grants\\\": [...]}` with at least one CapabilityRef (intersected with the role's approve ceiling where one is defined). ABSENT MEANS NONE: the subject may approve no capability, because absence derives no authority. Bounded by `approve`: where `approve` is absent or `{\\\"scope\\\": \\\"none\\\"}` this member confers nothing whatever it states. A subject MUST NOT confer approvable capabilities it cannot itself approve.\"\n },\n \"capabilities\": {\n \"$ref\": \"#/$defs/CapabilityScope\",\n \"description\": \"REQUIRED explicit capability scope: which capabilities this entry holds. Exactly one of `{\\\"scope\\\": \\\"ceiling\\\"}` (the role's full ceiling, unnarrowed), `{\\\"scope\\\": \\\"none\\\"}` (no capabilities), or `{\\\"scope\\\": \\\"listed\\\", \\\"grants\\\": [...]}` with at least one CapabilityGrant. For `listed`, the EFFECTIVE set is (the role's ceiling ∩ the non-additive grants) ∪ the additive grants; it can only narrow the ceiling, except through an explicit additive grant, which only an unrestricted granter may make. There is no implicit form: an entry without `capabilities`, or with an empty `grants` list, is malformed and MUST be refused. A non-additive grant outside the role's ceiling is refused when written, never accepted with the capability silently dropped; a capability the consumer does not recognise is never treated as granted. Producers SHOULD NOT list the same (capability, resource) pair twice; a consumer MAY refuse a list that does.\"\n },\n \"createdAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"createdBy\": {\n \"description\": \"VID of the party that originally wrote this entry.\",\n \"type\": \"string\"\n },\n \"delegatedBy\": {\n \"description\": \"VID of the granter whose authority this entry was delegated from and is bounded by. The entry MUST NOT hold authority the granter did not hold when it was written, and MUST NOT retain authority the granter has since lost, so a maintainer re-evaluates it when the granter's own entry narrows or is removed. Distinct from `createdBy`, which records who wrote the entry: the two differ where an entry is written on a granter's behalf (for example after an N-of-M approval, or by an offline operator). Set by the maintainer from the granter it authorized; absent on an entry that derives from no granter's authority (the first administrator, an operator-written recovery entry).\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"expiresAt\": {\n \"description\": \"Optional time after which the entry confers no authority. Evaluated at every authorization decision, not only when a session is established.\",\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1. Reverse-DNS-namespaced; consumers MUST ignore unrecognized namespaces. An extension member MUST NOT be interpreted as conferring authority.\"\n },\n \"keys\": {\n \"$ref\": \"#/$defs/KeyScope\",\n \"description\": \"REQUIRED explicit key scope: which keys this subject may invoke the maintainer's signing oracle on. Exactly one of `{\\\"scope\\\": \\\"all\\\"}` (every key the entry's act scope reaches), `{\\\"scope\\\": \\\"none\\\"}` (no keys), or `{\\\"scope\\\": \\\"listed\\\", \\\"keys\\\": [...]}` with at least one key identifier. INTERSECTS WITH `act` — it can only narrow, never widen: a listed key that lies outside the entry's act scope remains unreachable, exactly as if it were not listed. There is no implicit form: an entry without `keys`, or with an empty `keys` list, is malformed and MUST be refused. A maintainer that operates no signing oracle states `{\\\"scope\\\": \\\"none\\\"}`. Replaces 0.1's `allowedKeys`, whose absence meant every key.\"\n },\n \"label\": {\n \"description\": \"Optional human-readable label. Confers nothing.\",\n \"maxLength\": 256,\n \"type\": \"string\"\n },\n \"role\": {\n \"description\": \"Opaque role identifier interpreted by the ACL maintainer. A role is a CEILING, never a grant: it bounds the capabilities the entry may hold and never adds to them. A consumer that does not recognise the role MUST treat the entry as conferring no authority and MUST NOT fall back to a default role. Act scope and role are independent members; a consumer MUST NOT compute either from the other.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"stepUp\": {\n \"additionalProperties\": false,\n \"description\": \"Per-entry authentication step-up configuration, consumed by the ACL maintainer when it gates an operation behind a step-up (see auth/step-up/policy). ADDITIVE-ONLY: a per-entry setting MAY raise the assurance required of this subject above the maintainer's system-wide floor, but MUST NOT lower it. The maintainer resolves the effective requirement as the strictest of (system floor, this entry). Carried forward from 0.1 unchanged.\",\n \"properties\": {\n \"approver\": {\n \"description\": \"VID authorized to ratify step-up for this subject — the `recipient` the maintainer addresses an auth/step-up/approve-request to (e.g. the holder's mobile authenticator or browser companion). Absent → the subject is its own approver (mode `self`) when it holds a usable authenticator; if neither an `approver` nor a self authenticator exists, no step-up method is available for this subject and the maintainer's fail-closed rule applies.\",\n \"type\": \"string\"\n },\n \"require\": {\n \"description\": \"Minimum step-up mode this subject MUST satisfy for gated operations, raising the system floor. `self` = the subject re-authenticates its own session; `delegated` = a separate `approver` MUST ratify. Omitted → the system floor applies unchanged. A value weaker than the resolved floor is ignored (additive-only).\",\n \"enum\": [\n \"self\",\n \"delegated\"\n ],\n \"type\": \"string\"\n }\n },\n \"type\": \"object\"\n },\n \"subject\": {\n \"description\": \"VID of the party in the ACL. Compared by exact string equality (SPEC.md §4.8); producers SHOULD emit canonical form.\",\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"updatedAt\": {\n \"format\": \"date-time\",\n \"type\": \"string\"\n },\n \"updatedBy\": {\n \"description\": \"VID of the party that last modified this entry.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"subject\",\n \"role\",\n \"act\",\n \"keys\",\n \"capabilities\"\n ],\n \"title\": \"AclEntry\",\n \"type\": \"object\"\n },\n \"ApproveCapabilityScope\": {\n \"description\": \"An explicit statement of the capabilities a subject may approve. Exactly one of `ceiling` (the role's full approve ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityRef.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/CapabilityScopeCeiling\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/ApproveCapabilityScopeListed\"\n }\n ],\n \"title\": \"ApproveCapabilityScope\"\n },\n \"ApproveCapabilityScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed capabilities, intersected with the role's approve ceiling where the maintainer's roles define one.\",\n \"properties\": {\n \"grants\": {\n \"description\": \"Non-empty list of approvable capabilities. An empty array is invalid.\",\n \"items\": {\n \"$ref\": \"#/$defs/CapabilityRef\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"grants\"\n ],\n \"title\": \"ApproveCapabilityScopeListed\",\n \"type\": \"object\"\n },\n \"AuthorityScope\": {\n \"description\": \"An explicit authority scope — used for both the act scope and the approve scope of an entry. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `contexts` with a NON-EMPTY list. The empty list is not a fourth shape: it is invalid, so a serializer that drops or empties the list produces a document that fails validation rather than one that silently means something else.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/AuthorityScopeAll\"\n },\n {\n \"$ref\": \"#/$defs/AuthorityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/AuthorityScopeContexts\"\n }\n ],\n \"title\": \"AuthorityScope\"\n },\n \"AuthorityScopeAll\": {\n \"additionalProperties\": false,\n \"description\": \"Unrestricted: every context the maintainer holds, present and future. On the act axis this is a super-administrator (or, at a maintainer without contexts, an entry whose authority is not narrowed by location).\",\n \"properties\": {\n \"scope\": {\n \"const\": \"all\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"AuthorityScopeAll\",\n \"type\": \"object\"\n },\n \"AuthorityScopeContexts\": {\n \"additionalProperties\": false,\n \"description\": \"The named contexts and, where the maintainer's contexts are hierarchical, every descendant of them — and nowhere else. `contexts` MUST carry at least one path.\",\n \"properties\": {\n \"contexts\": {\n \"description\": \"Non-empty set of context paths. An empty array is invalid (it is neither `all` nor `none`).\",\n \"items\": {\n \"$ref\": \"#/$defs/ContextPath\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"scope\": {\n \"const\": \"contexts\"\n }\n },\n \"required\": [\n \"scope\",\n \"contexts\"\n ],\n \"title\": \"AuthorityScopeContexts\",\n \"type\": \"object\"\n },\n \"AuthorityScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No authority on this axis. Stated, not implied: `none` is how an entry says it may not act (a least-privilege approver) or may not approve.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"AuthorityScopeNone\",\n \"type\": \"object\"\n },\n \"Capability\": {\n \"description\": \"Opaque identifier of one administrative power in the maintainer's capability registry — lowercase dot-separated segments (e.g. `keys.sign`, `vtc.roles.assign`, `git.repo.manage`). A consumer MUST NOT treat a capability it does not recognise as granted.\",\n \"maxLength\": 128,\n \"minLength\": 1,\n \"pattern\": \"^[a-z][a-z0-9-]*(\\\\.[a-z0-9-]+)*$\",\n \"title\": \"Capability\",\n \"type\": \"string\"\n },\n \"CapabilityGrant\": {\n \"additionalProperties\": false,\n \"description\": \"A capability held by an entry, optionally qualified by a resource, optionally marked additive. A qualified grant confers nothing without a live entry for the same subject, and is bounded as delegated authority is.\",\n \"properties\": {\n \"additive\": {\n \"description\": \"`true` declares an ADDITIVE grant: a capability no role implies, granted to this entry beside its role rather than through it, and therefore not intersected with the role's ceiling. Granting one requires unrestricted act authority (`act: {scope: all}`) of the granter, and an entry never acquires one by virtue of its role. Absent or `false` → an ordinary grant, intersected with the role's ceiling, and refused when written if it lies outside it. A consumer MUST refuse `additive: true` on a capability the role's ceiling already includes, so that the flag cannot be used to make an ordinary capability survive a later role change.\",\n \"type\": \"boolean\"\n },\n \"capability\": {\n \"$ref\": \"#/$defs/Capability\"\n },\n \"resource\": {\n \"$ref\": \"#/$defs/ResourceQualifier\",\n \"description\": \"Optional qualifier. Absent covers every resource of the capability's kind.\"\n }\n },\n \"required\": [\n \"capability\"\n ],\n \"title\": \"CapabilityGrant\",\n \"type\": \"object\"\n },\n \"CapabilityRef\": {\n \"additionalProperties\": false,\n \"description\": \"A capability, optionally qualified by a resource. Used where a capability is named but not granted — a role's ceiling, a role's approve ceiling, an entry's approvable capabilities. An unqualified reference covers every resource of the capability's kind.\",\n \"properties\": {\n \"capability\": {\n \"$ref\": \"#/$defs/Capability\"\n },\n \"resource\": {\n \"$ref\": \"#/$defs/ResourceQualifier\",\n \"description\": \"Optional qualifier. Absent covers every resource of the capability's kind.\"\n }\n },\n \"required\": [\n \"capability\"\n ],\n \"title\": \"CapabilityRef\",\n \"type\": \"object\"\n },\n \"CapabilityScope\": {\n \"description\": \"An explicit statement of the capabilities an entry holds. Exactly one of three shapes, discriminated by `scope`: `ceiling` (the role's full ceiling), `none`, or `listed` with a NON-EMPTY list of CapabilityGrant. The empty list is invalid, not a fourth shape.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/CapabilityScopeCeiling\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/CapabilityScopeListed\"\n }\n ],\n \"title\": \"CapabilityScope\"\n },\n \"CapabilityScopeCeiling\": {\n \"additionalProperties\": false,\n \"description\": \"The role's full ceiling on this axis, unnarrowed: what the role admits, the entry holds (or, for approvable capabilities, may approve). Stated, not implied — it is the explicit spelling of \\\"no narrowing\\\".\",\n \"properties\": {\n \"scope\": {\n \"const\": \"ceiling\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"CapabilityScopeCeiling\",\n \"type\": \"object\"\n },\n \"CapabilityScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed grants: (role ceiling ∩ non-additive grants) ∪ additive grants.\",\n \"properties\": {\n \"grants\": {\n \"description\": \"Non-empty list of capability grants. An empty array is invalid (it is neither `ceiling` nor `none`).\",\n \"items\": {\n \"$ref\": \"#/$defs/CapabilityGrant\"\n },\n \"minItems\": 1,\n \"type\": \"array\"\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"grants\"\n ],\n \"title\": \"CapabilityScopeListed\",\n \"type\": \"object\"\n },\n \"CapabilityScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No capabilities on this axis.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"CapabilityScopeNone\",\n \"type\": \"object\"\n },\n \"ContextPath\": {\n \"description\": \"Opaque identifier of one of the maintainer's contexts, compared by the maintainer's own ancestry predicate. Its grammar is the maintainer's.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"ContextPath\",\n \"type\": \"string\"\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 \"KeyScope\": {\n \"description\": \"An explicit key scope. Exactly one of three shapes, discriminated by `scope`: `all`, `none`, or `listed` with a NON-EMPTY list of key identifiers. The empty list is invalid, not a fourth shape.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/KeyScopeAll\"\n },\n {\n \"$ref\": \"#/$defs/KeyScopeNone\"\n },\n {\n \"$ref\": \"#/$defs/KeyScopeListed\"\n }\n ],\n \"title\": \"KeyScope\"\n },\n \"KeyScopeAll\": {\n \"additionalProperties\": false,\n \"description\": \"Every key the entry's act scope reaches.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"all\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"KeyScopeAll\",\n \"type\": \"object\"\n },\n \"KeyScopeListed\": {\n \"additionalProperties\": false,\n \"description\": \"Exactly the listed keys, intersected with the entry's act scope.\",\n \"properties\": {\n \"keys\": {\n \"description\": \"Non-empty set of key identifiers. An empty array is invalid (it is neither `all` nor `none`).\",\n \"items\": {\n \"maxLength\": 512,\n \"minLength\": 1,\n \"type\": \"string\"\n },\n \"minItems\": 1,\n \"type\": \"array\",\n \"uniqueItems\": true\n },\n \"scope\": {\n \"const\": \"listed\"\n }\n },\n \"required\": [\n \"scope\",\n \"keys\"\n ],\n \"title\": \"KeyScopeListed\",\n \"type\": \"object\"\n },\n \"KeyScopeNone\": {\n \"additionalProperties\": false,\n \"description\": \"No keys.\",\n \"properties\": {\n \"scope\": {\n \"const\": \"none\"\n }\n },\n \"required\": [\n \"scope\"\n ],\n \"title\": \"KeyScopeNone\",\n \"type\": \"object\"\n },\n \"NarrowAct\": {\n \"additionalProperties\": false,\n \"description\": \"Narrow the entry's act scope to `act`, which MUST be strictly narrower than the stored act scope (a subset of its contexts, or `none`). The entry, and every other axis of it, remains.\",\n \"properties\": {\n \"act\": {\n \"$ref\": \"#/$defs/AuthorityScope\",\n \"description\": \"The resulting act scope, in the explicit form. Stating the result rather than a list of contexts to remove means the producer and the maintainer cannot disagree about what remains.\"\n },\n \"kind\": {\n \"const\": \"act\"\n }\n },\n \"required\": [\n \"kind\",\n \"act\"\n ],\n \"title\": \"NarrowAct\",\n \"type\": \"object\"\n },\n \"ResourceQualifier\": {\n \"description\": \"Opaque qualifier naming the part of the maintainer's resources a capability applies to (e.g. `git-ns:github.com/acme`, `git-repo:github.com/acme/r#4211`, `policy:join`). Its grammar and containment rule are the maintainer's: a qualified capability covers the named resource and the resources inside it. A qualifier MUST NOT be read as widening the entry's act scope.\",\n \"maxLength\": 512,\n \"minLength\": 1,\n \"title\": \"ResourceQualifier\",\n \"type\": \"string\"\n },\n \"Response\": {\n \"$anchor\": \"response\",\n \"additionalProperties\": false,\n \"description\": \"The success response to an acl/revoke/0.2 request. Carried in a Trust Task document whose type is https://trusttasks.org/spec/acl/revoke/0.2#response.\",\n \"properties\": {\n \"entry\": {\n \"description\": \"null for a removal; the resulting AclEntry for an act-scope narrowing.\",\n \"oneOf\": [\n {\n \"type\": \"null\"\n },\n {\n \"$ref\": \"#/$defs/AclEntry\"\n }\n ]\n },\n \"ext\": {\n \"$ref\": \"#/$defs/Ext\",\n \"description\": \"Ecosystem-defined extension members per SPEC.md §4.5.1.\"\n }\n },\n \"required\": [\n \"entry\"\n ],\n \"title\": \"ACL Revoke 0.2 — response payload\",\n \"type\": \"object\"\n },\n \"Revocation\": {\n \"description\": \"Exactly one of: `{\\\"kind\\\": \\\"entry\\\"}` — remove the entry entirely; `{\\\"kind\\\": \\\"act\\\", \\\"act\\\": AuthorityScope}` — replace the entry's act scope with the stated, strictly narrower one, keeping the entry.\",\n \"oneOf\": [\n {\n \"$ref\": \"#/$defs/RevokeEntry\"\n },\n {\n \"$ref\": \"#/$defs/NarrowAct\"\n }\n ],\n \"title\": \"Revocation\"\n },\n \"RevokeEntry\": {\n \"additionalProperties\": false,\n \"description\": \"Remove the subject's entry entirely.\",\n \"properties\": {\n \"kind\": {\n \"const\": \"entry\"\n }\n },\n \"required\": [\n \"kind\"\n ],\n \"title\": \"RevokeEntry\",\n \"type\": \"object\"\n }\n },\n \"$ref\": \"#/$defs/Response\",\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\"\n}\n",
);
}
impl crate::RequestPayload for Payload {
type Response = Response;
}
/// The extended error codes this specification declares (SPEC §7.3 item 9,
/// §8.5), in declaration order. Empty when it declares none.
pub const ERROR_CODES: &[crate::DeclaredErrorCode] = &[
error_codes::SUBJECT_NOT_PRESENT,
error_codes::LAST_AUTHORITY_PROTECTED,
error_codes::NOT_NARROWING,
error_codes::INVALID_ACT_SCOPE,
];
/// One constant per extended error code this specification declares
/// (SPEC §7.3 item 9), named for its local part.
///
/// Emit these rather than a string literal: the code is read from the
/// specification, so it cannot name a code the specification never
/// declared.
pub mod error_codes {
/// `acl/revoke:subjectNotPresent`
///
/// The subject named in the payload is not currently in the ACL.
///
/// Declared `retryable: false`.
pub const SUBJECT_NOT_PRESENT: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "acl/revoke:subjectNotPresent",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `acl/revoke:lastAuthorityProtected`
///
/// The revocation would leave the ACL with no party able to perform a privileged operation; the maintainer's policy forbids it.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const LAST_AUTHORITY_PROTECTED: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "acl/revoke:lastAuthorityProtected",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"protectedRole\":{\"type\":\"string\"},\"remainingHolders\":{\"items\":{\"type\":\"string\"},\"type\":\"array\"}},\"type\":\"object\"}",
),
};
/// `acl/revoke:notNarrowing`
///
/// The stated act scope is not strictly narrower than the entry's stored act scope. Widening, or restating, is acl/update/0.2.
///
/// Declared `retryable: false`.
pub const NOT_NARROWING: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "acl/revoke:notNarrowing",
retryable: false,
details_schema: ::core::option::Option::None,
};
/// `acl/revoke:invalidActScope`
///
/// The stated act scope names a context the maintainer does not hold, or uses the `contexts` shape at a maintainer without contexts.
///
/// Declared `retryable: false`.
/// Declares a `detailsSchema` for the error's `details` member.
pub const INVALID_ACT_SCOPE: crate::DeclaredErrorCode = crate::DeclaredErrorCode {
code: "acl/revoke:invalidActScope",
retryable: false,
details_schema: ::core::option::Option::Some(
"{\"additionalProperties\":false,\"properties\":{\"offendingContexts\":{\"items\":{\"type\":\"string\"},\"type\":\"array\"}},\"type\":\"object\"}",
),
};
}