You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
maps each installed LifecyclePackageRef → CapabilityId(s) via a PackageCapabilitySource;
returns CapabilityAllowSet::Allowlist(...).
Availability is sourced from #4544 effective installations — this PR depends only on #4544, NOT on #5262's EffectivePolicy fold. Config / identity / approval layer on top later (#5273).
PackageCapabilitySource (grounded)
visible_capability_ids come from the extension manifest [capabilities] filtered to Visibility::Model (available_extensions.rs:visible_capability_ids()), deterministic at parse time. There is no cross-boundary facade (product_workflow cannot depend on composition-scoped lifecycle), so the resolver gets a PackageCapabilitySourceseeded at composition from the AvailableExtensionCatalog. Covers WASM extensions cleanly; skills / MCP / WASM-kind don't expose cap-ids the same way yet → extension-tools-first.
Fail-closed (grounded — Err kills the turn)
resolve() is called once per turn at host build (loop_driver_host.rs:1367); a returned Err maps to HostFactoryError and fails the whole turn. Therefore:
no resolvable user / no grants → Ok(Allowlist(empty)) (deny all, turn still runs — a user with no grants can still chat);
genuine store / internal error → Err (fail-closed — never expose tools on uncertainty).
Wiring
Replaces EmptyCapabilitySurfaceResolver (production) andAllowAllCapabilitySurfaceResolver (local-dev) in crates/ironclaw_reborn_composition/src/runtime.rs (~2828 / ~2852). Must coexist with SubagentCapabilitySurfaceResolver (subagent intersection). The local-dev swap is what makes the effect observable for the manual test.
Tests
At the host-factory level (build_text_only_host_with_profiled_capabilities), modeled on crates/ironclaw_reborn/tests/runtime_policy_tool_visibility_integration.rs: admin-shared visible to any user; user-private only to its owner; disabled excluded; no-user → empty; mapping correctness.
Part of #5261 (epic) · continues #4628. The slice that makes a per-user availability grant actually change the model-visible tool surface.
What
ScopedLifecyclePolicyCapabilitySurfaceResolver, aCapabilitySurfaceProfileResolver(crates/ironclaw_loop_support/src/capability_allow_set.rs), that:(tenant_id, user_id)principal fromLoopRunContext—actor.user_idfirst, thenscope.explicit_owner_user_id();ScopedLifecycleSubject::new(tenant, user)and calls feat(reborn): scoped-lifecycle admin install store (#3288) — availability foundation for #5261 #4544'slist_effective_installations(subject)(its default impl already filtersenabled+ ownership-visibility:AdminShared→ all users in tenant,UserPrivate→ owner only);LifecyclePackageRef → CapabilityId(s)via aPackageCapabilitySource;CapabilityAllowSet::Allowlist(...).Availability is sourced from #4544 effective installations — this PR depends only on #4544, NOT on #5262's
EffectivePolicyfold. Config / identity / approval layer on top later (#5273).PackageCapabilitySource (grounded)
visible_capability_idscome from the extension manifest[capabilities]filtered toVisibility::Model(available_extensions.rs:visible_capability_ids()), deterministic at parse time. There is no cross-boundary facade (product_workflow cannot depend on composition-scoped lifecycle), so the resolver gets aPackageCapabilitySourceseeded at composition from theAvailableExtensionCatalog. Covers WASM extensions cleanly; skills / MCP / WASM-kind don't expose cap-ids the same way yet → extension-tools-first.Fail-closed (grounded —
Errkills the turn)resolve()is called once per turn at host build (loop_driver_host.rs:1367); a returnedErrmaps toHostFactoryErrorand fails the whole turn. Therefore:Ok(Allowlist(empty))(deny all, turn still runs — a user with no grants can still chat);Err(fail-closed — never expose tools on uncertainty).Wiring
Replaces
EmptyCapabilitySurfaceResolver(production) andAllowAllCapabilitySurfaceResolver(local-dev) incrates/ironclaw_reborn_composition/src/runtime.rs(~2828 / ~2852). Must coexist withSubagentCapabilitySurfaceResolver(subagent intersection). The local-dev swap is what makes the effect observable for the manual test.Tests
At the host-factory level (
build_text_only_host_with_profiled_capabilities), modeled oncrates/ironclaw_reborn/tests/runtime_policy_tool_visibility_integration.rs: admin-shared visible to any user; user-private only to its owner; disabled excluded; no-user → empty; mapping correctness.Depends on: #4544. Co-land bundle.