feat(infra): tmp partagé inter-projets géré par IdeA (handles opaques, leases, GC, projection sandbox) — #189 (QA verte)
- Domaine: port ManagedTempStore + modèle (handle opaque, kind Directory/File, état Active/Released, allocation/lease, expiry). - Application: use cases Allocate/Resolve/Release/GcManagedTemp, horodatés via Clock. - Infrastructure: impl FS FsManagedTempStore sous app_data_dir/managed-tmp (root global inter-projets, métadonnées par handle, GC des leases expirés/libérés). - Exposition MCP contrôlée (ManagedTempToolProvider, catalogue) + câblage sandbox: les agents résolvent un handle au lieu d'inventer un path libre. - Tests: application/infrastructure managed_temp.
This commit is contained in:
@ -57,6 +57,7 @@ pub const READ_ONLY_TOOLS: &[&str] = &[
|
||||
"idea_sprint_list",
|
||||
"idea_template_list",
|
||||
"idea_template_read",
|
||||
"idea_managed_temp_resolve",
|
||||
];
|
||||
|
||||
/// Canonical write/action MCP tools denied by default.
|
||||
@ -87,6 +88,9 @@ pub const WRITE_ACTION_TOOLS: &[&str] = &[
|
||||
"idea_template_create",
|
||||
"idea_template_update",
|
||||
"idea_template_delete",
|
||||
"idea_managed_temp_allocate",
|
||||
"idea_managed_temp_release",
|
||||
"idea_managed_temp_gc",
|
||||
];
|
||||
|
||||
/// All MCP tool names that have an explicit access classification.
|
||||
@ -142,6 +146,7 @@ pub fn tool_returns_reply(tool: &str) -> bool {
|
||||
| "idea_workstate_read"
|
||||
) || is_ticket_tool(tool)
|
||||
|| is_template_tool(tool)
|
||||
|| is_managed_temp_tool(tool)
|
||||
}
|
||||
|
||||
/// Whether `tool` is a public ticket MCP tool.
|
||||
@ -156,6 +161,12 @@ pub fn is_template_tool(tool: &str) -> bool {
|
||||
super::templates::is_template_tool(tool)
|
||||
}
|
||||
|
||||
/// Whether `tool` is a public managed-temp MCP tool.
|
||||
#[must_use]
|
||||
pub fn is_managed_temp_tool(tool: &str) -> bool {
|
||||
super::managed_temp::is_managed_temp_tool(tool)
|
||||
}
|
||||
|
||||
/// The full catalogue advertised on `tools/list`.
|
||||
///
|
||||
/// Exactly the tools whose mapping target already exists as an
|
||||
@ -415,6 +426,7 @@ pub fn catalogue() -> Vec<ToolDef> {
|
||||
];
|
||||
tools.extend(super::tickets::catalogue());
|
||||
tools.extend(super::templates::catalogue());
|
||||
tools.extend(super::managed_temp::catalogue());
|
||||
tools
|
||||
}
|
||||
|
||||
@ -1090,4 +1102,37 @@ mod tests {
|
||||
"status enum must match WorkStatus labels exactly"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalogue_advertises_managed_temp_tools_with_expected_access() {
|
||||
let cat = catalogue();
|
||||
for tool in [
|
||||
"idea_managed_temp_allocate",
|
||||
"idea_managed_temp_resolve",
|
||||
"idea_managed_temp_release",
|
||||
"idea_managed_temp_gc",
|
||||
] {
|
||||
assert!(
|
||||
cat.iter().any(|entry| entry.name == tool),
|
||||
"catalogue must contain {tool}"
|
||||
);
|
||||
assert!(tool_returns_reply(tool), "{tool} returns JSON inline");
|
||||
}
|
||||
assert_eq!(
|
||||
tool_access("idea_managed_temp_resolve"),
|
||||
Some(McpToolAccess::Read)
|
||||
);
|
||||
assert_eq!(
|
||||
tool_access("idea_managed_temp_allocate"),
|
||||
Some(McpToolAccess::WriteAction)
|
||||
);
|
||||
assert_eq!(
|
||||
tool_access("idea_managed_temp_release"),
|
||||
Some(McpToolAccess::WriteAction)
|
||||
);
|
||||
assert_eq!(
|
||||
tool_access("idea_managed_temp_gc"),
|
||||
Some(McpToolAccess::WriteAction)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user