summaryrefslogtreecommitdiff
path: root/makima/src
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-27 11:04:20 +0000
committerGitHub <noreply@github.com>2026-01-27 11:04:20 +0000
commitc618174e60e4632d36d7352d83399508c72b2f42 (patch)
treefbca74b921a57165aea046b959a44ab00589532f /makima/src
parentb6f239c19f0d3130515f3745f842e17a69212295 (diff)
downloadsoryu-c618174e60e4632d36d7352d83399508c72b2f42.tar.gz
soryu-c618174e60e4632d36d7352d83399508c72b2f42.zip
Add Red Team CLI command and frontend UI (#39)
* Add Red Team CLI command and frontend UI Backend additions: - Add `makima red-team notify` CLI command for red team tasks - Add RedTeamCommand enum with Notify subcommand - Add red_team API client module for notify endpoint - Add RedTeamNotifyArgs with severity, task, file, context options Frontend additions: - Add ContractCreateModal with red team toggle and prompt input - Update ContractDetail with red-team tab for notifications - Update ContractList with red team enabled badge - Add TypeScript types for RedTeamNotification and related interfaces Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add CSS styles for Red Team frontend components Add comprehensive styling for: - Contract list and detail containers - Red team badge styling with gradient backgrounds - Tab navigation with red team specific styling - Red team notifications panel with severity indicators - Contract creation modal form elements - Task badges for supervisor and red team roles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix missing local_only field in TUI CreateContractRequest Add the missing local_only field to the CreateContractRequest struct initialization in the TUI contract creation handler. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * [WIP] Heartbeat checkpoint - 2026-01-27 03:07:28 UTC --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src')
-rw-r--r--makima/src/bin/makima.rs13
-rw-r--r--makima/src/daemon/api/mod.rs2
-rw-r--r--makima/src/daemon/api/red_team.rs39
-rw-r--r--makima/src/daemon/cli/mod.rs57
-rw-r--r--makima/src/daemon/cli/red_team.rs26
5 files changed, 135 insertions, 2 deletions
diff --git a/makima/src/bin/makima.rs b/makima/src/bin/makima.rs
index ffb9364..44fa590 100644
--- a/makima/src/bin/makima.rs
+++ b/makima/src/bin/makima.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
use makima::daemon::api::{ApiClient, CreateContractRequest};
use makima::daemon::cli::{
- Cli, CliConfig, Commands, ConfigCommand, ContractCommand, SupervisorCommand, ViewArgs,
+ Cli, CliConfig, Commands, ConfigCommand, ContractCommand, RedTeamCommand, SupervisorCommand, ViewArgs,
};
use makima::daemon::tui::{self, Action, App, ListItem, ViewType, TuiWsClient, WsEvent, OutputLine, OutputMessageType, WsConnectionState, RepositorySuggestion};
use makima::daemon::config::{DaemonConfig, RepoEntry};
@@ -30,6 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Commands::Contract(cmd) => run_contract(cmd).await,
Commands::View(args) => run_view(args).await,
Commands::Config(cmd) => run_config(cmd).await,
+ Commands::RedTeam(cmd) => run_red_team(cmd).await,
}
}
@@ -789,6 +790,16 @@ async fn run_config(cmd: ConfigCommand) -> Result<(), Box<dyn std::error::Error
}
}
+/// Run red team commands.
+async fn run_red_team(cmd: RedTeamCommand) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
+ match cmd {
+ RedTeamCommand::Notify(args) => {
+ makima::daemon::cli::handle_notify(args).await?;
+ Ok(())
+ }
+ }
+}
+
/// Load contracts from API
async fn load_contracts(client: &ApiClient) -> Result<Vec<ListItem>, Box<dyn std::error::Error + Send + Sync>> {
let result = client.list_contracts().await?;
diff --git a/makima/src/daemon/api/mod.rs b/makima/src/daemon/api/mod.rs
index 49d80e0..92e34e9 100644
--- a/makima/src/daemon/api/mod.rs
+++ b/makima/src/daemon/api/mod.rs
@@ -2,7 +2,9 @@
pub mod client;
pub mod contract;
+pub mod red_team;
pub mod supervisor;
pub use client::ApiClient;
pub use contract::CreateContractRequest;
+pub use red_team::RedTeamNotifyRequest;
diff --git a/makima/src/daemon/api/red_team.rs b/makima/src/daemon/api/red_team.rs
new file mode 100644
index 0000000..6d3c969
--- /dev/null
+++ b/makima/src/daemon/api/red_team.rs
@@ -0,0 +1,39 @@
+//! Red team API methods.
+
+use serde::Serialize;
+use uuid::Uuid;
+
+use super::client::{ApiClient, ApiError};
+use super::supervisor::JsonValue;
+
+/// Request body for red team notify endpoint.
+#[derive(Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RedTeamNotifyRequest {
+ /// The issue message
+ pub message: String,
+
+ /// Severity level: low, medium, high, critical
+ pub severity: String,
+
+ /// The specific task this relates to (optional)
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub related_task_id: Option<Uuid>,
+
+ /// The file path where the issue was detected (optional)
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub file_path: Option<String>,
+
+ /// Additional context about the issue (optional)
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context: Option<String>,
+}
+
+impl ApiClient {
+ /// Send a red team notification about an issue found during adversarial review.
+ ///
+ /// POST /api/v1/mesh/red-team/notify
+ pub async fn red_team_notify(&self, req: RedTeamNotifyRequest) -> Result<JsonValue, ApiError> {
+ self.post("/api/v1/mesh/red-team/notify", &req).await
+ }
+}
diff --git a/makima/src/daemon/cli/mod.rs b/makima/src/daemon/cli/mod.rs
index 0805edd..c848e8e 100644
--- a/makima/src/daemon/cli/mod.rs
+++ b/makima/src/daemon/cli/mod.rs
@@ -3,15 +3,18 @@
pub mod config;
pub mod contract;
pub mod daemon;
+pub mod red_team;
pub mod server;
pub mod supervisor;
pub mod view;
-use clap::{Parser, Subcommand};
+use clap::{Args, Parser, Subcommand};
+use uuid::Uuid;
pub use config::CliConfig;
pub use contract::ContractArgs;
pub use daemon::DaemonArgs;
+pub use red_team::handle_notify;
pub use server::ServerArgs;
pub use supervisor::SupervisorArgs;
pub use view::ViewArgs;
@@ -58,6 +61,10 @@ pub enum Commands {
/// Saves configuration to ~/.makima/config.toml for use by CLI commands.
#[command(subcommand)]
Config(ConfigCommand),
+
+ /// Red team commands for adversarial monitoring
+ #[command(name = "red-team", subcommand)]
+ RedTeam(RedTeamCommand),
}
/// Config subcommands for CLI configuration.
@@ -196,6 +203,54 @@ pub enum ContractCommand {
CreateFile(contract::CreateFileArgs),
}
+/// Red team subcommands for adversarial monitoring.
+#[derive(Subcommand, Debug)]
+pub enum RedTeamCommand {
+ /// Send a notification to the supervisor about a detected issue.
+ /// Only available to red team tasks.
+ Notify(RedTeamNotifyArgs),
+}
+
+/// Arguments for red-team notify command.
+#[derive(Args, Debug)]
+pub struct RedTeamNotifyArgs {
+ /// API URL
+ #[arg(long, env = "MAKIMA_API_URL", default_value = "https://api.makima.jp")]
+ pub api_url: String,
+
+ /// API key for authentication
+ #[arg(long, env = "MAKIMA_API_KEY")]
+ pub api_key: String,
+
+ /// Current task ID (must be a red team task)
+ #[arg(long, env = "MAKIMA_TASK_ID")]
+ pub task_id: Uuid,
+
+ /// Contract ID
+ #[arg(long, env = "MAKIMA_CONTRACT_ID")]
+ pub contract_id: Uuid,
+
+ /// The notification message
+ #[arg(index = 1)]
+ pub message: String,
+
+ /// Severity level: low, medium, high, critical
+ #[arg(long, default_value = "medium")]
+ pub severity: String,
+
+ /// Related task ID (optional)
+ #[arg(long)]
+ pub task: Option<Uuid>,
+
+ /// Related file path (optional)
+ #[arg(long)]
+ pub file: Option<String>,
+
+ /// Additional context (optional)
+ #[arg(long)]
+ pub context: Option<String>,
+}
+
impl Cli {
/// Parse command-line arguments
pub fn parse_args() -> Self {
diff --git a/makima/src/daemon/cli/red_team.rs b/makima/src/daemon/cli/red_team.rs
new file mode 100644
index 0000000..771aae4
--- /dev/null
+++ b/makima/src/daemon/cli/red_team.rs
@@ -0,0 +1,26 @@
+//! Red Team subcommand - adversarial review notification commands.
+
+use crate::daemon::api::{ApiClient, RedTeamNotifyRequest};
+use super::RedTeamNotifyArgs;
+
+/// Handle the red-team notify command.
+pub async fn handle_notify(args: RedTeamNotifyArgs) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
+ let client = ApiClient::new(args.api_url, args.api_key)?;
+
+ // Use --task if provided, otherwise fall back to MAKIMA_TASK_ID
+ let related_task_id = args.task;
+
+ let req = RedTeamNotifyRequest {
+ message: args.message,
+ severity: args.severity,
+ related_task_id,
+ file_path: args.file,
+ context: args.context,
+ };
+
+ eprintln!("Sending red team notification...");
+ let result = client.red_team_notify(req).await?;
+ println!("{}", serde_json::to_string(&result.0)?);
+
+ Ok(())
+}