From 5549c50d86790c92b1d4773d0073bb6d6e47bb64 Mon Sep 17 00:00:00 2001 From: Hare Date: Sun, 14 Jun 2026 03:52:26 +0900 Subject: [PATCH 1/3] feat: remove feature host authority API --- crates/pod/src/feature.rs | 269 +-------------------- crates/pod/src/feature/builtin/task/mod.rs | 5 +- crates/pod/src/feature/builtin/ticket.rs | 29 +-- 3 files changed, 16 insertions(+), 287 deletions(-) diff --git a/crates/pod/src/feature.rs b/crates/pod/src/feature.rs index 5c903eb7..58a8ec86 100644 --- a/crates/pod/src/feature.rs +++ b/crates/pod/src/feature.rs @@ -1,8 +1,8 @@ //! Feature contribution registry for Pod-hosted builtin/plugin modules. //! //! This module defines the Pod-side feature boundary used to collect -//! descriptor metadata, host authority requests, tool contributions, safe hook -//! contributions, background task declarations, and service declarations before +//! descriptor metadata, tool contributions, safe hook contributions, background +//! task declarations, and service declarations before //! installing them into the existing Worker/HookRegistry host surfaces. //! //! The first implementation slice is intentionally host-mediated and @@ -69,26 +69,6 @@ pub enum FeatureRuntimeKind { ExternalPlugin, } -/// Host authority requested by a feature for host-mediated operations that can -/// cross sandbox or model-context boundaries. -/// -/// Contribution declarations such as tools, hooks, background tasks, and -/// services are descriptor/package-approved host-visible contributions, not -/// host authorities. Host authority grants are additive and do not replace -/// manifest/tool permission checks. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum HostAuthority { - Filesystem, - Network, - SecretRef { id: String }, - ModelNotification, - PodManagement, - StateStore { name: String }, - TicketBackend { root: String }, - ServiceAccess { service: ServiceId }, -} - /// A safe hook contribution point exposed to feature modules. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] @@ -99,82 +79,6 @@ pub enum FeatureHookPoint { TurnEnd, } -/// Host authority request declared by a feature descriptor. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct HostAuthorityRequest { - pub authority: HostAuthority, - pub required: bool, - pub reason: String, -} - -impl HostAuthorityRequest { - pub fn required(authority: HostAuthority, reason: impl Into) -> Self { - Self { - authority, - required: true, - reason: reason.into(), - } - } - - pub fn optional(authority: HostAuthority, reason: impl Into) -> Self { - Self { - authority, - required: false, - reason: reason.into(), - } - } -} - -/// Host authority grants resolved by the host for one feature installation. -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] -pub struct HostAuthorityGrantSet { - granted: HashSet, - denied: Vec, -} - -impl HostAuthorityGrantSet { - pub fn grant_all(requests: &[HostAuthorityRequest]) -> Self { - Self { - granted: requests - .iter() - .map(|request| request.authority.clone()) - .collect(), - denied: Vec::new(), - } - } - - pub fn empty() -> Self { - Self::default() - } - - pub fn contains(&self, authority: &HostAuthority) -> bool { - self.granted.contains(authority) - } - - pub fn denied(&self) -> &[HostAuthorityDenial] { - &self.denied - } - - pub fn grant(&mut self, authority: HostAuthority) { - self.granted.insert(authority); - } - - pub fn deny(&mut self, authority: HostAuthority, reason: impl Into) { - self.granted.remove(&authority); - self.denied.push(HostAuthorityDenial { - authority, - reason: reason.into(), - }); - } -} - -/// Host-side denial of a requested feature host authority. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct HostAuthorityDenial { - pub authority: HostAuthority, - pub reason: String, -} - /// Serializable declaration of a tool contribution. The executable factory is /// carried by [`ToolContribution`] during installation. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -192,12 +96,10 @@ impl ToolDeclaration { } } -/// Executable tool contribution wrapper. Host-authority requirements are optional -/// per-tool gates for privileged host APIs, not permission to contribute a tool. +/// Executable tool contribution wrapper. pub struct ToolContribution { name: String, definition: ToolDefinition, - required_host_authorities: Vec, } impl ToolContribution { @@ -205,18 +107,9 @@ impl ToolContribution { Self { name: name.into(), definition, - required_host_authorities: Vec::new(), } } - pub fn with_required_host_authorities( - mut self, - required_host_authorities: Vec, - ) -> Self { - self.required_host_authorities = required_host_authorities; - self - } - pub fn name(&self) -> &str { &self.name } @@ -410,7 +303,6 @@ pub struct FeatureDescriptor { pub display_name: String, pub version: String, pub description: String, - pub requested_host_authorities: Vec, pub tools: Vec, pub hooks: Vec, pub background_tasks: Vec, @@ -426,7 +318,6 @@ impl FeatureDescriptor { display_name: display_name.into(), version: env!("CARGO_PKG_VERSION").into(), description: String::new(), - requested_host_authorities: Vec::new(), tools: Vec::new(), hooks: Vec::new(), background_tasks: Vec::new(), @@ -440,11 +331,6 @@ impl FeatureDescriptor { self } - pub fn with_host_authority(mut self, request: HostAuthorityRequest) -> Self { - self.requested_host_authorities.push(request); - self - } - pub fn with_tool(mut self, tool: ToolDeclaration) -> Self { self.tools.push(tool); self @@ -543,7 +429,6 @@ pub struct FeatureInstallReport { pub feature_id: FeatureId, pub runtime: FeatureRuntimeKind, pub installed: bool, - pub host_authority_grants: HostAuthorityGrantSet, pub installed_tools: Vec, pub installed_hooks: Vec, pub declared_background_tasks: Vec, @@ -554,12 +439,11 @@ pub struct FeatureInstallReport { } impl FeatureInstallReport { - fn new(descriptor: &FeatureDescriptor, host_authority_grants: HostAuthorityGrantSet) -> Self { + fn new(descriptor: &FeatureDescriptor) -> Self { Self { feature_id: descriptor.id.clone(), runtime: descriptor.runtime.clone(), installed: false, - host_authority_grants, installed_tools: Vec::new(), installed_hooks: Vec::new(), declared_background_tasks: Vec::new(), @@ -653,38 +537,14 @@ fn reject_undeclared_contribution( error } -fn require_host_authority( - host_authority_grants: &HostAuthorityGrantSet, - report: &mut FeatureInstallReport, - kind: FeatureContributionKind, - name: impl Into, - authority: &HostAuthority, -) -> Result<(), FeatureInstallError> { - if host_authority_grants.contains(authority) { - return Ok(()); - } - - let reason = format!("required host authority was not granted: {authority:?}"); - report.mark_skipped(kind, name, reason.clone()); - Err(FeatureInstallError::HostAuthorityDenied(reason)) -} - /// Model-visible durable notification sink skeleton. The first slice exposes /// the boundary without implementing a new event channel. pub struct FeatureNotificationSink<'a> { - host_authority_grants: &'a HostAuthorityGrantSet, report: &'a mut FeatureInstallReport, } impl FeatureNotificationSink<'_> { pub fn notify_model(&mut self, message: impl Into) -> Result<(), FeatureInstallError> { - require_host_authority( - self.host_authority_grants, - self.report, - FeatureContributionKind::Notification, - "notify_model", - &HostAuthority::ModelNotification, - )?; let message = message.into(); self.report.diagnostics.push(FeatureDiagnostic::warning(format!( "model notification requested during feature installation but no durable Notify host is attached: {message}" @@ -744,7 +604,6 @@ impl FeatureDiagnosticSink<'_> { pub struct ToolContributionRegistrar<'a> { feature_id: &'a FeatureId, declarations: &'a FeatureContributionDeclarations, - host_authority_grants: &'a HostAuthorityGrantSet, pending_tools: &'a mut Vec, installed_tool_names: &'a mut HashMap, report: &'a mut FeatureInstallReport, @@ -776,16 +635,6 @@ impl ToolContributionRegistrar<'_> { )); } - for authority in &contribution.required_host_authorities { - require_host_authority( - self.host_authority_grants, - self.report, - FeatureContributionKind::Tool, - model_visible_name.clone(), - authority, - )?; - } - if let Some(first) = self.installed_tool_names.get(&model_visible_name) { let error = FeatureInstallError::DuplicateToolName { tool: model_visible_name.clone(), @@ -951,7 +800,6 @@ impl FeatureServiceRegistrar<'_> { pub struct FeatureInstallContext<'a> { feature_id: &'a FeatureId, declarations: &'a FeatureContributionDeclarations, - host_authority_grants: &'a HostAuthorityGrantSet, pending_tools: &'a mut Vec, installed_tool_names: &'a mut HashMap, hook_builder: &'a mut HookRegistryBuilder, @@ -964,15 +812,10 @@ impl FeatureInstallContext<'_> { self.feature_id } - pub fn host_authority_grants(&self) -> &HostAuthorityGrantSet { - self.host_authority_grants - } - pub fn tools(&mut self) -> ToolContributionRegistrar<'_> { ToolContributionRegistrar { feature_id: self.feature_id, declarations: self.declarations, - host_authority_grants: self.host_authority_grants, pending_tools: self.pending_tools, installed_tool_names: self.installed_tool_names, report: self.report, @@ -1007,7 +850,6 @@ impl FeatureInstallContext<'_> { pub fn notifications(&mut self) -> FeatureNotificationSink<'_> { FeatureNotificationSink { - host_authority_grants: self.host_authority_grants, report: self.report, } } @@ -1107,10 +949,8 @@ impl FeatureRegistryBuilder { let mut seen_features = HashSet::new(); for (module, descriptor) in self.modules.into_iter().zip(descriptors.into_iter()) { - let host_authority_grants = - HostAuthorityGrantSet::grant_all(&descriptor.requested_host_authorities); let declarations = FeatureContributionDeclarations::from_descriptor(&descriptor); - let mut report = FeatureInstallReport::new(&descriptor, host_authority_grants.clone()); + let mut report = FeatureInstallReport::new(&descriptor); if !seen_features.insert(descriptor.id.clone()) { report.diagnostics.push(FeatureDiagnostic::error(format!( @@ -1126,13 +966,6 @@ impl FeatureRegistryBuilder { continue; } - for authority in host_authority_grants.denied() { - report.diagnostics.push(FeatureDiagnostic::warning(format!( - "host authority denied: {:?}: {}", - authority.authority, authority.reason - ))); - } - let mut required_service_failed = false; for requirement in descriptor.requires_services.iter().cloned() { if service_registry.provides(&requirement.id) { @@ -1192,7 +1025,6 @@ impl FeatureRegistryBuilder { let mut context = FeatureInstallContext { feature_id: &descriptor.id, declarations: &declarations, - host_authority_grants: &host_authority_grants, pending_tools, installed_tool_names: &mut installed_tool_names, hook_builder, @@ -1256,8 +1088,6 @@ pub enum FeatureInstallError { first_feature: String, duplicate_feature: String, }, - #[error("feature host authority denied: {0}")] - HostAuthorityDenied(String), #[error("feature install failed: {0}")] Install(String), } @@ -1335,7 +1165,7 @@ mod tests { } #[test] - fn descriptor_contributions_and_empty_host_authority_grants_are_recorded() { + fn descriptor_contributions_are_recorded() { let descriptor = FeatureDescriptor::builtin("dummy", "Dummy") .with_tool(ToolDeclaration::new("Dummy", "dummy tool")) .with_background_task(BackgroundTaskDeclaration::descriptor_only( @@ -1358,7 +1188,6 @@ mod tests { assert!(feature_report.installed); assert_eq!(feature_report.installed_tools, vec!["Dummy"]); assert_eq!(feature_report.declared_background_tasks[0].name, "daily"); - assert!(feature_report.host_authority_grants.denied().is_empty()); } #[test] @@ -1421,79 +1250,6 @@ mod tests { assert_eq!(report.reports[0].skipped[0].name, "Actual"); } - #[test] - fn tool_host_authority_requirements_use_host_authority_grants_not_contribution_declarations() { - struct HostAuthorityToolFeature { - descriptor: FeatureDescriptor, - required_host_authorities: Vec, - } - - impl FeatureModule for HostAuthorityToolFeature { - fn descriptor(&self) -> FeatureDescriptor { - self.descriptor.clone() - } - - fn install( - &self, - context: &mut FeatureInstallContext<'_>, - ) -> Result<(), FeatureInstallError> { - context.tools().register( - ToolContribution::new("NetworkTool", dummy_tool("NetworkTool")) - .with_required_host_authorities(self.required_host_authorities.clone()), - ) - } - } - - let mut hook_builder = HookRegistryBuilder::default(); - let mut pending_tools = Vec::new(); - let missing_grant = FeatureDescriptor::builtin("missing-host-authority", "Missing") - .with_tool(ToolDeclaration::new("NetworkTool", "network host API tool")); - let missing_report = FeatureRegistryBuilder::new() - .with_module(HostAuthorityToolFeature { - descriptor: missing_grant, - required_host_authorities: vec![HostAuthority::Network], - }) - .install_into_pending(&mut pending_tools, &mut hook_builder); - - assert!(pending_tools.is_empty()); - assert!(!missing_report.reports[0].installed); - assert!( - missing_report.reports[0] - .diagnostics - .iter() - .any(|diagnostic| { - diagnostic - .message - .contains("required host authority was not granted") - }) - ); - assert_eq!( - missing_report.reports[0].skipped[0].kind, - FeatureContributionKind::Tool - ); - - let granted = FeatureDescriptor::builtin("granted-host-authority", "Granted") - .with_host_authority(HostAuthorityRequest::required( - HostAuthority::Network, - "uses a host network API", - )) - .with_tool(ToolDeclaration::new("NetworkTool", "network host API tool")); - let granted_report = FeatureRegistryBuilder::new() - .with_module(HostAuthorityToolFeature { - descriptor: granted, - required_host_authorities: vec![HostAuthority::Network], - }) - .install_into_pending(&mut pending_tools, &mut hook_builder); - - assert!(granted_report.reports[0].installed); - assert!( - granted_report.reports[0] - .host_authority_grants - .contains(&HostAuthority::Network) - ); - assert_eq!(pending_tools.len(), 1); - } - #[test] fn stateful_tool_definition_is_materialized_once_for_report_and_worker() { struct StatefulToolFeature { @@ -1790,7 +1546,7 @@ mod tests { } #[test] - fn background_task_declaration_is_not_host_authority_gated() { + fn background_task_declaration_is_descriptor_contribution() { let descriptor = FeatureDescriptor::builtin("background", "Background") .with_background_task(BackgroundTaskDeclaration::descriptor_only( "declared-task", @@ -1811,7 +1567,7 @@ mod tests { } #[test] - fn service_provider_declaration_is_not_host_authority_gated() { + fn service_provider_declaration_is_descriptor_contribution() { let service = ServiceId::builtin("declared-service"); let descriptor = FeatureDescriptor::builtin("service", "Service").with_provided_service( ServiceDeclaration::new(service.clone(), "1", "descriptor contribution"), @@ -1829,7 +1585,7 @@ mod tests { } #[test] - fn builtin_internal_task_feature_descriptor_has_exact_tools_hooks_and_no_host_authorities() { + fn builtin_internal_task_feature_descriptor_has_exact_tools_hooks() { let descriptor = builtin::task_tools_feature().descriptor(); let tool_names: Vec<_> = descriptor .tools @@ -1845,7 +1601,6 @@ mod tests { assert_eq!(descriptor.id.as_str(), "builtin:task-tools"); assert_eq!(descriptor.runtime, FeatureRuntimeKind::Builtin); - assert!(descriptor.requested_host_authorities.is_empty()); assert_eq!( hook_points, vec![FeatureHookPoint::PreRequest, FeatureHookPoint::PreToolCall] @@ -1860,7 +1615,7 @@ mod tests { } #[test] - fn builtin_internal_task_feature_installs_declared_tools_without_host_authorities() { + fn builtin_internal_task_feature_installs_declared_tools() { let mut hook_builder = HookRegistryBuilder::default(); let mut pending_tools = Vec::new(); let mut builder = FeatureRegistryBuilder::new(); @@ -1882,10 +1637,6 @@ mod tests { assert_eq!(report.reports.len(), 1); assert!(report.reports[0].installed); - assert_eq!( - report.reports[0].host_authority_grants, - HostAuthorityGrantSet::empty() - ); assert!(report.reports[0].skipped.is_empty()); assert!(report.reports[0].diagnostics.is_empty()); assert_eq!(report.reports[0].installed_hooks.len(), 2); diff --git a/crates/pod/src/feature/builtin/task/mod.rs b/crates/pod/src/feature/builtin/task/mod.rs index d6d8c725..abf6741d 100644 --- a/crates/pod/src/feature/builtin/task/mod.rs +++ b/crates/pod/src/feature/builtin/task/mod.rs @@ -35,9 +35,8 @@ const TASK_MANAGEMENT_TOOL_NAMES: [&str; 2] = ["TaskCreate", "TaskUpdate"]; /// /// The returned module contributes `TaskCreate`, `TaskUpdate`, `TaskGet`, and /// `TaskList` through descriptor-approved tool registration, plus built-in hooks -/// that maintain Task-reminder state. It does not request sandbox/external-plugin -/// host authorities; normal ToolRegistry and PreToolCall permission policy still -/// applies at call time. +/// that maintain Task-reminder state. Normal ToolRegistry and PreToolCall +/// permission policy still applies at call time. pub fn task_tools_feature() -> TaskFeature { TaskFeature::new() } diff --git a/crates/pod/src/feature/builtin/ticket.rs b/crates/pod/src/feature/builtin/ticket.rs index f9cf2f05..c3bfd804 100644 --- a/crates/pod/src/feature/builtin/ticket.rs +++ b/crates/pod/src/feature/builtin/ticket.rs @@ -18,14 +18,13 @@ use ticket::{ use crate::feature::{ FeatureDescriptor, FeatureDiagnostic, FeatureInstallContext, FeatureInstallError, - FeatureModule, HostAuthority, HostAuthorityRequest, ToolContribution, ToolDeclaration, + FeatureModule, ToolContribution, ToolDeclaration, }; const FEATURE_ID: &str = "ticket"; const FEATURE_NAME: &str = "Ticket tools"; const FEATURE_DESCRIPTION: &str = "Typed local Ticket work-item operations over a bounded backend root. \ The tools operate through the ticket crate backend and do not grant generic filesystem write scope."; -const AUTHORITY_REASON: &str = "Use a configured local Ticket backend root for typed work-item operations without generic filesystem write authority."; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TicketFeatureAccess { @@ -150,12 +149,6 @@ impl TicketFeature { names } - fn authority(&self) -> HostAuthority { - HostAuthority::TicketBackend { - root: self.backend_root.display().to_string(), - } - } - fn usable_backend_root(&self) -> Result { let root = self .backend_root @@ -171,11 +164,7 @@ impl TicketFeature { impl FeatureModule for TicketFeature { fn descriptor(&self) -> FeatureDescriptor { let mut descriptor = FeatureDescriptor::builtin(FEATURE_ID, FEATURE_NAME) - .with_description(FEATURE_DESCRIPTION) - .with_host_authority(HostAuthorityRequest::required( - self.authority(), - AUTHORITY_REASON, - )); + .with_description(FEATURE_DESCRIPTION); let enabled_tool_names = self.enabled_tool_names(); for name in &enabled_tool_names { descriptor = descriptor.with_tool(ToolDeclaration::new( @@ -207,7 +196,6 @@ impl FeatureModule for TicketFeature { return Ok(()); } }; - let authority = self.authority(); let backend = LocalTicketBackend::new(usable_root) .with_record_language(self.record_language.as_deref()); let allowed_tool_names = self.enabled_tool_names(); @@ -221,10 +209,7 @@ impl FeatureModule for TicketFeature { { continue; } - tools.register( - ToolContribution::new(name, definition) - .with_required_host_authorities(vec![authority.clone()]), - )?; + tools.register(ToolContribution::new(name, definition))?; } Ok(()) } @@ -284,7 +269,7 @@ mod tests { } #[test] - fn descriptor_declares_ticket_tools_and_backend_authority() { + fn descriptor_declares_ticket_tools() { let temp = TempDir::new().unwrap(); let feature = ticket_tools_feature(temp.path()); let descriptor = feature.descriptor(); @@ -299,11 +284,6 @@ mod tests { .collect::>(), TICKET_TOOL_NAMES ); - assert_eq!(descriptor.requested_host_authorities.len(), 1); - assert!(matches!( - descriptor.requested_host_authorities[0].authority, - HostAuthority::TicketBackend { .. } - )); } #[test] @@ -321,7 +301,6 @@ mod tests { .collect::>(), TICKET_READ_ONLY_TOOL_NAMES ); - assert_eq!(descriptor.requested_host_authorities.len(), 1); } #[test] From 3faf7d7bd12ac3cd9ec8275ed0ebf1718a43dba4 Mon Sep 17 00:00:00 2001 From: Hare Date: Sun, 14 Jun 2026 03:53:11 +0900 Subject: [PATCH 2/3] ticket: report host authority cleanup --- .yoi/tickets/00001KV0SP0TY/item.md | 2 +- .yoi/tickets/00001KV0SP0TY/thread.md | 35 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.yoi/tickets/00001KV0SP0TY/item.md b/.yoi/tickets/00001KV0SP0TY/item.md index 138fc2f5..aed2a5fc 100644 --- a/.yoi/tickets/00001KV0SP0TY/item.md +++ b/.yoi/tickets/00001KV0SP0TY/item.md @@ -2,7 +2,7 @@ title: 'Remove feature-layer HostAuthority model' state: 'inprogress' created_at: '2026-06-13T15:30:22Z' -updated_at: '2026-06-13T18:41:25Z' +updated_at: '2026-06-13T18:53:02Z' assignee: null readiness: 'implementation_ready' risk_flags: ['feature-api', 'tool-registry', 'ticket-tools'] diff --git a/.yoi/tickets/00001KV0SP0TY/thread.md b/.yoi/tickets/00001KV0SP0TY/thread.md index 0dd01be9..839a43d6 100644 --- a/.yoi/tickets/00001KV0SP0TY/thread.md +++ b/.yoi/tickets/00001KV0SP0TY/thread.md @@ -83,4 +83,39 @@ Validation: Ticket evidence、relation records、orchestration plan、workspace state を確認した。This Ticket 自身を blocking する relation はなく、incoming dependent Ticket の前提として先に進めるべき。実装 side effect の前に inprogress acceptance を記録する。 +--- + + + +## Implementation report + +## Implementation report + +Commit: `5549c50d8679` (`feat: remove feature host authority API`) + +Files changed: +- `crates/pod/src/feature.rs` + - Removed `HostAuthority`, `HostAuthorityRequest`, `HostAuthorityGrantSet`, host-authority denial errors, grant plumbing, and per-tool host-authority gates from the public feature API/install path. + - Kept ordinary contribution declaration diagnostics: duplicate names, undeclared/mismatched tools, undeclared hooks/background tasks/services, skipped contributions, and service requirement diagnostics. + - Kept install reports focused on installed/skipped contributions and diagnostics without security grant semantics. +- `crates/pod/src/feature/builtin/ticket.rs` + - Stopped declaring TicketBackend host authority and registering Ticket tools with feature-layer authority requirements. + - Preserved explicit `TicketFeatureConfig`, backend provider/root validation, and access-level-controlled tool exposure. +- `crates/pod/src/feature/builtin/task/mod.rs` + - Removed Task feature prose that referenced feature-layer host authorities. + +Validation: +- `cargo test -p pod feature:: --lib` — passed (46 tests). +- `cargo test -p pod feature::builtin::task --lib` — passed (18 tests). +- `cargo test -p ticket` — passed (68 tests + doc-tests). +- `cargo fmt --check` — passed. +- `cargo check --workspace --all-targets` — passed. +- `git diff --check` — passed before commit. +- Source grep under `crates/**/*.rs` found no remaining `HostAuthority*`, `host_authority`, `with_host_authority`, `requested_host_authorities`, or `required_host_authorities` symbols/terminology after cleanup. + +Residual risks / notes: +- `nix build .#yoi` was not run; this change does not modify dependencies, `Cargo.lock`, packaging, or source filters. +- Related Plugin/MCP planning Ticket review was not performed from this delegated Coder scope because only Ticket `00001KV0SP0TY` is readable/writable in `.yoi/tickets`; no Plugin/MCP permission or trust policy was implemented. + + --- From 92e64bda5f699b6ed9c135d1c69335a457eea2c4 Mon Sep 17 00:00:00 2001 From: Hare Date: Sun, 14 Jun 2026 03:59:20 +0900 Subject: [PATCH 3/3] ticket: approve host authority cleanup --- .yoi/tickets/00001KV0SP0TY/item.md | 2 +- .yoi/tickets/00001KV0SP0TY/thread.md | 35 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.yoi/tickets/00001KV0SP0TY/item.md b/.yoi/tickets/00001KV0SP0TY/item.md index aed2a5fc..a36bb220 100644 --- a/.yoi/tickets/00001KV0SP0TY/item.md +++ b/.yoi/tickets/00001KV0SP0TY/item.md @@ -2,7 +2,7 @@ title: 'Remove feature-layer HostAuthority model' state: 'inprogress' created_at: '2026-06-13T15:30:22Z' -updated_at: '2026-06-13T18:53:02Z' +updated_at: '2026-06-13T18:58:42Z' assignee: null readiness: 'implementation_ready' risk_flags: ['feature-api', 'tool-registry', 'ticket-tools'] diff --git a/.yoi/tickets/00001KV0SP0TY/thread.md b/.yoi/tickets/00001KV0SP0TY/thread.md index 839a43d6..a17dc835 100644 --- a/.yoi/tickets/00001KV0SP0TY/thread.md +++ b/.yoi/tickets/00001KV0SP0TY/thread.md @@ -118,4 +118,39 @@ Residual risks / notes: - Related Plugin/MCP planning Ticket review was not performed from this delegated Coder scope because only Ticket `00001KV0SP0TY` is readable/writable in `.yoi/tickets`; no Plugin/MCP permission or trust policy was implemented. +--- + + + +## Review: approve + +## Review: approve + +Reviewed implementation commits `5549c50d` and `3faf7d7b` against Ticket `00001KV0SP0TY`. + +Evidence: +- `crates/pod/src/feature.rs` removes the feature-layer `HostAuthority`, `HostAuthorityRequest`, `HostAuthorityGrantSet`, grant/denial/install-report semantics, and per-tool authority gates. The remaining feature API is contribution/lifecycle/diagnostic oriented: tools, hooks, background tasks, services, notifications, and install diagnostics. +- No renamed equivalent authority/grant layer was introduced in `pod::feature`; remaining checks are ordinary contribution diagnostics such as duplicate tool names, undeclared tools/hooks/background tasks/services, service requirements, skipped contributions, and install errors. +- `crates/pod/src/feature/builtin/ticket.rs` no longer requests or registers feature-layer host authority. Ticket tool exposure remains controlled by `TicketFeatureConfig` resolution, backend provider/root validation, and `TicketFeatureAccess` / base-orchestration tool selection. Missing/invalid backend roots and unsupported providers still fail closed without registering tools. +- `crates/pod/src/feature/builtin/task/mod.rs` no longer describes task tools in host-authority terms; task hooks/tools still install through the normal feature registry path. +- Source grep under `crates/**/*.rs` found no remaining `HostAuthority`, `HostAuthorityRequest`, `HostAuthorityGrantSet`, `host_authority`, `with_host_authority`, `requested_host_authorities`, or `required_host_authorities` symbols/terms. +- Related Plugin/MCP planning Tickets inspected (`00001KTR81P9X`, `00001KTR82RB7`, `00001KSXRQ4G8`, `00001KT0Z4BK8`) state that Plugin/MCP permission/trust policy is not a `pod::feature` authority/grant dependency. The remaining mentions are negative boundary statements, not implementation reliance. + +Validation performed: +- `git diff --check c4465a04..HEAD` — passed. +- `cargo test -p pod feature:: --lib` — passed. +- `cargo test -p pod feature::builtin::task --lib` — passed. +- `cargo test -p ticket` — passed. +- `cargo fmt --check` — passed. +- `cargo check --workspace --all-targets` — passed. + +Not run: +- `nix build .#yoi`; skipped because this review scope is source read-only with writes limited to `target/` and this Ticket record, and the change does not touch dependencies, `Cargo.lock`, packaging, or source filters. + +Risks / notes: +- This intentionally removes the feature-layer authority gate rather than replacing it. Any future Plugin/MCP permission policy must be implemented in its owning layer and must not reintroduce this as a feature-layer grant API. + +Decision: approved. + + ---