Files
clawmates/crates/cm-domain/tests/ids_and_roles.rs
T
Omar SobhandClaude Fable 5 add4f79fed Rebrand: TeamClaw -> Clawmates (clawmates.work)
Full-depth rename per the approved plan; the 'claw' product vocabulary
(claws, /claws routes, clawId, Claw Chat) stays — it is now the brand.

- Display brand: Clawmates (manifest, titles, hero, login/rail logo
  'clawmates'); default host app.clawmates.work; registry
  ghcr.io/clawmates
- Crates tc-* -> cm-* (16 crates + all imports); binaries
  clawmates-server/broker/bundler; images clawmates/*; env prefix
  CLAWMATES_* (+ CM_TEST_DATABASE_URL / CM_LIVE_LLM); config
  clawmates.toml; helm chart deploy/helm/clawmates with clawmates-*
  resources; db names clawmates*; sockets /run/clawmates; cookie
  cm_session; kind cluster clawmates-test; seccomp node profile
  clawmates-agent-profile.json
- All 9 Playwright brand assertions updated in lockstep; historical
  spec document left untouched as the only remaining 'TeamClaw'
- Local env migrated: dev pg clawmates-dev-pg/clawmates_dev, shared
  test server clawmates-test-pg, kind cluster recreated with image +
  profile, compose images rebuilt under clawmates/*

Verified end to end: 161 Rust + 68 frontend tests, 29 Playwright
journeys, 4 live kind tests, helm/install/LOC/placeholder gates, and
the clean-room install rehearsal serving the clawmates login page from
a signed bundle of the rebuilt images.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-06-10 12:31:25 -05:00

89 lines
2.6 KiB
Rust

use std::str::FromStr;
use cm_domain::{AccessPolicy, AgentId, AgentScope, GatedCategory, HumanScope, Role, UserId};
#[test]
fn ids_display_as_uuid_and_parse_back() {
let id = AgentId::new();
let parsed = AgentId::from_str(&id.to_string()).unwrap();
assert_eq!(parsed, id);
}
#[test]
fn new_ids_are_unique_and_v7() {
let a = UserId::new();
let b = UserId::new();
assert_ne!(a, b);
assert_eq!(a.as_uuid().get_version_num(), 7);
}
#[test]
fn distinct_id_types_serialize_as_plain_uuid_strings() {
let id = AgentId::new();
let json = serde_json::to_string(&id).unwrap();
assert_eq!(json, format!("\"{id}\""));
}
#[test]
fn role_serde_uses_lowercase() {
assert_eq!(serde_json::to_string(&Role::Owner).unwrap(), "\"owner\"");
assert_eq!(serde_json::to_string(&Role::Member).unwrap(), "\"member\"");
let r: Role = serde_json::from_str("\"owner\"").unwrap();
assert_eq!(r, Role::Owner);
}
#[test]
fn gated_categories_cover_spec_section_15() {
// The six gated categories are fixed by spec §15; serde names are the
// wire contract with the frontend approval queue.
let all = GatedCategory::ALL;
assert_eq!(all.len(), 6);
let names: Vec<String> = all
.iter()
.map(|c| serde_json::to_string(c).unwrap())
.collect();
assert_eq!(
names,
vec![
"\"outbound_message\"",
"\"secret_sharing\"",
"\"access_change\"",
"\"financial_transaction\"",
"\"file_deletion\"",
"\"infra_access_grant\"",
]
);
}
#[test]
fn default_access_policy_is_entire_team_and_any_claw() {
let policy = AccessPolicy::default();
assert_eq!(policy.humans, HumanScope::EntireTeam);
assert_eq!(policy.agents, AgentScope::Any);
}
#[test]
fn specific_scopes_carry_member_lists() {
let user = UserId::new();
let agent = AgentId::new();
let policy = AccessPolicy {
humans: HumanScope::Specific(vec![user]),
agents: AgentScope::Specific(vec![agent]),
};
let json = serde_json::to_value(&policy).unwrap();
assert_eq!(json["humans"]["mode"], "specific");
assert_eq!(json["humans"]["ids"][0], user.to_string());
assert_eq!(json["agents"]["mode"], "specific");
assert_eq!(json["agents"]["ids"][0], agent.to_string());
let back: AccessPolicy = serde_json::from_value(json).unwrap();
assert_eq!(back, policy);
}
#[test]
fn entire_team_scope_serializes_with_mode_tag() {
let policy = AccessPolicy::default();
let json = serde_json::to_value(&policy).unwrap();
assert_eq!(json["humans"]["mode"], "entire_team");
assert_eq!(json["agents"]["mode"], "any");
}