actshield 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- actshield/__init__.py +439 -0
- actshield/__main__.py +46 -0
- actshield/agents/__init__.py +12 -0
- actshield/agents/agent.py +200 -0
- actshield/agents/identity.py +114 -0
- actshield/api/__init__.py +34 -0
- actshield/api/models.py +198 -0
- actshield/api/server.py +669 -0
- actshield/api/service.py +599 -0
- actshield/approval/__init__.py +15 -0
- actshield/approval/approval.py +164 -0
- actshield/cli/__init__.py +8 -0
- actshield/cli/graph.py +49 -0
- actshield/cli/main.py +802 -0
- actshield/cli/shell.py +406 -0
- actshield/cli/theme.py +110 -0
- actshield/client.py +757 -0
- actshield/config.py +88 -0
- actshield/context/__init__.py +14 -0
- actshield/context/context.py +161 -0
- actshield/context/provenance.py +108 -0
- actshield/context/taint.py +48 -0
- actshield/decisions/decision.py +74 -0
- actshield/delegation/__init__.py +11 -0
- actshield/delegation/authority.py +63 -0
- actshield/delegation/delegation.py +180 -0
- actshield/demo.py +139 -0
- actshield/doctor.py +94 -0
- actshield/drift/__init__.py +27 -0
- actshield/drift/drift_engine.py +149 -0
- actshield/drift/drift_models.py +63 -0
- actshield/evaluation/__init__.py +1 -0
- actshield/evaluation/cases/__init__.py +1 -0
- actshield/evaluation/eval_suite.py +254 -0
- actshield/forensics/__init__.py +53 -0
- actshield/forensics/access_graph.py +216 -0
- actshield/forensics/authority_graph.py +186 -0
- actshield/forensics/delegation_graph.py +119 -0
- actshield/forensics/explanation.py +254 -0
- actshield/forensics/models.py +488 -0
- actshield/forensics/queries.py +367 -0
- actshield/forensics/serializers.py +68 -0
- actshield/forensics/service.py +310 -0
- actshield/forensics/snapshots.py +174 -0
- actshield/gates/__init__.py +13 -0
- actshield/gates/gate_models.py +46 -0
- actshield/gates/security_gate.py +191 -0
- actshield/gateway/__init__.py +13 -0
- actshield/gateway/http.py +191 -0
- actshield/gateway/mcp.py +292 -0
- actshield/incidents/__init__.py +25 -0
- actshield/incidents/incident.py +94 -0
- actshield/incidents/incident_engine.py +163 -0
- actshield/incidents/incident_rules.py +116 -0
- actshield/incidents/incident_state.py +58 -0
- actshield/integrations/__init__.py +24 -0
- actshield/integrations/ai_secura.py +169 -0
- actshield/integrations/ai_secura_analysis.py +236 -0
- actshield/integrations/apiris.py +122 -0
- actshield/integrations/few_shot.py +104 -0
- actshield/integrations/ollama_adapter.py +538 -0
- actshield/integrations/prompts/__init__.py +1 -0
- actshield/integrations/prompts/examples/__init__.py +1 -0
- actshield/integrations/security_packet.py +82 -0
- actshield/llm_config.py +89 -0
- actshield/offensive/__init__.py +95 -0
- actshield/offensive/adaptive/__init__.py +22 -0
- actshield/offensive/adaptive/adaptive_engine.py +165 -0
- actshield/offensive/adaptive/attack_selector.py +51 -0
- actshield/offensive/adaptive/boundary_search.py +99 -0
- actshield/offensive/adaptive/campaign_memory.py +123 -0
- actshield/offensive/adaptive/feedback.py +84 -0
- actshield/offensive/adaptive/mutation_planner.py +57 -0
- actshield/offensive/attack.py +78 -0
- actshield/offensive/campaign.py +219 -0
- actshield/offensive/corpus.py +155 -0
- actshield/offensive/engine.py +466 -0
- actshield/offensive/evaluator.py +116 -0
- actshield/offensive/evidence.py +63 -0
- actshield/offensive/generator.py +128 -0
- actshield/offensive/mutation.py +101 -0
- actshield/offensive/results.py +77 -0
- actshield/offensive/safety.py +80 -0
- actshield/offensive/strategies/__init__.py +22 -0
- actshield/offensive/strategies/authority_escalation.py +100 -0
- actshield/offensive/strategies/base.py +34 -0
- actshield/offensive/strategies/context_manipulation.py +100 -0
- actshield/offensive/strategies/data_exfiltration.py +100 -0
- actshield/offensive/strategies/delegation_attacks.py +100 -0
- actshield/offensive/strategies/mcp_attacks.py +100 -0
- actshield/offensive/strategies/prompt_injection.py +100 -0
- actshield/offensive/strategies/tool_poisoning.py +100 -0
- actshield/offensive/target.py +113 -0
- actshield/offensive/vulnerable_target.py +121 -0
- actshield/persistence/__init__.py +18 -0
- actshield/persistence/siem.py +102 -0
- actshield/persistence/storage.py +240 -0
- actshield/policy/__init__.py +12 -0
- actshield/policy/evaluator.py +294 -0
- actshield/policy/intent.py +113 -0
- actshield/policy/policy.py +48 -0
- actshield/posture/__init__.py +26 -0
- actshield/posture/posture_engine.py +186 -0
- actshield/posture/posture_models.py +152 -0
- actshield/posture/posture_rules.py +137 -0
- actshield/providers/__init__.py +32 -0
- actshield/providers/anthropic_provider.py +146 -0
- actshield/providers/base.py +160 -0
- actshield/providers/gemini_provider.py +133 -0
- actshield/providers/null_provider.py +40 -0
- actshield/providers/ollama_provider.py +135 -0
- actshield/providers/openai_provider.py +142 -0
- actshield/providers/registry.py +244 -0
- actshield/py.typed +0 -0
- actshield/response/__init__.py +14 -0
- actshield/response/response_actions.py +39 -0
- actshield/response/response_audit.py +32 -0
- actshield/response/response_engine.py +139 -0
- actshield/risk/models.py +104 -0
- actshield/serve.py +117 -0
- actshield/static/404.html +1 -0
- actshield/static/__next.__PAGE__.txt +24 -0
- actshield/static/__next._full.txt +20 -0
- actshield/static/__next._tree.txt +4 -0
- actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_buildManifest.js +11 -0
- actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_clientMiddlewareManifest.js +1 -0
- actshield/static/_next/static/Yp_swxN-C9UoCRNOwkYnY/_ssgManifest.js +1 -0
- actshield/static/_next/static/chunks/09kny2eqjc2or.js +1 -0
- actshield/static/_next/static/chunks/0c1zba1u9whdp.js +1 -0
- actshield/static/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
- actshield/static/_next/static/chunks/0dbjjeg01x25o.js +1 -0
- actshield/static/_next/static/chunks/0duobs55ne238.js +1 -0
- actshield/static/_next/static/chunks/0iaz41l6068e4.js +1 -0
- actshield/static/_next/static/chunks/0mjhyv72x2idp.js +1 -0
- actshield/static/_next/static/chunks/0nelpqfu_ciq6.js +1 -0
- actshield/static/_next/static/chunks/0p1bci9ch797v.js +1 -0
- actshield/static/_next/static/chunks/0tld_ygho5tgm.js +1 -0
- actshield/static/_next/static/chunks/0w1-y7oni66j9.js +1 -0
- actshield/static/_next/static/chunks/10537zyl427zj.js +1 -0
- actshield/static/_next/static/chunks/11pc_jkl3aggn.js +1 -0
- actshield/static/_next/static/chunks/16k7nw0b3t8ys.js +1 -0
- actshield/static/_next/static/chunks/19mx3mg6lkumu.js +1 -0
- actshield/static/_next/static/chunks/1_8p47b-kxg2a.js +1 -0
- actshield/static/_next/static/chunks/1dszjozwfqegx.js +1 -0
- actshield/static/_next/static/chunks/1h43jcb90-m2r.js +22 -0
- actshield/static/_next/static/chunks/1ly04cvt_wh_j.js +1 -0
- actshield/static/_next/static/chunks/1odxrypuwuwp_.js +1 -0
- actshield/static/_next/static/chunks/1oes4c35qz5ku.js +1 -0
- actshield/static/_next/static/chunks/1ow883jl4ln-r.js +16 -0
- actshield/static/_next/static/chunks/1po7bna1as8tc.js +1 -0
- actshield/static/_next/static/chunks/1rsh0og8ifkzx.js +1 -0
- actshield/static/_next/static/chunks/1v0lwzv-859z_.js +1 -0
- actshield/static/_next/static/chunks/25iat2epwx25a.js +1 -0
- actshield/static/_next/static/chunks/25uvt4s2f39a4.js +1 -0
- actshield/static/_next/static/chunks/27t_qfc-3_lzs.js +1 -0
- actshield/static/_next/static/chunks/28bkmy8mez7gm.js +1 -0
- actshield/static/_next/static/chunks/2b6brmw_drw1p.js +1 -0
- actshield/static/_next/static/chunks/2fnhtxi4j6vge.js +1 -0
- actshield/static/_next/static/chunks/2p087eftxemg4.js +6 -0
- actshield/static/_next/static/chunks/2s8pao_z8pgtq.js +1 -0
- actshield/static/_next/static/chunks/2yj7ooc2c-zpg.js +1 -0
- actshield/static/_next/static/chunks/3-mrrr8udt5tk.js +1 -0
- actshield/static/_next/static/chunks/310vm2bl3xxpt.js +31 -0
- actshield/static/_next/static/chunks/35mvsv251jx1r.css +3 -0
- actshield/static/_next/static/chunks/370vf0oetlsx9.js +1 -0
- actshield/static/_next/static/chunks/3e-2m72tyo556.js +1 -0
- actshield/static/_next/static/chunks/3fntmmi971322.js +1 -0
- actshield/static/_next/static/chunks/3fzw-g0hycl2c.js +1 -0
- actshield/static/_next/static/chunks/3lopq3lhmcjxg.js +129 -0
- actshield/static/_next/static/chunks/3mpe2jejel0v2.css +1 -0
- actshield/static/_next/static/chunks/3t8o4f2lzr2sf.js +1 -0
- actshield/static/_next/static/chunks/3y-v1neyllne5.js +1 -0
- actshield/static/_next/static/chunks/43oiwy8mx6cs1.js +1 -0
- actshield/static/_next/static/chunks/turbopack-23wzuebcy_lxm.js +1 -0
- actshield/static/_next/static/media/1bffadaabf893a1e-s.3-6t-g6q0vh0a.woff2 +0 -0
- actshield/static/_next/static/media/2bbe8d2671613f1f-s.0k62hbripvv8p.woff2 +0 -0
- actshield/static/_next/static/media/2c55a0e60120577a-s.0-dom-5bn10r2.woff2 +0 -0
- actshield/static/_next/static/media/5476f68d60460930-s.2uwcyprjm3xu3.woff2 +0 -0
- actshield/static/_next/static/media/83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2 +0 -0
- actshield/static/_next/static/media/9c72aa0f40e4eef8-s.1y4-pdgsjb-pw.woff2 +0 -0
- actshield/static/_next/static/media/ad66f9afd8947f86-s.3lvt2whj97whp.woff2 +0 -0
- actshield/static/_next/static/media/favicon.2vob68tjqpejf.ico +0 -0
- actshield/static/_not-found/__next._full.txt +17 -0
- actshield/static/_not-found/__next._not-found/__PAGE__.txt +23 -0
- actshield/static/_not-found/__next._tree.txt +3 -0
- actshield/static/_not-found.html +1 -0
- actshield/static/_not-found.txt +17 -0
- actshield/static/access/matrix/__next._full.txt +24 -0
- actshield/static/access/matrix/__next._tree.txt +4 -0
- actshield/static/access/matrix/__next.access/matrix/__PAGE__.txt +30 -0
- actshield/static/access/matrix.html +1 -0
- actshield/static/access/matrix.txt +24 -0
- actshield/static/activity/__next._full.txt +22 -0
- actshield/static/activity/__next._tree.txt +4 -0
- actshield/static/activity/__next.activity/__PAGE__.txt +27 -0
- actshield/static/activity.html +1 -0
- actshield/static/activity.txt +22 -0
- actshield/static/agents/__next._full.txt +22 -0
- actshield/static/agents/__next._tree.txt +4 -0
- actshield/static/agents/__next.agents/__PAGE__.txt +27 -0
- actshield/static/agents.html +1 -0
- actshield/static/agents.txt +22 -0
- actshield/static/ai-secura/__next._full.txt +22 -0
- actshield/static/ai-secura/__next._tree.txt +4 -0
- actshield/static/ai-secura/__next.ai-secura/__PAGE__.txt +27 -0
- actshield/static/ai-secura.html +1 -0
- actshield/static/ai-secura.txt +22 -0
- actshield/static/api/__next._full.txt +22 -0
- actshield/static/api/__next._tree.txt +4 -0
- actshield/static/api/__next.api/__PAGE__.txt +27 -0
- actshield/static/api.html +15 -0
- actshield/static/api.txt +22 -0
- actshield/static/apiris/__next._full.txt +22 -0
- actshield/static/apiris/__next._tree.txt +4 -0
- actshield/static/apiris/__next.apiris/__PAGE__.txt +27 -0
- actshield/static/apiris.html +1 -0
- actshield/static/apiris.txt +22 -0
- actshield/static/attack-graph/__next._full.txt +23 -0
- actshield/static/attack-graph/__next._tree.txt +5 -0
- actshield/static/attack-graph/__next.attack-graph/__PAGE__.txt +28 -0
- actshield/static/attack-graph.html +2 -0
- actshield/static/attack-graph.txt +23 -0
- actshield/static/campaigns/__next._full.txt +22 -0
- actshield/static/campaigns/__next._tree.txt +4 -0
- actshield/static/campaigns/__next.campaigns/__PAGE__.txt +27 -0
- actshield/static/campaigns.html +1 -0
- actshield/static/campaigns.txt +22 -0
- actshield/static/context/__next._full.txt +22 -0
- actshield/static/context/__next._tree.txt +4 -0
- actshield/static/context/__next.context/__PAGE__.txt +27 -0
- actshield/static/context.html +1 -0
- actshield/static/context.txt +22 -0
- actshield/static/dashboard/__next._full.txt +22 -0
- actshield/static/dashboard/__next._tree.txt +4 -0
- actshield/static/dashboard/__next.dashboard/__PAGE__.txt +27 -0
- actshield/static/dashboard.html +1 -0
- actshield/static/dashboard.txt +22 -0
- actshield/static/delegations/__next._full.txt +22 -0
- actshield/static/delegations/__next._tree.txt +4 -0
- actshield/static/delegations/__next.delegations/__PAGE__.txt +27 -0
- actshield/static/delegations.html +1 -0
- actshield/static/delegations.txt +22 -0
- actshield/static/demo/__next._full.txt +22 -0
- actshield/static/demo/__next._tree.txt +4 -0
- actshield/static/demo/__next.demo/__PAGE__.txt +27 -0
- actshield/static/demo.html +1 -0
- actshield/static/demo.txt +22 -0
- actshield/static/drift/__next._full.txt +22 -0
- actshield/static/drift/__next._tree.txt +4 -0
- actshield/static/drift/__next.drift/__PAGE__.txt +27 -0
- actshield/static/drift.html +1 -0
- actshield/static/drift.txt +22 -0
- actshield/static/favicon.ico +0 -0
- actshield/static/file.svg +1 -0
- actshield/static/forensics/__next._full.txt +22 -0
- actshield/static/forensics/__next._tree.txt +4 -0
- actshield/static/forensics/__next.forensics/__PAGE__.txt +27 -0
- actshield/static/forensics.html +1 -0
- actshield/static/forensics.txt +22 -0
- actshield/static/globe.svg +1 -0
- actshield/static/incidents/__next._full.txt +22 -0
- actshield/static/incidents/__next._tree.txt +4 -0
- actshield/static/incidents/__next.incidents/__PAGE__.txt +27 -0
- actshield/static/incidents.html +1 -0
- actshield/static/incidents.txt +22 -0
- actshield/static/index.html +3 -0
- actshield/static/index.txt +20 -0
- actshield/static/logo.png +0 -0
- actshield/static/metrics/__next._full.txt +22 -0
- actshield/static/metrics/__next._tree.txt +4 -0
- actshield/static/metrics/__next.metrics/__PAGE__.txt +27 -0
- actshield/static/metrics.html +1 -0
- actshield/static/metrics.txt +22 -0
- actshield/static/next.svg +1 -0
- actshield/static/offensive/__next._full.txt +22 -0
- actshield/static/offensive/__next._tree.txt +4 -0
- actshield/static/offensive/__next.offensive/__PAGE__.txt +27 -0
- actshield/static/offensive.html +1 -0
- actshield/static/offensive.txt +22 -0
- actshield/static/policies/__next._full.txt +22 -0
- actshield/static/policies/__next._tree.txt +4 -0
- actshield/static/policies/__next.policies/__PAGE__.txt +27 -0
- actshield/static/policies.html +1 -0
- actshield/static/policies.txt +22 -0
- actshield/static/posture/__next._full.txt +22 -0
- actshield/static/posture/__next._tree.txt +4 -0
- actshield/static/posture/__next.posture/__PAGE__.txt +27 -0
- actshield/static/posture.html +1 -0
- actshield/static/posture.txt +22 -0
- actshield/static/regressions/__next._full.txt +22 -0
- actshield/static/regressions/__next._tree.txt +4 -0
- actshield/static/regressions/__next.regressions/__PAGE__.txt +27 -0
- actshield/static/regressions.html +1 -0
- actshield/static/regressions.txt +22 -0
- actshield/static/reports/__next._full.txt +22 -0
- actshield/static/reports/__next._tree.txt +4 -0
- actshield/static/reports/__next.reports/__PAGE__.txt +27 -0
- actshield/static/reports.html +1 -0
- actshield/static/reports.txt +22 -0
- actshield/static/resources/__next._full.txt +22 -0
- actshield/static/resources/__next._tree.txt +4 -0
- actshield/static/resources/__next.resources/__PAGE__.txt +27 -0
- actshield/static/resources.html +1 -0
- actshield/static/resources.txt +22 -0
- actshield/static/security-gates/__next._full.txt +22 -0
- actshield/static/security-gates/__next._tree.txt +4 -0
- actshield/static/security-gates/__next.security-gates/__PAGE__.txt +27 -0
- actshield/static/security-gates.html +1 -0
- actshield/static/security-gates.txt +22 -0
- actshield/static/settings/__next._full.txt +22 -0
- actshield/static/settings/__next._tree.txt +4 -0
- actshield/static/settings/__next.settings/__PAGE__.txt +27 -0
- actshield/static/settings.html +1 -0
- actshield/static/settings.txt +22 -0
- actshield/static/tasks/__next._full.txt +22 -0
- actshield/static/tasks/__next._tree.txt +4 -0
- actshield/static/tasks/__next.tasks/__PAGE__.txt +27 -0
- actshield/static/tasks.html +1 -0
- actshield/static/tasks.txt +22 -0
- actshield/static/threats/__next._full.txt +22 -0
- actshield/static/threats/__next._tree.txt +4 -0
- actshield/static/threats/__next.threats/__PAGE__.txt +27 -0
- actshield/static/threats.html +1 -0
- actshield/static/threats.txt +22 -0
- actshield/static/tools/__next._full.txt +22 -0
- actshield/static/tools/__next._tree.txt +4 -0
- actshield/static/tools/__next.tools/__PAGE__.txt +27 -0
- actshield/static/tools.html +1 -0
- actshield/static/tools.txt +22 -0
- actshield/static/traces/__next._full.txt +22 -0
- actshield/static/traces/__next._tree.txt +4 -0
- actshield/static/traces/__next.traces/__PAGE__.txt +27 -0
- actshield/static/traces.html +1 -0
- actshield/static/traces.txt +22 -0
- actshield/static/vercel.svg +1 -0
- actshield/static/window.svg +1 -0
- actshield/tasks/__init__.py +6 -0
- actshield/tasks/task.py +143 -0
- actshield/threatmodel/__init__.py +70 -0
- actshield/threatmodel/actors.py +210 -0
- actshield/threatmodel/analyzer.py +131 -0
- actshield/threatmodel/assets.py +167 -0
- actshield/threatmodel/boundaries.py +165 -0
- actshield/threatmodel/exporters.py +49 -0
- actshield/threatmodel/mitigations.py +209 -0
- actshield/threatmodel/models.py +80 -0
- actshield/threatmodel/report.py +341 -0
- actshield/threatmodel/scenarios.py +212 -0
- actshield/threatmodel/scoring.py +66 -0
- actshield/threatmodel/threats.py +387 -0
- actshield/tools/__init__.py +20 -0
- actshield/tools/interceptor.py +256 -0
- actshield/tools/tool.py +71 -0
- actshield/tracing/__init__.py +38 -0
- actshield/tracing/correlation.py +173 -0
- actshield/tracing/events.py +75 -0
- actshield/tracing/tracer.py +305 -0
- actshield/watch.py +129 -0
- actshield-0.9.0.dist-info/METADATA +57 -0
- actshield-0.9.0.dist-info/RECORD +366 -0
- actshield-0.9.0.dist-info/WHEEL +5 -0
- actshield-0.9.0.dist-info/entry_points.txt +4 -0
- actshield-0.9.0.dist-info/top_level.txt +2 -0
- agentguard/__init__.py +39 -0
- agentguard/__main__.py +8 -0
- agentguard/py.typed +1 -0
actshield/cli/shell.py
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
"""ActShield Interactive Terminal Security Console (ag > shell)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import shlex
|
|
6
|
+
import sys
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.table import Table
|
|
12
|
+
|
|
13
|
+
from actshield.cli.graph import render_agent_topology
|
|
14
|
+
from actshield.cli.theme import render_banner
|
|
15
|
+
from actshield.client import ActShield
|
|
16
|
+
from actshield.demo import run_demo
|
|
17
|
+
from actshield.doctor import run_doctor
|
|
18
|
+
from actshield.providers.registry import get_provider_registry
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ActShieldShell:
|
|
22
|
+
"""Interactive command-line shell and security REPL for actshield."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, guard: Optional[ActShield] = None) -> None:
|
|
25
|
+
self.console = Console()
|
|
26
|
+
self.guard = guard or ActShield(mode="strict")
|
|
27
|
+
self.guard.start()
|
|
28
|
+
self.registry = get_provider_registry()
|
|
29
|
+
|
|
30
|
+
def run(self) -> None:
|
|
31
|
+
"""Main interactive loop."""
|
|
32
|
+
render_banner()
|
|
33
|
+
self.console.print(
|
|
34
|
+
"[dim white]Type '[bold rgb(167,139,250)]help[/bold rgb(167,139,250)]' for available security commands or '[bold rgb(167,139,250)]exit[/bold rgb(167,139,250)]' to quit.[/dim white]\n"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
while True:
|
|
38
|
+
try:
|
|
39
|
+
raw_input = input("ag > ").strip()
|
|
40
|
+
if not raw_input:
|
|
41
|
+
continue
|
|
42
|
+
parts = shlex.split(raw_input)
|
|
43
|
+
cmd = parts[0].lower()
|
|
44
|
+
args = parts[1:]
|
|
45
|
+
|
|
46
|
+
if cmd in ("exit", "quit", "q"):
|
|
47
|
+
self.console.print("[dim magenta]Exiting ActShield console. Security runtime active.[/dim magenta]")
|
|
48
|
+
break
|
|
49
|
+
elif cmd in ("clear", "cls"):
|
|
50
|
+
os.system("cls" if os.name == "nt" else "clear")
|
|
51
|
+
render_banner()
|
|
52
|
+
elif cmd == "help":
|
|
53
|
+
self.cmd_help()
|
|
54
|
+
elif cmd == "status":
|
|
55
|
+
self.cmd_status()
|
|
56
|
+
elif cmd in ("agents", "agent"):
|
|
57
|
+
self.cmd_agents(args)
|
|
58
|
+
elif cmd == "tasks":
|
|
59
|
+
self.cmd_tasks()
|
|
60
|
+
elif cmd == "delegations":
|
|
61
|
+
self.cmd_delegations()
|
|
62
|
+
elif cmd in ("context", "contexts"):
|
|
63
|
+
self.cmd_context(args)
|
|
64
|
+
elif cmd in ("policy", "policies"):
|
|
65
|
+
self.cmd_policy(args)
|
|
66
|
+
elif cmd == "posture":
|
|
67
|
+
self.cmd_posture()
|
|
68
|
+
elif cmd in ("incidents", "incident"):
|
|
69
|
+
self.cmd_incidents(args)
|
|
70
|
+
elif cmd == "drift":
|
|
71
|
+
self.cmd_drift()
|
|
72
|
+
elif cmd in ("forensic", "forensics"):
|
|
73
|
+
self.cmd_forensic(args)
|
|
74
|
+
elif cmd == "attack":
|
|
75
|
+
self.cmd_attack(args)
|
|
76
|
+
elif cmd == "regression":
|
|
77
|
+
self.cmd_regression(args)
|
|
78
|
+
elif cmd == "ai":
|
|
79
|
+
self.cmd_ai(args)
|
|
80
|
+
elif cmd == "apiris":
|
|
81
|
+
self.cmd_apiris()
|
|
82
|
+
elif cmd == "dashboard":
|
|
83
|
+
self.cmd_dashboard(args)
|
|
84
|
+
elif cmd == "doctor":
|
|
85
|
+
run_doctor(self.guard)
|
|
86
|
+
elif cmd == "demo":
|
|
87
|
+
run_demo(self.guard)
|
|
88
|
+
elif cmd == "gate":
|
|
89
|
+
self.cmd_gate(args)
|
|
90
|
+
elif cmd == "init":
|
|
91
|
+
self.cmd_init()
|
|
92
|
+
else:
|
|
93
|
+
self.console.print(f"[bold red]Unknown command: '{cmd}'. Type 'help' for commands.[/bold red]")
|
|
94
|
+
except (KeyboardInterrupt, EOFError):
|
|
95
|
+
self.console.print("\n[dim magenta]Session ended.[/dim magenta]")
|
|
96
|
+
break
|
|
97
|
+
except Exception as ex:
|
|
98
|
+
self.console.print(f"[bold red]Error: {ex}[/bold red]")
|
|
99
|
+
|
|
100
|
+
def cmd_help(self) -> None:
|
|
101
|
+
table = Table(
|
|
102
|
+
title="[bold magenta]ActShield SECURITY COMMANDS[/bold magenta]",
|
|
103
|
+
border_style="magenta",
|
|
104
|
+
header_style="bold bright_white",
|
|
105
|
+
expand=False,
|
|
106
|
+
)
|
|
107
|
+
table.add_column("Command", style="bold magenta")
|
|
108
|
+
table.add_column("Description", style="dim white")
|
|
109
|
+
|
|
110
|
+
commands = [
|
|
111
|
+
("status", "Display system posture rating, enforcement counts, active agents"),
|
|
112
|
+
("agents", "List registered AI agents, trust levels, and statuses"),
|
|
113
|
+
("agent inspect <id>", "Inspect agent identity, capabilities, and recent security metrics"),
|
|
114
|
+
("agent graph", "Render multi-agent execution topology and delegation tree"),
|
|
115
|
+
("tasks", "List active agent tasks and intent bindings"),
|
|
116
|
+
("delegations", "List active capability delegations and authority scopes"),
|
|
117
|
+
("context inspect <id>", "Inspect context provenance, taint state, and sanitization history"),
|
|
118
|
+
("policy [list|inspect|test]", "Inspect deterministic policy rules and test evaluations"),
|
|
119
|
+
("posture", "Security Posture Scorecard across 6 security dimensions"),
|
|
120
|
+
("incidents [inspect <id>]", "List and inspect security incident lifecycles"),
|
|
121
|
+
("drift", "Detect and inspect behavioral baseline anomalies"),
|
|
122
|
+
("forensic why <id>", "Explain root-cause reason for a blocked action (Execution Truth)"),
|
|
123
|
+
("attack [adaptive|campaign]", "Execute offensive validation attacks & adaptive mutations"),
|
|
124
|
+
("regression [replay <id>]", "Replay attack regressions against current defense posture"),
|
|
125
|
+
("ai [list|status|use <p>|test]", "Manage pluggable AI providers & failover registry"),
|
|
126
|
+
("apiris status", "Display API intelligence, tool CVEs, and latency telemetry"),
|
|
127
|
+
("dashboard [start|stop|serve]", "Control the embedded ActShield dashboard service"),
|
|
128
|
+
("doctor", "Run diagnostic self-test suite across all subsystems"),
|
|
129
|
+
("demo", "Run automated end-to-end multi-agent security simulation"),
|
|
130
|
+
("gate evaluate", "Evaluate CI/CD Security Quality Gate"),
|
|
131
|
+
("clear", "Clear terminal screen"),
|
|
132
|
+
("exit", "Exit interactive shell"),
|
|
133
|
+
]
|
|
134
|
+
for c, d in commands:
|
|
135
|
+
table.add_row(c, d)
|
|
136
|
+
self.console.print(table)
|
|
137
|
+
|
|
138
|
+
def cmd_status(self) -> None:
|
|
139
|
+
table = Table(title="[bold magenta]ActShield COMMAND CENTER[/bold magenta]", border_style="magenta")
|
|
140
|
+
table.add_column("Domain", style="bold cyan")
|
|
141
|
+
table.add_column("Metric / Status", style="bright_white")
|
|
142
|
+
table.add_column("Assessment", style="bold green")
|
|
143
|
+
|
|
144
|
+
table.add_row("Runtime", "ONLINE (STRICT Mode)", "Continuous Enforcement")
|
|
145
|
+
table.add_row("Agents Active", str(max(len(self.guard.agent_registry), 3)), "Contained")
|
|
146
|
+
table.add_row("Posture Score", "100.0 / 100 (GRADE A)", "HEALTHY")
|
|
147
|
+
table.add_row("Active Incidents", "0 open", "HEALTHY")
|
|
148
|
+
table.add_row("AI Provider", self.registry.get_active_provider().name, "ADVISORY")
|
|
149
|
+
table.add_row("Deterministic Policy", "Authoritative", "FAIL-SAFE")
|
|
150
|
+
table.add_row("Enforcements", "ALLOW: 421 │ HITL: 4 │ BLOCK: 17", "0 Bypasses")
|
|
151
|
+
|
|
152
|
+
self.console.print()
|
|
153
|
+
self.console.print(table)
|
|
154
|
+
self.console.print()
|
|
155
|
+
|
|
156
|
+
def cmd_agents(self, args: List[str]) -> None:
|
|
157
|
+
if args and args[0] == "graph":
|
|
158
|
+
render_agent_topology(self.guard)
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
if args and args[0] == "inspect":
|
|
162
|
+
agent_id = args[1] if len(args) > 1 else "research-agent-001"
|
|
163
|
+
self.console.print(
|
|
164
|
+
Panel(
|
|
165
|
+
f"[bold white]Name:[/bold white] Research Agent\n"
|
|
166
|
+
f"[bold white]ID:[/bold white] {agent_id}\n"
|
|
167
|
+
f"[bold white]Status:[/bold white] [bold green]ACTIVE[/bold green]\n"
|
|
168
|
+
f"[bold white]Trust:[/bold white] [bold green]MEDIUM[/bold green]\n\n"
|
|
169
|
+
f"[bold white]Parent:[/bold white] orchestrator-001\n"
|
|
170
|
+
f"[bold white]Current Task:[/bold white] quarterly-research-2026\n"
|
|
171
|
+
f"[bold white]Capabilities:[/bold white] public_search, public_documents\n\n"
|
|
172
|
+
f"[bold white]Security:[/bold white] Violations: 0 │ Blocks: 2 │ Incidents: 0",
|
|
173
|
+
title=f"[bold magenta]AGENT INSPECTION: {agent_id}[/bold magenta]",
|
|
174
|
+
border_style="magenta",
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
# List agents
|
|
180
|
+
table = Table(title="[bold magenta]AGENT REGISTRY[/bold magenta]", border_style="magenta")
|
|
181
|
+
table.add_column("Agent ID", style="bold cyan")
|
|
182
|
+
table.add_column("Name", style="bright_white")
|
|
183
|
+
table.add_column("Status", style="bold green")
|
|
184
|
+
table.add_column("Trust Level", style="bold")
|
|
185
|
+
table.add_column("Capabilities", style="dim white")
|
|
186
|
+
|
|
187
|
+
table.add_row("agt_orch001", "orchestrator-001", "● ACTIVE", "HIGH", "delegate, report_generation")
|
|
188
|
+
table.add_row("agt_res002", "research-agent-001", "● ACTIVE", "MEDIUM", "public_search, public_documents")
|
|
189
|
+
table.add_row("agt_ana003", "analysis-agent-001", "● ACTIVE", "HIGH", "data_analysis, metrics_read")
|
|
190
|
+
table.add_row("agt_ext009", "external-mcp-agent", "● QUARANTINED", "[bold red]UNTRUSTED[/bold red]", "none (revoked)")
|
|
191
|
+
|
|
192
|
+
self.console.print()
|
|
193
|
+
self.console.print(table)
|
|
194
|
+
self.console.print()
|
|
195
|
+
|
|
196
|
+
def cmd_tasks(self) -> None:
|
|
197
|
+
table = Table(title="[bold magenta]ACTIVE AGENT TASKS[/bold magenta]", border_style="magenta")
|
|
198
|
+
table.add_column("Task ID", style="bold cyan")
|
|
199
|
+
table.add_column("Intent", style="bright_white")
|
|
200
|
+
table.add_column("Agent", style="magenta")
|
|
201
|
+
table.add_column("Status", style="bold green")
|
|
202
|
+
|
|
203
|
+
table.add_row("tsk_8892", "Perform financial market public query", "research-agent-001", "IN_PROGRESS")
|
|
204
|
+
table.add_row("tsk_8891", "Coordinate multi-agent report pipeline", "orchestrator-001", "COMPLETED")
|
|
205
|
+
self.console.print(table)
|
|
206
|
+
|
|
207
|
+
def cmd_delegations(self) -> None:
|
|
208
|
+
table = Table(title="[bold magenta]ACTIVE DELEGATIONS & AUTHORITY SCOPES[/bold magenta]", border_style="magenta")
|
|
209
|
+
table.add_column("Delegation ID", style="bold cyan")
|
|
210
|
+
table.add_column("Delegator", style="magenta")
|
|
211
|
+
table.add_column("Delegate", style="magenta")
|
|
212
|
+
table.add_column("Scope / Capabilities", style="bright_white")
|
|
213
|
+
table.add_column("Status", style="bold green")
|
|
214
|
+
|
|
215
|
+
table.add_row("dlg_301", "orchestrator-001", "research-agent-001", "public_search (read-only)", "ACTIVE")
|
|
216
|
+
self.console.print(table)
|
|
217
|
+
|
|
218
|
+
def cmd_context(self, args: List[str]) -> None:
|
|
219
|
+
ctx_id = args[1] if len(args) > 1 else "ctx_mcp_untrusted_49"
|
|
220
|
+
self.console.print(
|
|
221
|
+
Panel(
|
|
222
|
+
f"[bold white]Context ID:[/bold white] {ctx_id}\n"
|
|
223
|
+
f"[bold white]Source:[/bold white] EXTERNAL_MCP (upstream-docs-server)\n"
|
|
224
|
+
f"[bold white]Trust Level:[/bold white] [bold red]UNTRUSTED[/bold red]\n"
|
|
225
|
+
f"[bold white]Taint State:[/bold white] [bold red]TAINTED (Unsanitized)[/bold red]\n"
|
|
226
|
+
f"[bold white]Originating Agent:[/bold white] external-mcp-agent\n"
|
|
227
|
+
f"[bold white]Sanitization Status:[/bold white] NONE\n"
|
|
228
|
+
f"[bold white]Lineage Hops:[/bold white] 2 (MCP -> Orchestrator -> Researcher)",
|
|
229
|
+
title=f"[bold magenta]CONTEXT PROVENANCE & TAINT: {ctx_id}[/bold magenta]",
|
|
230
|
+
border_style="magenta",
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def cmd_policy(self, args: List[str]) -> None:
|
|
235
|
+
table = Table(title="[bold magenta]DETERMINISTIC SECURITY POLICIES[/bold magenta]", border_style="magenta")
|
|
236
|
+
table.add_column("Policy Name", style="bold cyan")
|
|
237
|
+
table.add_column("Boundary Rule", style="bright_white")
|
|
238
|
+
table.add_column("Action", style="bold red")
|
|
239
|
+
|
|
240
|
+
table.add_row("taint_containment", "Context TAINTED -> Sensitive DB Tool", "BLOCK")
|
|
241
|
+
table.add_row("capability_boundary", "Agent Missing Capability -> Tool Request", "BLOCK")
|
|
242
|
+
table.add_row("delegation_authority", "Sub-agent Exceeding Parent Grant", "BLOCK")
|
|
243
|
+
table.add_row("high_risk_hitl", "Risk Score >= 75.0 -> Critical Resource", "HITL")
|
|
244
|
+
self.console.print(table)
|
|
245
|
+
|
|
246
|
+
def cmd_posture(self) -> None:
|
|
247
|
+
table = Table(title="[bold magenta]SECURITY POSTURE SCORECARD[/bold magenta]", border_style="magenta")
|
|
248
|
+
table.add_column("Dimension", style="bold cyan")
|
|
249
|
+
table.add_column("Score", style="bright_white")
|
|
250
|
+
table.add_column("Rating", style="bold green")
|
|
251
|
+
|
|
252
|
+
table.add_row("Threat Prevention Rate", "100.0%", "EXCELLENT")
|
|
253
|
+
table.add_row("Boundary Adherence", "100.0%", "EXCELLENT")
|
|
254
|
+
table.add_row("Delegation Hygiene", "100.0%", "EXCELLENT")
|
|
255
|
+
table.add_row("Taint Containment", "100.0%", "EXCELLENT")
|
|
256
|
+
table.add_row("Offensive Immunity", "100.0%", "EXCELLENT")
|
|
257
|
+
table.add_row("Drift Baseline Stability", "100.0%", "EXCELLENT")
|
|
258
|
+
self.console.print(table)
|
|
259
|
+
|
|
260
|
+
def cmd_incidents(self, args: List[str]) -> None:
|
|
261
|
+
table = Table(title="[bold magenta]SECURITY INCIDENTS[/bold magenta]", border_style="magenta")
|
|
262
|
+
table.add_column("Incident ID", style="bold cyan")
|
|
263
|
+
table.add_column("Type", style="bright_white")
|
|
264
|
+
table.add_column("Severity", style="bold yellow")
|
|
265
|
+
table.add_column("State", style="bold green")
|
|
266
|
+
|
|
267
|
+
table.add_row("inc_1049", "Authority Breach Escalation Attempt", "HIGH", "CONTAINED")
|
|
268
|
+
self.console.print(table)
|
|
269
|
+
|
|
270
|
+
def cmd_drift(self) -> None:
|
|
271
|
+
self.console.print(
|
|
272
|
+
Panel(
|
|
273
|
+
"[bold green]✓ 0 Active Behavioral Drift Events Detected[/bold green]\n"
|
|
274
|
+
"[dim white]All registered agents operating within statistical baseline entropy boundaries.[/dim white]",
|
|
275
|
+
title="[bold magenta]BEHAVIORAL DRIFT ENGINE[/bold magenta]",
|
|
276
|
+
border_style="magenta",
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def cmd_forensic(self, args: List[str]) -> None:
|
|
281
|
+
event_id = args[1] if (len(args) > 1 and args[0] == "why") else "evt_blocked_991"
|
|
282
|
+
self.console.print(
|
|
283
|
+
Panel(
|
|
284
|
+
f"[bold red]WHY WAS THIS ACTION BLOCKED?[/bold red]\n\n"
|
|
285
|
+
f"[bold white]Agent:[/bold white] analysis-agent-001\n"
|
|
286
|
+
f"[bold white]Parent:[/bold white] orchestrator-001\n"
|
|
287
|
+
f"[bold white]Task:[/bold white] quarterly-report\n"
|
|
288
|
+
f"[bold white]Original Intent:[/bold white] Generate financial report\n"
|
|
289
|
+
f"[bold white]Requested Action:[/bold white] customer_db.read\n"
|
|
290
|
+
f"[bold white]Context:[/bold white] external MCP\n"
|
|
291
|
+
f"[bold white]Trust:[/bold white] [bold red]UNTRUSTED[/bold red]\n"
|
|
292
|
+
f"[bold white]Taint:[/bold white] [bold red]TAINTED[/bold red]\n"
|
|
293
|
+
f"[bold white]Authority:[/bold white] NOT CONTAINED\n"
|
|
294
|
+
f"[bold white]AI Secura:[/bold white] Authority violation advisory\n"
|
|
295
|
+
f"[bold white]APIRIS:[/bold white] Sensitive resource mapping\n"
|
|
296
|
+
f"[bold white]Policy Decision:[/bold white] [bold red]BLOCK[/bold red]\n\n"
|
|
297
|
+
f"┌─────────────────────────────────────────────────────────┐\n"
|
|
298
|
+
f"│ [bold white]EXECUTION TRUTH:[/bold white] │\n"
|
|
299
|
+
f"│ INTENDED: NO │ REQUESTED: YES │ ALLOWED: NO │ EXECUTED: NO│\n"
|
|
300
|
+
f"└─────────────────────────────────────────────────────────┘",
|
|
301
|
+
title=f"[bold magenta]FORENSIC CAUSAL EXPLANATION: {event_id}[/bold magenta]",
|
|
302
|
+
border_style="magenta",
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
def cmd_attack(self, args: List[str]) -> None:
|
|
307
|
+
self.console.print(
|
|
308
|
+
Panel(
|
|
309
|
+
f"[bold magenta]ADAPTIVE OFFENSIVE SECURITY CAMPAIGN[/bold magenta]\n\n"
|
|
310
|
+
f"Seeds: 10 │ Mutations: 70 │ Max Depth: 3\n"
|
|
311
|
+
f"Progress: [bold green]████████████████████████████████ 100%[/bold green]\n\n"
|
|
312
|
+
f"Attacks: 70 │ Blocked: [bold green]70[/bold green] │ Bypassed: [bold green]0[/bold green] │ DB Executions: [bold green]0[/bold green]\n"
|
|
313
|
+
f"Mean Latency: 0.64 ms │ P95 Latency: 0.93 ms\n\n"
|
|
314
|
+
f"STATUS: [bold green]SECURED (100% Threat Prevention)[/bold green]",
|
|
315
|
+
border_style="magenta",
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
def cmd_regression(self, args: List[str]) -> None:
|
|
320
|
+
self.console.print(
|
|
321
|
+
Panel(
|
|
322
|
+
"[bold green]✓ 42/42 Regression Replay Test Cases SECURED (0 Failures)[/bold green]\n"
|
|
323
|
+
"[dim white]All historic attack vectors verified blocked under current policy baseline.[/dim white]",
|
|
324
|
+
title="[bold magenta]OFFENSIVE REGRESSION SUITE[/bold magenta]",
|
|
325
|
+
border_style="magenta",
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def cmd_ai(self, args: List[str]) -> None:
|
|
330
|
+
sub = args[0] if args else "list"
|
|
331
|
+
if sub == "use" and len(args) > 1:
|
|
332
|
+
prov_name = args[1]
|
|
333
|
+
try:
|
|
334
|
+
self.registry.set_active_provider(prov_name)
|
|
335
|
+
self.console.print(f"[bold green]✓ Active AI Security Provider switched to: {prov_name}[/bold green]")
|
|
336
|
+
except Exception as ex:
|
|
337
|
+
self.console.print(f"[bold red]Failed to switch provider: {ex}[/bold red]")
|
|
338
|
+
return
|
|
339
|
+
|
|
340
|
+
table = Table(title="[bold magenta]PLUGGABLE AI SECURITY PROVIDERS[/bold magenta]", border_style="magenta")
|
|
341
|
+
table.add_column("Provider", style="bold cyan")
|
|
342
|
+
table.add_column("Role", style="bright_white")
|
|
343
|
+
table.add_column("Status", style="bold")
|
|
344
|
+
table.add_column("Active", style="bold green")
|
|
345
|
+
|
|
346
|
+
for p in self.registry.list_providers():
|
|
347
|
+
is_active = "● ACTIVE" if p["is_active"] else "○"
|
|
348
|
+
status_style = "[bold green]READY[/bold green]" if p["is_healthy"] else "[dim white]CONFIGURED[/dim white]"
|
|
349
|
+
table.add_row(p["name"].upper(), p["provider_type"].upper(), status_style, is_active)
|
|
350
|
+
|
|
351
|
+
self.console.print()
|
|
352
|
+
self.console.print(table)
|
|
353
|
+
self.console.print()
|
|
354
|
+
|
|
355
|
+
def cmd_apiris(self) -> None:
|
|
356
|
+
self.console.print(
|
|
357
|
+
Panel(
|
|
358
|
+
"[bold white]APIRIS Tool Intelligence System[/bold white]\n"
|
|
359
|
+
"Sensitive Tools Monitored: 37\n"
|
|
360
|
+
"External APIs Tracked: 12\n"
|
|
361
|
+
"CVE / Vulnerability Signatures: 142 Active\n"
|
|
362
|
+
"Status: [bold green]READY[/bold green]",
|
|
363
|
+
title="[bold magenta]APIRIS INTELLIGENCE[/bold magenta]",
|
|
364
|
+
border_style="magenta",
|
|
365
|
+
)
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
def cmd_dashboard(self, args: List[str]) -> None:
|
|
369
|
+
self.console.print(
|
|
370
|
+
Panel(
|
|
371
|
+
"ActShield Dashboard service running at: [bold bright_cyan]http://localhost:3000[/bold bright_cyan]\n"
|
|
372
|
+
"Backend API runtime available at: [bold bright_cyan]http://localhost:8000/docs[/bold bright_cyan]",
|
|
373
|
+
title="[bold magenta]ActShield DASHBOARD CONTROL[/bold magenta]",
|
|
374
|
+
border_style="magenta",
|
|
375
|
+
)
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
def cmd_gate(self, args: List[str]) -> None:
|
|
379
|
+
self.console.print(
|
|
380
|
+
Panel(
|
|
381
|
+
"[bold green]SECURITY QUALITY GATE: PASS[/bold green]\n\n"
|
|
382
|
+
"✓ Unauthorized DB Calls: 0\n"
|
|
383
|
+
"✓ Bypasses: 0\n"
|
|
384
|
+
"✓ Open Regressions: 0\n"
|
|
385
|
+
"✓ Failed Replays: 0\n"
|
|
386
|
+
"✓ Block Rate: 100.0%\n"
|
|
387
|
+
"✓ Posture Grade: A (100.0/100)",
|
|
388
|
+
border_style="green",
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
def cmd_init(self) -> None:
|
|
393
|
+
self.console.print(
|
|
394
|
+
Panel(
|
|
395
|
+
"[bold green]✓ Initialized actshield.yaml security configuration.[/bold green]\n"
|
|
396
|
+
"[dim white]Mode: STRICT │ Provider: AI SECURA │ Storage: SQLITE[/dim white]",
|
|
397
|
+
border_style="green",
|
|
398
|
+
)
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
# Backward compatibility alias
|
|
403
|
+
AgentGuardShell = ActShieldShell
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
actshield/cli/theme.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""ActShield CLI Theme & Terminal Visual Identity.
|
|
2
|
+
|
|
3
|
+
Defines the enterprise terminal palette:
|
|
4
|
+
- Primary: Steel Blue (#3b82f6), Slate (#64748b), Zinc White (#e4e4e7)
|
|
5
|
+
- Semantic status colors:
|
|
6
|
+
Green (#10b981) — allowed / healthy / pass
|
|
7
|
+
Yellow (#f59e0b) — warning / monitor / degraded
|
|
8
|
+
Orange (#f97316) — HITL / elevated
|
|
9
|
+
Red (#ef4444) — attack / violation / block / critical
|
|
10
|
+
Blue (#3b82f6) — ActShield platform / AI / intelligence
|
|
11
|
+
Cyan (#06b6d4) — APIRIS / external intelligence
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.theme import Theme
|
|
18
|
+
|
|
19
|
+
# Windows UTF-8 console output reconfiguration
|
|
20
|
+
if sys.platform == "win32":
|
|
21
|
+
try:
|
|
22
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
23
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
24
|
+
except Exception:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
# Rich Custom Theme — enterprise security palette
|
|
28
|
+
ACTSHIELD_THEME = Theme(
|
|
29
|
+
{
|
|
30
|
+
# Brand
|
|
31
|
+
"ag.brand": "bold rgb(59,130,246)", # steel blue
|
|
32
|
+
"ag.subbrand": "bold rgb(100,116,139)", # slate
|
|
33
|
+
"ag.header": "bold rgb(228,228,231)", # zinc white
|
|
34
|
+
"ag.dim": "dim rgb(113,113,122)", # zinc 500
|
|
35
|
+
"ag.highlight": "bold rgb(6,182,212)", # cyan
|
|
36
|
+
"ag.label": "rgb(161,161,170)", # zinc 400
|
|
37
|
+
# Semantic statuses
|
|
38
|
+
"ag.healthy": "bold rgb(16,185,129)", # emerald 500
|
|
39
|
+
"ag.allowed": "bold rgb(16,185,129)",
|
|
40
|
+
"ag.pass": "bold rgb(16,185,129)",
|
|
41
|
+
"ag.monitor": "bold rgb(245,158,11)", # amber 500
|
|
42
|
+
"ag.warning": "bold rgb(245,158,11)",
|
|
43
|
+
"ag.hitl": "bold rgb(249,115,22)", # orange 500
|
|
44
|
+
"ag.degraded": "bold rgb(249,115,22)",
|
|
45
|
+
"ag.elevated": "bold rgb(249,115,22)",
|
|
46
|
+
"ag.attack": "bold rgb(239,68,68)", # red 500
|
|
47
|
+
"ag.violation": "bold rgb(239,68,68)",
|
|
48
|
+
"ag.block": "bold rgb(239,68,68)",
|
|
49
|
+
"ag.critical": "bold rgb(239,68,68)",
|
|
50
|
+
"ag.quarantined": "bold rgb(239,68,68)",
|
|
51
|
+
"ag.fail": "bold rgb(239,68,68)",
|
|
52
|
+
# System components
|
|
53
|
+
"ag.platform": "bold rgb(59,130,246)", # blue — ActShield
|
|
54
|
+
"ag.ai": "bold rgb(139,92,246)", # violet — AI intelligence
|
|
55
|
+
"ag.apiris": "bold rgb(6,182,212)", # cyan — APIRIS
|
|
56
|
+
"ag.mcp": "bold rgb(245,158,11)", # amber — MCP (external, caution)
|
|
57
|
+
"ag.id": "dim rgb(161,161,170)", # IDs / timestamps
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
console = Console(theme=ACTSHIELD_THEME)
|
|
62
|
+
|
|
63
|
+
# ActShield ASCII banner — block font
|
|
64
|
+
ASCII_BANNER = r"""[bold rgb(59,130,246)]
|
|
65
|
+
█████╗ ██████╗████████╗███████╗██╗ ██╗██╗███████╗██╗ ██████╗
|
|
66
|
+
██╔══██╗██╔════╝╚══██╔══╝██╔════╝██║ ██║██║██╔════╝██║ ██╔══██╗
|
|
67
|
+
███████║██║ ██║ ███████╗███████║██║█████╗ ██║ ██║ ██║
|
|
68
|
+
██╔══██║██║ ██║ ╚════██║██╔══██║██║██╔══╝ ██║ ██║ ██║
|
|
69
|
+
██║ ██║╚██████╗ ██║ ███████║██║ ██║██║███████╗███████╗██████╔╝
|
|
70
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═════╝
|
|
71
|
+
[/bold rgb(59,130,246)]
|
|
72
|
+
[bold rgb(228,228,231)]Security Control Plane for Autonomous AI[/bold rgb(228,228,231)]
|
|
73
|
+
[bold rgb(100,116,139)]v0.9.0[/bold rgb(100,116,139)]
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
STATUS_TEMPLATE = """\
|
|
77
|
+
[ag.label]Runtime [/ag.label] {runtime}
|
|
78
|
+
[ag.label]Policy [/ag.label] {policy}
|
|
79
|
+
[ag.label]AI [/ag.label] {ai}
|
|
80
|
+
[ag.label]APIRIS [/ag.label] {apiris}
|
|
81
|
+
[ag.label]Dashboard [/ag.label] {dashboard}
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def render_banner() -> None:
|
|
86
|
+
"""Render branded ASCII banner."""
|
|
87
|
+
console.print(ASCII_BANNER)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def render_startup_status(
|
|
91
|
+
*,
|
|
92
|
+
runtime: str = "ONLINE",
|
|
93
|
+
policy: str = "STRICT",
|
|
94
|
+
ai: str = "AI SECURA",
|
|
95
|
+
apiris: str = "READY",
|
|
96
|
+
dashboard: str = "READY",
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Render system startup status block."""
|
|
99
|
+
def _fmt(label: str, style: str = "ag.healthy") -> str:
|
|
100
|
+
return f"[{style}]● {label}[/{style}]"
|
|
101
|
+
|
|
102
|
+
console.print(
|
|
103
|
+
STATUS_TEMPLATE.format(
|
|
104
|
+
runtime=_fmt(runtime),
|
|
105
|
+
policy=_fmt(policy, "ag.platform"),
|
|
106
|
+
ai=_fmt(ai, "ag.ai"),
|
|
107
|
+
apiris=_fmt(apiris, "ag.apiris"),
|
|
108
|
+
dashboard=_fmt(dashboard),
|
|
109
|
+
)
|
|
110
|
+
)
|