wip(tickets): backend createdBy (#5) + bulk status/priority/delete (#6)

Ajoute created_by sur IssueIndexEntry/TicketSummaryDto + filtre createdBy
(#5), et les use cases BulkUpdateIssueStatus/Priority + BulkDeleteIssues
avec les DTO/outils MCP idea_ticket_bulk_* associés (#6).

NON VERT : BulkDeleteIssues::execute référence BatchIssueResult::deleted(),
constructeur pas encore ajouté à BatchIssueResult (seuls ok/err existent) ->
`cargo check` échoue (E0599 dans application::issues::mod). Reste à
DevBackend avant toute QA/merge.

Branché sur feature/sdk-integration (dépend du commit #2 dans
orchestrator/mcp/server.rs et tools.rs) ; à rebaser sur develop une fois
feature/sdk-integration mergé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 18:28:39 +02:00
parent 1ef1fd9e40
commit 6da52c6a02
20 changed files with 1061 additions and 34 deletions

View File

@ -284,7 +284,31 @@ fn enforce_policy(
"tool `{name}` is not permitted for requester {requester}"
)));
}
if is_ticket_policy_mutation_tool(name) {
if is_ticket_policy_bulk_mutation_tool(name) {
let refs = arguments
.get("refs")
.and_then(Value::as_array)
.ok_or_else(|| {
ToolInvocationError::InvalidArguments(format!(
"tool `{name}` requires ticket refs under the active policy"
))
})?;
for raw_ref in refs {
let raw_ref = raw_ref.as_str().ok_or_else(|| {
ToolInvocationError::InvalidArguments(format!(
"tool `{name}` requires string ticket refs under the active policy"
))
})?;
let issue_ref = IssueRef::from_str(raw_ref).map_err(|e| {
ToolInvocationError::InvalidArguments(format!("invalid ticket ref: {e}"))
})?;
if !policy.permits_ticket_mutation(name, issue_ref) {
return Err(ToolInvocationError::Rejected(format!(
"tool `{name}` is not permitted for ticket {issue_ref}"
)));
}
}
} else if is_ticket_policy_mutation_tool(name) {
let raw_ref = arguments
.get("ref")
.and_then(Value::as_str)
@ -317,6 +341,13 @@ fn is_ticket_policy_mutation_tool(name: &str) -> bool {
)
}
fn is_ticket_policy_bulk_mutation_tool(name: &str) -> bool {
matches!(
name,
"idea_ticket_bulk_update_status" | "idea_ticket_bulk_update_priority"
)
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;