Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
da41857
feat(team): KarsTeam standing-team primitive with charter cadence loop
Jun 28, 2026
e76ce94
feat(team): grant controller RBAC for karsteams resources
Jun 28, 2026
f9b784c
feat(team): knowledge commons — provenance-tracked team shared memory
Jun 28, 2026
44e1e1a
feat(team): operations health — autonomous-monitoring report
Jun 28, 2026
8cf739e
fix(team): make auto-launched standing runs reliable (no hard timeout)
Jun 28, 2026
f03dd35
feat(admission): envelope-write VAP — governance fields controller-wr…
Jun 28, 2026
ae6cc33
feat(receipt): record the validated launch package at the receipt hea…
Jun 28, 2026
3da56d3
feat(team): daily digest to the steering inbox (§20)
Jun 28, 2026
435ef37
feat(team): KarsSkill + KarsProfile CRDs, skill grants, profile insta…
Jun 28, 2026
fefa290
fix(team): promote uses merge-patch + charter CEL allows profile inhe…
Jun 28, 2026
39fa94e
fix(team): meet public conformance gates
pallakatos Sep 3, 2026
adc091f
Merge updated core governance base
pallakatos Sep 4, 2026
5aa9131
Merge existing-AKS adoption stack
pallakatos Sep 4, 2026
067881d
Merge explicit kube-context stack
pallakatos Sep 4, 2026
4fb606c
Merge existing-cluster documentation stack
pallakatos Sep 4, 2026
957c283
Merge existing AKS values template stack
pallakatos Sep 4, 2026
9c67a69
Merge complete existing AKS prerequisites stack
pallakatos Sep 4, 2026
735076e
Merge fixed public image repository stack
pallakatos Sep 4, 2026
b2732a8
Merge npm lockfile audit stack
pallakatos Sep 4, 2026
03c7756
Merge npm bulk audit stack
pallakatos Sep 4, 2026
8fe755b
Merge stacked publication qualification
pallakatos Sep 7, 2026
ea6f578
refactor(team): route content hashes through signing provider
pallakatos Sep 7, 2026
4a8a6ff
fix(team): bind authority and preserve scoped team evidence
pallakatos Sep 7, 2026
21782f5
Integrate repaired governance APIs into team foundations
pallakatos Sep 7, 2026
41e0b84
test(team): pin authority fixtures and reject stale promotion digests
pallakatos Sep 7, 2026
ae66349
Integrate qualified governance and nil-safe admission followups
pallakatos Sep 7, 2026
3bfc99f
fix(team): qualify integrated schemas and independent test fixtures
pallakatos Sep 7, 2026
415b53c
Carry current publication guardrails through team integration
pallakatos Sep 7, 2026
44c94b2
fix(team): bound complete cadence objectives and commons history
pallakatos Sep 7, 2026
4bb5043
Carry qualified effective authority snapshot into team closure
pallakatos Sep 7, 2026
1fd9781
Preserve signed historical decisions in team governance
pallakatos Sep 7, 2026
94d5721
Carry final entry-slice compatibility through team foundations
pallakatos Sep 7, 2026
8a75f24
fix(team): use the shared degraded phase constant
pallakatos Sep 7, 2026
73094aa
Carry governance CI corrections into team qualification
pallakatos Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions controller/src/crd_validations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use crate::kars_memory::KarsMemory;
use crate::kars_receipt::KarsReceipt;
use crate::kars_sre_action::KarsSREAction;
use crate::kars_task::KarsTask;
use crate::kars_team::KarsTeam;
use crate::mcp_server::McpServer;
use crate::tool_policy::ToolPolicy;

Expand Down Expand Up @@ -641,6 +642,115 @@ pub fn kars_task_crd() -> CustomResourceDefinition {
.expect("kube-rs derive must produce a spec property on KarsTask")
}

/// Admission CEL for `KarsTeam` — the standing-team envelope must obey the same
/// anti-amplification rules as a task (tier range, ceiling <= tier, depth >= 0),
/// plus a non-empty charter (the mandate that generates the team's work).
pub fn kars_team_validations() -> Vec<ValidationRule> {
vec![
ValidationRule {
rule: "(has(self.profileRef) && size(self.charter) == 0) || (size(self.charter) > 0 && size(self.charter) <= 8192)".into(),
message: Some("spec.charter must be 1-8192 characters (or empty when spec.profileRef is set, to inherit the profile's charter)".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "self.envelope.tier >= 1 && self.envelope.tier <= 5".into(),
message: Some("spec.envelope.tier must be in 1..5".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "self.envelope.authorityCeiling >= 1 && self.envelope.authorityCeiling <= 5".into(),
message: Some("spec.envelope.authorityCeiling must be in 1..5".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "self.envelope.authorityCeiling <= self.envelope.tier".into(),
message: Some(
"spec.envelope.authorityCeiling must be <= spec.envelope.tier (a team cannot grant a member more authority than it holds)".into(),
),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "self.envelope.delegationDepth >= 0 && self.envelope.delegationDepth <= 16".into(),
message: Some("spec.envelope.delegationDepth must be in 0..16".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "!has(self.cadence) || !has(self.cadence.everyMinutes) || self.cadence.everyMinutes >= 1".into(),
message: Some("spec.cadence.everyMinutes, when set, must be >= 1".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
]
}

/// `KarsTeam` CRD — the standing-team / org primitive (design note §11).
#[must_use]
pub fn kars_team_crd() -> CustomResourceDefinition {
inject_spec_validations(KarsTeam::crd(), kars_team_validations())
.expect("kube-rs derive must produce a spec property on KarsTeam")
}

#[must_use]
pub fn kars_skill_validations() -> Vec<ValidationRule> {
vec![
ValidationRule {
rule: "size(self.version) > 0".into(),
message: Some("spec.version must be non-empty".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "size(self.summary) > 0 && size(self.summary) <= 512".into(),
message: Some("spec.summary must be 1-512 characters".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
]
}

/// `KarsSkill` CRD (§13) with admission validation.
#[must_use]
pub fn kars_skill_crd() -> CustomResourceDefinition {
inject_spec_validations(
crate::kars_skill::KarsSkill::crd(),
kars_skill_validations(),
)
.expect("kube-rs derive must produce a spec property on KarsSkill")
}

#[must_use]
pub fn kars_profile_validations() -> Vec<ValidationRule> {
vec![
ValidationRule {
rule: "size(self.charterTemplate) > 0".into(),
message: Some("spec.charterTemplate must be non-empty".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
ValidationRule {
rule: "size(self.domain) > 0".into(),
message: Some("spec.domain must be non-empty".into()),
reason: Some("FieldValueInvalid".into()),
..ValidationRule::default()
},
]
}

/// `KarsProfile` CRD (§17) with admission validation.
#[must_use]
pub fn kars_profile_crd() -> CustomResourceDefinition {
inject_spec_validations(
crate::kars_profile::KarsProfile::crd(),
kars_profile_validations(),
)
.expect("kube-rs derive must produce a spec property on KarsProfile")
}

#[must_use]
pub fn kars_receipt_validations() -> Vec<ValidationRule> {
vec![
Expand Down
14 changes: 14 additions & 0 deletions controller/src/field_managers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ pub const CLAW_EVAL: &str = "kars-controller/karseval";
/// envelope digest + lifecycle phase on status.
pub const CLAW_TASK: &str = "kars-controller/karstask";

/// `KarsTeam` reconciler — the standing-team primitive. Authors the principal +
/// member `KarsTask`s and the charter-loop task-force tasks; sole writer of
/// `KarsTeam.status`.
pub const CLAW_TEAM: &str = "kars-controller/karsteam";

/// `KarsSkill` reconciler — validates + versions reusable capability bundles.
pub const CLAW_SKILL: &str = "kars-controller/karsskill";

/// `KarsProfile` reconciler — validates team templates + instantiates teams.
pub const CLAW_PROFILE: &str = "kars-controller/karsprofile";

/// `TrustGraph` reconciler (Phase F1) — verifies signed trust edges
/// and publishes a `ConfigMap` projection to `kars-system`.
pub const TRUST_GRAPH: &str = "kars-controller/trustgraph";
Expand Down Expand Up @@ -114,6 +125,9 @@ pub const ALL_FIELD_MANAGERS: &[&str] = &[
MESH,
RECONCILER,
EGRESS_APPROVAL,
CLAW_TEAM,
CLAW_SKILL,
CLAW_PROFILE,
];

#[cfg(test)]
Expand Down
74 changes: 72 additions & 2 deletions controller/src/helm_drift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
#[cfg(test)]
use crate::crd_validations::{
a2a_agent_crd, egress_approval_crd, inference_policy_crd, kars_approval_crd, kars_eval_crd,
kars_memory_crd, kars_receipt_crd, kars_sre_action_crd, kars_task_crd, mcp_server_crd,
tool_policy_crd, trust_graph_crd,
kars_memory_crd, kars_profile_crd, kars_receipt_crd, kars_skill_crd, kars_sre_action_crd,
kars_task_crd, kars_team_crd, mcp_server_crd, tool_policy_crd, trust_graph_crd,
};

const MCP_HELM_CRD_PATH: &str = concat!(
Expand Down Expand Up @@ -72,6 +72,21 @@ const KARSTASK_HELM_CRD_PATH: &str = concat!(
"/../deploy/helm/kars/templates/crd-karstask.yaml"
);

const KARSTEAM_HELM_CRD_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../deploy/helm/kars/templates/crd-karsteam.yaml"
);

const KARSSKILL_HELM_CRD_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../deploy/helm/kars/templates/crd-karsskill.yaml"
);

const KARSPROFILE_HELM_CRD_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../deploy/helm/kars/templates/crd-karsprofile.yaml"
);

const KARSRECEIPT_HELM_CRD_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../deploy/helm/kars/templates/crd-karsreceipt.yaml"
Expand Down Expand Up @@ -299,6 +314,61 @@ mod tests {
assert_helm_matches_rust(KARSTASK_HELM_CRD_PATH, rust_crd_value, "karstask");
}

/// One-shot dumper for the karsteam CRD. Run via:
///
/// DUMP_KARSTEAM_CRD_YAML=1 cargo test --bin kars-controller \
/// helm_drift::tests::dump_karsteam_crd_yaml -- --nocapture
#[test]
fn dump_karsteam_crd_yaml() {
if std::env::var("DUMP_KARSTEAM_CRD_YAML").is_err() {
return;
}
let crd = kars_team_crd();
let yaml = serde_yaml::to_string(&crd).expect("serialize crd to YAML");
println!("---\n{yaml}");
}

#[test]
fn helm_karsteam_crd_matches_rust_schema() {
let rust_crd_value =
serde_json::to_value(kars_team_crd()).expect("rust crd serializes to JSON");
assert_helm_matches_rust(KARSTEAM_HELM_CRD_PATH, rust_crd_value, "karsteam");
}

#[test]
fn dump_karsskill_crd_yaml() {
if std::env::var("DUMP_KARSSKILL_CRD_YAML").is_err() {
return;
}
let crd = kars_skill_crd();
let yaml = serde_yaml::to_string(&crd).expect("serialize crd to YAML");
println!("---\n{yaml}");
}

#[test]
fn helm_karsskill_crd_matches_rust_schema() {
let rust_crd_value =
serde_json::to_value(kars_skill_crd()).expect("rust crd serializes to JSON");
assert_helm_matches_rust(KARSSKILL_HELM_CRD_PATH, rust_crd_value, "karsskill");
}

#[test]
fn dump_karsprofile_crd_yaml() {
if std::env::var("DUMP_KARSPROFILE_CRD_YAML").is_err() {
return;
}
let crd = kars_profile_crd();
let yaml = serde_yaml::to_string(&crd).expect("serialize crd to YAML");
println!("---\n{yaml}");
}

#[test]
fn helm_karsprofile_crd_matches_rust_schema() {
let rust_crd_value =
serde_json::to_value(kars_profile_crd()).expect("rust crd serializes to JSON");
assert_helm_matches_rust(KARSPROFILE_HELM_CRD_PATH, rust_crd_value, "karsprofile");
}

/// One-shot dumper for the karsreceipt CRD. Run via:
///
/// DUMP_KARSRECEIPT_CRD_YAML=1 cargo test --bin kars-controller \
Expand Down
Loading
Loading