AI Copilot — multi-provider security assistant
A partir da v4.8, o CipherVault inclui um AI Copilot plugável a quatro backends LLM, com redactor obrigatório em todos os prompts (secrets, tokens, PII, IPs internos mascarados antes do egress) e cost meter per-tenant.
Cinco capabilities expostas como endpoints REST + widget de chat flutuante na UI.
Providers suportados
| Provider | Use case | Auth |
|---|---|---|
| OpenAI | SaaS default, lowest latency | API key |
| Azure OpenAI | Enterprise compliance + data residency | API key + endpoint |
| AWS Bedrock (Claude) | AWS-native, IAM-driven, BAA disponível | IRSA / IAM role |
| Ollama | Self-hosted, air-gap, modelos local Llama/Mistral | HTTP local |
Default: nenhum. Copilot é opt-in via env (proprietários querem ler o contrato com cada provider antes de habilitar).
# Pick one:
export CV_COPILOT_PROVIDER=openai
export OPENAI_API_KEY=sk-...
# OU
export CV_COPILOT_PROVIDER=azure-openai
export AZURE_OPENAI_API_KEY=...
export AZURE_OPENAI_ENDPOINT=https://acme.openai.azure.com/
export AZURE_OPENAI_DEPLOYMENT=gpt-4o
# OU
export CV_COPILOT_PROVIDER=bedrock-claude
# IAM role via IRSA (sem keys)
export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID=anthropic.claude-sonnet-4-6-...
# OU
export CV_COPILOT_PROVIDER=ollama
export OLLAMA_URL=http://localhost:11434
export OLLAMA_MODEL=llama3.1:70b
Redactor — sempre on, sem opt-out
Antes de qualquer prompt sair do CV, passa por
backend/src/lib/copilot/redactor.js:
- Regex de credenciais (AWS access keys, Stripe
sk_live_, GitHubghp_, GitLabglpat-, generic API key patterns) - Hash de email PII (substituído por
<email:sha8>) - IPs RFC1918 + RFC6598 + IPv6 ULA mascarados
- Secret values do CV detectados via prefix
cv:vault/...→ blocked completamente (não é redacted; é refused)
Nada disso é opt-out. Se você não confia no provider, use Ollama self-hosted.
Cost meter
Per-tenant, persistido em copilot_usage:
GET /copilot/usage
# → {
# "tenant_id": 42,
# "this_month": {
# "tokens_input": 1234567,
# "tokens_output": 234567,
# "cost_usd": 12.34,
# "by_provider": { "openai": 9.5, "bedrock-claude": 2.84 }
# },
# "limit_usd": 50.00,
# "limit_reached": false
# }
Tenant pode setar hard cap mensal em settings. Ao atingir → 429 com mensagem clara.
Capabilities (5 endpoints)
1. POST /copilot/explain-risk
Explica por que um secret tem risk score alto:
curl -X POST .../copilot/explain-risk -d '{"secret_id": 1234}'
# → "Esse secret tem score 87/100 alto porque (1) não rotacionado há
# 180 dias, (2) compartilhado entre 3 vaults, (3) appears em 2 audit
# events recentes de unusual hours..."
2. POST /copilot/summarize-path
Sumariza um Attack Path:
curl -X POST .../copilot/summarize-path -d '{"attack_path_id": 99}'
# → "Esse attack path em 4 hops começa com leaked GitHub token em
# repo público (Risk #1234), permite acesso ao AWS via OIDC
# federation com role over-permissioned, escala pra Secrets
# Manager prod via sts:AssumeRole..."
3. POST /copilot/validation-tasks
Gera checklist de validação pra vault/policy:
curl -X POST .../copilot/validation-tasks \
-d '{"vault_id": 42, "policy": "pci-dss-4.0"}'
# → [
# "Verifique que todos os secrets em vault 42 têm rotation < 90d (PCI 8.3.9)",
# "Confirme RBAC com least-privilege — atualmente 14 users com 'owner'",
# ...
# ]
4. POST /copilot/chat
Free-form Q&A com history:
curl -X POST .../copilot/chat \
-d '{
"messages": [
{"role": "user", "content": "Como roto chaves SSH em hosts production?"}
]
}'
History per-tenant persistido em copilot_chat_history (retention 30d
configurável). RAG indexa docs do CV pra grounded responses com citation
chips.
5. POST /copilot/generate-code
Gera código para integrar CV em apps. Passa por lint guard-rails antes de retornar:
curl -X POST .../copilot/generate-code -d '{
"language": "python",
"prompt": "Fetch secret X from vault Y and use as DATABASE_URL"
}'
# → código + warnings caso template inclua hardcoded fallback
Lint check rejeita output com:
- Hardcoded secret string (
password = "abc123") urllib.requestsem TLS verify- Pickle /
evalem untrusted input - Token printado em stdout/logs
Se lint falhar, retorna com lint_violations: [...] + suggestion
auto-fix.
RAG (Retrieval Augmented Generation)
backend/src/lib/copilot/rag.js indexa:
docs/do produto (Markdown)CHANGELOG.md- Operator runbooks em
docs/runbooks/ - API spec (
openapi.json)
Vector store em-memory (default) ou Pinecone/Qdrant (opt-in via env). Embedding via mesmo provider (OpenAI text-embed, ou Ollama nomic-embed). Top-K=5 chunks injetados no system prompt antes do call ao LLM.
UI — Chat widget
Floating button bottom-right em todas as páginas. Click → slide-over com:
- Streaming tokens (Server-Sent Events)
- History per-tenant (truncated 30d)
- Citation chips — clicks abrem doc relevante
- Copy code button em blocos code (rendered Markdown)
Disponível como <CopilotChat /> component reusável; admin pode embed
em outras páginas custom.
Observabilidade
Prometheus metrics:
cv_copilot_requests_total{provider, capability, status}
cv_copilot_tokens_total{provider, kind="input|output"}
cv_copilot_cost_usd_total{provider}
cv_copilot_redactions_total{kind="aws|stripe|github|...|cv-secret"}
cv_copilot_lint_violations_total{language, rule}
cv_copilot_rag_hits{source}
Limitações
- Sem function calling — capabilities expostas são as 5 acima. Não use Copilot como agent (ainda).
- No image/audio — text-only.
- Rate-limit per-tenant: 60 req/min default; override em config.
- History em chat NÃO sai do CV — Copilot tem retenção própria; provider apenas vê os messages enviados (após redactor)
Referências
backend/src/lib/copilot/ebackend/src/routes/copilot.jsno repo do produto- Issue #223 — epic
- Blog post v4.8