Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0588b82
feat(reborn): declare Slack channel as extension manifest
serrrfirat Jun 11, 2026
e34744c
fix(reborn): address extension review feedback
henrypark133 Jun 12, 2026
de607cb
Merge branch 'main' into codex/slack-extension-manifest
henrypark133 Jun 12, 2026
5038ab3
Merge branch 'main' into codex/slack-extension-manifest
henrypark133 Jun 14, 2026
651647c
Merge branch 'main' into codex/slack-extension-manifest
henrypark133 Jun 14, 2026
97e35ef
fix(reborn): address Slack product-adapter extension review feedback
henrypark133 Jun 14, 2026
67e583b
feat(runtime-context): enable connected-channel classification via su…
henrypark133 Jun 14, 2026
59cdfc8
style(runtime-context): cargo fmt + drop unreachable classification b…
henrypark133 Jun 14, 2026
f504aae
fix(webui-v2): repair Slack extension asset + locale checks after cha…
henrypark133 Jun 14, 2026
0ce4484
test(webui-v2): cover ExtensionCard channel overflow + localize regis…
henrypark133 Jun 15, 2026
8e9931b
refactor(runtime-context): drop permanent classification flag, docume…
henrypark133 Jun 15, 2026
329eb4c
fix(webui-v2): suppress Activate for channel kinds during pairing
henrypark133 Jun 15, 2026
3bdd36e
fix(webui-v2): add channels.slack key + regression tests for surface-…
henrypark133 Jun 15, 2026
17676dd
fix(reborn): gate Slack catalog entry behind slack-v2-host-beta; test…
henrypark133 Jun 15, 2026
1e62742
refactor(reborn): consolidate Slack trust policy tests (#4778)
serrrfirat Jun 15, 2026
7b2f622
feat(reborn): expose outbound delivery targets to model
serrrfirat Jun 11, 2026
cf67669
Merge branch 'main' into codex/channel-manifest-surfaces
serrrfirat Jun 15, 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
14 changes: 11 additions & 3 deletions crates/ironclaw_reborn_composition/src/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ use ironclaw_filesystem::{
MountDescriptor, RootFilesystem, StorageClass,
};
use ironclaw_filesystem::{LocalFilesystem, ScopedFilesystem};
#[cfg(any(feature = "libsql", feature = "postgres"))]
use ironclaw_host_api::runtime_policy::EffectiveRuntimePolicy;
use ironclaw_host_api::runtime_policy::{FilesystemBackendKind, ProcessBackendKind, SecretMode};
use ironclaw_host_api::runtime_policy::{
EffectiveRuntimePolicy, FilesystemBackendKind, ProcessBackendKind, SecretMode,
};
use ironclaw_host_api::{
EffectKind, ExtensionId, HostPath, MountPermissions, MountView, PackageId, RuntimeHttpEgress,
UserId, VirtualPath,
Expand Down Expand Up @@ -396,6 +396,7 @@ pub struct RebornLocalDevApprovalTestParts {
pub(crate) struct RebornLocalRuntimeServices {
pub(crate) approval_requests: Arc<LocalDevApprovalRequestStore>,
pub(crate) capability_leases: Arc<LocalDevCapabilityLeaseStore>,
pub(crate) runtime_policy: Option<EffectiveRuntimePolicy>,
// Used in approval_test_support (cfg(test) only); suppress the dead-code
// lint on non-test builds where that module is not compiled in.
#[cfg_attr(not(test), allow(dead_code))]
Expand Down Expand Up @@ -569,6 +570,7 @@ struct RebornLocalDevStoreGraph {
struct RebornLocalDevStoreGraphInput {
filesystem: Arc<LocalDevRootFilesystem>,
owner_user_id: UserId,
runtime_policy: Option<EffectiveRuntimePolicy>,
skill_filesystem: Arc<ScopedFilesystem<LocalDevRootFilesystem>>,
workspace_filesystem: Arc<ScopedFilesystem<LocalDevRootFilesystem>>,
workspace_mounts: MountView,
Expand Down Expand Up @@ -787,6 +789,7 @@ async fn build_local_dev(input: RebornBuildInput) -> Result<RebornServices, Rebo
let mut store_graph = build_local_dev_store_graph(RebornLocalDevStoreGraphInput {
filesystem: Arc::clone(&filesystem),
owner_user_id,
runtime_policy: runtime_policy.clone(),
skill_filesystem,
workspace_filesystem,
workspace_mounts: runtime_workspace_mounts,
Expand Down Expand Up @@ -1210,6 +1213,7 @@ fn build_local_dev_store_graph(
let RebornLocalDevStoreGraphInput {
filesystem,
owner_user_id,
runtime_policy,
skill_filesystem,
workspace_filesystem,
workspace_mounts,
Expand Down Expand Up @@ -1276,6 +1280,7 @@ fn build_local_dev_store_graph(
let local_runtime = Arc::new(RebornLocalRuntimeServices {
approval_requests: Arc::clone(&approval_requests),
capability_leases: Arc::clone(&capability_leases),
runtime_policy,
capability_policy: Arc::clone(&capability_policy),
persistent_approval_policies: Arc::clone(&persistent_approval_policies),
turn_state: Arc::clone(&turn_state),
Expand Down Expand Up @@ -1343,6 +1348,7 @@ fn build_local_dev_store_graph(
let RebornLocalDevStoreGraphInput {
filesystem,
owner_user_id,
runtime_policy,
skill_filesystem,
workspace_filesystem,
workspace_mounts,
Expand Down Expand Up @@ -1398,6 +1404,7 @@ fn build_local_dev_store_graph(
let local_runtime = Arc::new(RebornLocalRuntimeServices {
approval_requests: Arc::clone(&approval_requests),
capability_leases: Arc::clone(&capability_leases),
runtime_policy,
capability_policy: Arc::clone(&capability_policy),
persistent_approval_policies: Arc::clone(&persistent_approval_policies),
turn_state: Arc::clone(&turn_state),
Expand Down Expand Up @@ -3330,6 +3337,7 @@ mod tests {
Arc::new(RebornLocalRuntimeServices {
approval_requests: Arc::clone(&base_runtime.approval_requests),
capability_leases: Arc::clone(&base_runtime.capability_leases),
runtime_policy: base_runtime.runtime_policy.clone(),
capability_policy: Arc::clone(&base_runtime.capability_policy),
persistent_approval_policies: Arc::clone(&base_runtime.persistent_approval_policies),
turn_state: Arc::clone(&base_runtime.turn_state),
Expand Down
35 changes: 29 additions & 6 deletions crates/ironclaw_reborn_composition/src/local_dev_authorization.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::sync::Arc;

use ironclaw_authorization::TrustAwareCapabilityDispatchAuthorizer;
use ironclaw_host_api::runtime_policy::{ApprovalPolicy, EffectiveRuntimePolicy, RuntimeProfile};
use ironclaw_host_api::{
EffectKind,
runtime_policy::{ApprovalPolicy, EffectiveRuntimePolicy, RuntimeProfile},
};

use crate::{
local_dev_capability_policy::LocalDevCapabilityPolicy,
Expand All @@ -13,15 +16,35 @@ pub(crate) fn local_dev_authorizer(
runtime_policy: Option<&EffectiveRuntimePolicy>,
capability_policy: Arc<LocalDevCapabilityPolicy>,
) -> Arc<dyn TrustAwareCapabilityDispatchAuthorizer> {
let (approval_policy, resolved_profile) = local_dev_approval_policy(runtime_policy);
let gate_effects = capability_policy.approval_gate_effects();
let gate_policy: Arc<dyn ProfileApprovalGatePolicy> = Arc::new(
RuntimeProfileApprovalGatePolicy::new(resolved_profile, gate_effects),
);
profile_approval_authorizer(approval_policy, gate_policy)
}

pub(crate) fn local_dev_effects_require_approval(
runtime_policy: Option<&EffectiveRuntimePolicy>,
capability_policy: &LocalDevCapabilityPolicy,
effects: &[EffectKind],
) -> bool {
let (approval_policy, resolved_profile) = local_dev_approval_policy(runtime_policy);
RuntimeProfileApprovalGatePolicy::new(
resolved_profile,
capability_policy.approval_gate_effects(),
)
.effects_require_approval(approval_policy, effects)
}

fn local_dev_approval_policy(
runtime_policy: Option<&EffectiveRuntimePolicy>,
) -> (ApprovalPolicy, RuntimeProfile) {
let approval_policy = runtime_policy
.map(|policy| policy.approval_policy)
.unwrap_or(ApprovalPolicy::AskDestructive);
let resolved_profile = runtime_policy
.map(|policy| policy.resolved_profile)
.unwrap_or(RuntimeProfile::LocalDev);
let gate_effects = capability_policy.approval_gate_effects();
let gate_policy: Arc<dyn ProfileApprovalGatePolicy> = Arc::new(
RuntimeProfileApprovalGatePolicy::new(resolved_profile, gate_effects),
);
profile_approval_authorizer(approval_policy, gate_policy)
(approval_policy, resolved_profile)
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,9 @@ capability = "builtin.trigger_remove"
effects = ["dispatch_capability", "external_write"]
mounts = "ambient"
network = "default"

[[grants]]
capability = "builtin.outbound_delivery_target_set"
effects = ["dispatch_capability", "external_write"]
mounts = "ambient"
network = "default"
Comment thread
serrrfirat marked this conversation as resolved.
1 change: 1 addition & 0 deletions crates/ironclaw_reborn_composition/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,7 @@ pub async fn build_reborn_runtime(
model_gateway,
milestone_sink.clone(),
skill_activation_source.clone(),
None,
)
.ok_or(RebornRuntimeError::HostRuntimeUnavailable)?;
(
Expand Down
34 changes: 32 additions & 2 deletions crates/ironclaw_reborn_composition/src/runtime/local_dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use std::{
use chrono::Utc;
use uuid::Uuid;

use ironclaw_authorization::CapabilityLeaseStore;
use ironclaw_host_api::{
CapabilityId, ExecutionContext, ExtensionId, InvocationId, MountView, ResourceScope,
RuntimeKind, TrustClass, UserId,
CapabilityId, EffectKind, ExecutionContext, ExtensionId, InvocationId, MountView,
ResourceScope, RuntimeKind, TrustClass, UserId,
};
use ironclaw_host_runtime::{
CapabilitySurfacePolicy, HostRuntime, SurfaceKind,
Expand All @@ -20,6 +21,8 @@ use ironclaw_loop_support::{
HostManagedModelResponse, HostManagedToolResultContent, LoopCapabilityInputResolver,
LoopCapabilityPortFactory, LoopCapabilityResultWriter, loop_driver_execution_extension_id,
};
use ironclaw_product_workflow::OutboundPreferencesProductFacade;
use ironclaw_run_state::ApprovalRequestStore;
use ironclaw_threads::{
AppendCapabilityDisplayPreviewRequest, CapabilityDisplayPreviewEnvelope,
CapabilityDisplayPreviewEnvelopeInput, CapabilityDisplayPreviewStatus, SessionThreadService,
Expand All @@ -34,6 +37,7 @@ use ironclaw_turns::{
},
};

use crate::local_dev_authorization::local_dev_effects_require_approval;
use crate::local_dev_capability_policy::LocalDevCapabilityPolicy;
use crate::local_dev_mounts::scoped_skill_management_mount_view;
use crate::{
Expand All @@ -43,6 +47,7 @@ use crate::{
};

pub(super) mod extension_surface;
mod outbound_delivery;
mod refreshing_capability_port;
#[cfg(test)]
mod shell_tests;
Expand All @@ -51,6 +56,10 @@ mod surface_disclosure;
mod synthetic_capability;

use extension_surface::{LocalDevExtensionSurface, LocalDevExtensionSurfaceSource};
#[cfg(test)]
pub(crate) use outbound_delivery::{
OUTBOUND_DELIVERY_TARGET_SET_CAPABILITY_ID, OUTBOUND_DELIVERY_TARGETS_LIST_CAPABILITY_ID,
};
use refreshing_capability_port::{
RefreshingLocalDevCapabilityPortConfig, create_refreshing_local_dev_capability_port,
};
Expand All @@ -75,11 +84,19 @@ pub(super) fn capability_wiring(
model_gateway: Arc<dyn HostManagedModelGateway>,
milestone_sink: Arc<dyn LoopHostMilestoneSink>,
skill_activation_source: Option<Arc<LocalDevSelectableSkillContextSource>>,
outbound_preferences_facade: Option<Arc<dyn OutboundPreferencesProductFacade>>,
) -> Option<LocalDevCapabilityWiring> {
let runtime = services.host_runtime.clone()?;
let local_runtime = services.local_runtime.as_ref()?;
let workspace_mounts = local_runtime.workspace_mounts.clone();
let memory_mounts = local_runtime.memory_mounts.clone();
let approval_requests: Arc<dyn ApprovalRequestStore> = local_runtime.approval_requests.clone();
let capability_leases: Arc<dyn CapabilityLeaseStore> = local_runtime.capability_leases.clone();
let outbound_delivery_target_set_requires_approval = local_dev_effects_require_approval(
local_runtime.runtime_policy.as_ref(),
policy.as_ref(),
&[EffectKind::ExternalWrite],
);
let extension_surface_source =
LocalDevExtensionSurfaceSource::new(local_runtime.extension_management.clone());
let display_previews = Arc::new(CapabilityDisplayPreviewStore::default());
Expand All @@ -102,6 +119,10 @@ pub(super) fn capability_wiring(
result_writer: Arc::clone(&capability_result_writer),
milestone_sink,
skill_activation_source,
outbound_preferences_facade,
outbound_delivery_target_set_requires_approval,
approval_requests,
capability_leases,
});
let model_gateway: Arc<dyn HostManagedModelGateway> = Arc::new(
LocalDevResultHydratingModelGateway::new(model_gateway, capability_io),
Expand All @@ -128,6 +149,10 @@ struct LocalDevLoopCapabilityPortFactory {
result_writer: Arc<dyn LoopCapabilityResultWriter>,
milestone_sink: Arc<dyn LoopHostMilestoneSink>,
skill_activation_source: Option<Arc<LocalDevSelectableSkillContextSource>>,
outbound_preferences_facade: Option<Arc<dyn OutboundPreferencesProductFacade>>,
outbound_delivery_target_set_requires_approval: bool,
approval_requests: Arc<dyn ApprovalRequestStore>,
capability_leases: Arc<dyn CapabilityLeaseStore>,
}

#[async_trait::async_trait]
Expand All @@ -154,6 +179,11 @@ impl LoopCapabilityPortFactory for LocalDevLoopCapabilityPortFactory {
result_writer: Arc::clone(&self.result_writer),
milestone_sink: Arc::clone(&self.milestone_sink),
skill_activation_source: self.skill_activation_source.clone(),
outbound_preferences_facade: self.outbound_preferences_facade.clone(),
outbound_delivery_target_set_requires_approval: self
.outbound_delivery_target_set_requires_approval,
approval_requests: Arc::clone(&self.approval_requests),
capability_leases: Arc::clone(&self.capability_leases),
})
.await
}
Expand Down
Loading
Loading