#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActionCategory {
Dml,
Ddl,
Schema,
Function,
Mgmt,
Policy,
Admin,
Config,
Vault,
Wildcard,
Ai,
Other,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LifecycleState {
Active,
Deprecated {
replacement: Option<&'static str>,
since_version: &'static str,
},
Removed,
}
#[derive(Debug, Clone)]
pub struct ActionEntry {
pub name: &'static str,
pub category: ActionCategory,
pub lifecycle_state: LifecycleState,
pub gates_description: &'static str,
}
pub const ACTIONS: &[ActionEntry] = &[
ActionEntry {
name: "select",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "read rows from a collection",
},
ActionEntry {
name: "write",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "any mutating DML (insert/update/delete)",
},
ActionEntry {
name: "insert",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "insert rows into a collection",
},
ActionEntry {
name: "update",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "update rows in a collection",
},
ActionEntry {
name: "delete",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "delete rows from a collection",
},
ActionEntry {
name: "truncate",
category: ActionCategory::Dml,
lifecycle_state: LifecycleState::Active,
gates_description: "truncate a collection",
},
ActionEntry {
name: "references",
category: ActionCategory::Schema,
lifecycle_state: LifecycleState::Active,
gates_description: "declare a foreign key referencing a table",
},
ActionEntry {
name: "execute",
category: ActionCategory::Function,
lifecycle_state: LifecycleState::Active,
gates_description: "execute a stored function",
},
ActionEntry {
name: "usage",
category: ActionCategory::Schema,
lifecycle_state: LifecycleState::Active,
gates_description: "use a schema namespace",
},
ActionEntry {
name: "grant",
category: ActionCategory::Mgmt,
lifecycle_state: LifecycleState::Active,
gates_description: "grant privileges to another principal",
},
ActionEntry {
name: "revoke",
category: ActionCategory::Mgmt,
lifecycle_state: LifecycleState::Active,
gates_description: "revoke privileges from another principal",
},
ActionEntry {
name: "create",
category: ActionCategory::Ddl,
lifecycle_state: LifecycleState::Active,
gates_description: "create a database object",
},
ActionEntry {
name: "drop",
category: ActionCategory::Ddl,
lifecycle_state: LifecycleState::Active,
gates_description: "drop a database object",
},
ActionEntry {
name: "alter",
category: ActionCategory::Ddl,
lifecycle_state: LifecycleState::Active,
gates_description: "alter a database object",
},
ActionEntry {
name: "policy:put",
category: ActionCategory::Policy,
lifecycle_state: LifecycleState::Active,
gates_description: "create or update a managed policy document",
},
ActionEntry {
name: "policy:drop",
category: ActionCategory::Policy,
lifecycle_state: LifecycleState::Active,
gates_description: "delete a managed policy document",
},
ActionEntry {
name: "policy:attach",
category: ActionCategory::Policy,
lifecycle_state: LifecycleState::Active,
gates_description: "attach a policy to a principal",
},
ActionEntry {
name: "policy:detach",
category: ActionCategory::Policy,
lifecycle_state: LifecycleState::Active,
gates_description: "detach a policy from a principal",
},
ActionEntry {
name: "policy:simulate",
category: ActionCategory::Policy,
lifecycle_state: LifecycleState::Active,
gates_description: "run the policy simulator",
},
ActionEntry {
name: "kv:invalidate",
category: ActionCategory::Other,
lifecycle_state: LifecycleState::Active,
gates_description: "invalidate cached KV entries",
},
ActionEntry {
name: "admin:bootstrap",
category: ActionCategory::Admin,
lifecycle_state: LifecycleState::Active,
gates_description: "execute the bootstrap workflow",
},
ActionEntry {
name: "admin:audit-read",
category: ActionCategory::Admin,
lifecycle_state: LifecycleState::Active,
gates_description: "read the platform audit log",
},
ActionEntry {
name: "admin:reload",
category: ActionCategory::Admin,
lifecycle_state: LifecycleState::Active,
gates_description: "reload runtime configuration",
},
ActionEntry {
name: "admin:lease-promote",
category: ActionCategory::Admin,
lifecycle_state: LifecycleState::Active,
gates_description: "promote a standby instance via lease handoff",
},
ActionEntry {
name: "config:read",
category: ActionCategory::Config,
lifecycle_state: LifecycleState::Active,
gates_description: "read runtime configuration values",
},
ActionEntry {
name: "config:write",
category: ActionCategory::Config,
lifecycle_state: LifecycleState::Active,
gates_description: "mutate runtime configuration values",
},
ActionEntry {
name: "config:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any runtime configuration verb",
},
ActionEntry {
name: "vault:read_metadata",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Active,
gates_description: "read vault entry metadata (no plaintext)",
},
ActionEntry {
name: "vault:read",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Active,
gates_description: "reveal vault entry plaintext",
},
ActionEntry {
name: "vault:write",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Active,
gates_description: "write or rotate vault entries",
},
ActionEntry {
name: "vault:unseal",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Active,
gates_description: "unseal the vault master key for this session",
},
ActionEntry {
name: "vault:unseal_history",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Deprecated {
replacement: Some("vault:read_metadata"),
since_version: "0.5.0",
},
gates_description: "read the vault unseal-event audit trail",
},
ActionEntry {
name: "vault:purge",
category: ActionCategory::Vault,
lifecycle_state: LifecycleState::Active,
gates_description: "purge (destructively remove) vault entries",
},
ActionEntry {
name: "evidence:export",
category: ActionCategory::Other,
lifecycle_state: LifecycleState::Active,
gates_description: "export evidence bundles",
},
ActionEntry {
name: "evidence:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any evidence-pipeline verb",
},
ActionEntry {
name: "red.registry:register",
category: ActionCategory::Other,
lifecycle_state: LifecycleState::Active,
gates_description: "register a new managed-config schema",
},
ActionEntry {
name: "red.registry:supersede",
category: ActionCategory::Other,
lifecycle_state: LifecycleState::Active,
gates_description: "supersede an existing managed-config schema",
},
ActionEntry {
name: "red.registry:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any registry verb",
},
ActionEntry {
name: "*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any action (escape hatch — audit usage carefully)",
},
ActionEntry {
name: "admin:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any admin verb",
},
ActionEntry {
name: "vault:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any vault verb",
},
ActionEntry {
name: "kv:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any KV verb",
},
ActionEntry {
name: "policy:*",
category: ActionCategory::Wildcard,
lifecycle_state: LifecycleState::Active,
gates_description: "any policy lifecycle verb",
},
];
pub fn is_valid_action(name: &str) -> bool {
ACTIONS
.iter()
.any(|e| e.name == name && !matches!(e.lifecycle_state, LifecycleState::Removed))
}
pub fn lookup(name: &str) -> Option<&'static ActionEntry> {
ACTIONS.iter().find(|e| e.name == name)
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
const HISTORICAL_ALLOWLIST: &[&str] = &[
"select",
"write",
"insert",
"update",
"delete",
"truncate",
"references",
"execute",
"usage",
"grant",
"revoke",
"create",
"drop",
"alter",
"policy:put",
"policy:drop",
"policy:attach",
"policy:detach",
"policy:simulate",
"kv:invalidate",
"admin:bootstrap",
"admin:audit-read",
"admin:reload",
"admin:lease-promote",
"config:read",
"config:write",
"config:*",
"vault:read_metadata",
"vault:read",
"vault:write",
"vault:unseal",
"vault:unseal_history",
"vault:purge",
"evidence:export",
"evidence:*",
"red.registry:register",
"red.registry:supersede",
"red.registry:*",
"*",
"admin:*",
"vault:*",
"kv:*",
"policy:*",
];
#[test]
fn no_duplicate_names() {
let mut seen = HashSet::new();
for entry in ACTIONS {
assert!(
seen.insert(entry.name),
"duplicate action name in catalog: {}",
entry.name
);
}
}
#[test]
fn covers_historical_allowlist() {
let names: HashSet<&'static str> = ACTIONS.iter().map(|e| e.name).collect();
for action in HISTORICAL_ALLOWLIST {
assert!(
names.contains(action),
"catalog missing historically-accepted action: {action}",
);
}
}
#[test]
fn historical_allowlist_still_validates() {
for action in HISTORICAL_ALLOWLIST {
assert!(
is_valid_action(action),
"action {action} was accepted before the catalog and must still validate",
);
}
}
#[test]
fn has_at_least_one_deprecated_entry() {
let count = ACTIONS
.iter()
.filter(|e| matches!(e.lifecycle_state, LifecycleState::Deprecated { .. }))
.count();
assert!(
count >= 1,
"catalog must demonstrate the Deprecated lifecycle state with at least one entry",
);
}
#[test]
fn removed_entries_are_rejected() {
for entry in ACTIONS {
if matches!(entry.lifecycle_state, LifecycleState::Removed) {
assert!(
!is_valid_action(entry.name),
"Removed entry {} must not validate",
entry.name,
);
}
}
}
#[test]
fn lookup_finds_known_entries() {
assert!(lookup("policy:put").is_some());
assert!(lookup("definitely-not-an-action").is_none());
}
}