Projetos e recursos aninhados
Grupo /platform/projects/* — projetos e todos os recursos aninhados (workspaces, casos, revisões, versões, membros, auditoria, qualidade, impacto).
Todos os endpoints exigem contexto de organização e o usuário/chave precisa ter permissão no projeto específico — acesso a projeto de outra organização retorna 404.
Tabela resumo (por bloco)
Dashboard e CRUD
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/dashboard | project:view |
| GET | /platform/projects | project:view |
| POST | /platform/projects | project:create |
| GET | /platform/projects/{project_id} | project:view |
| PATCH | /platform/projects/{project_id} | project:edit |
| GET | /platform/projects/{project_id}/overview | project:view |
| GET | /platform/projects/{project_id}/report | project:view |
| POST | /platform/projects/{project_id}/impact/{workspace_id} | project:view |
Conteúdo (regras e decoders do projeto)
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/rules | project:view |
| GET | /platform/projects/{project_id}/decoders | project:view |
Qualidade
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/quality-gate | project:view |
| PATCH | /platform/projects/{project_id}/quality-gate | project:edit |
Casos de teste
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/cases | project:view |
| POST | /platform/projects/{project_id}/cases | case:edit |
| PATCH | /platform/projects/{project_id}/cases/{case_id} | case:edit |
| DELETE | /platform/projects/{project_id}/cases/{case_id} | case:edit |
| POST | /platform/projects/{project_id}/cases/run | case:run |
| POST | /platform/projects/{project_id}/cases/{case_id}/run | case:run |
Workspaces (snapshots editáveis)
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/workspaces | project:view |
| POST | /platform/projects/{project_id}/workspaces | workspace:create |
| GET | /platform/projects/{project_id}/workspaces/{workspace_id} | project:view |
| PATCH | /platform/projects/{project_id}/workspaces/{workspace_id} | workspace:create |
Revisões
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/reviews | project:view |
| POST | /platform/projects/{project_id}/reviews | review:create |
| PATCH | /platform/projects/{project_id}/reviews/{review_id} | review:approve |
| GET | /platform/projects/{project_id}/reviews/{review_id}/comments | project:view |
| POST | /platform/projects/{project_id}/reviews/{review_id}/comments | review:comment |
Versões
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/versions | project:view |
| POST | /platform/projects/{project_id}/versions | version:create |
| POST | /platform/projects/{project_id}/versions/{version_id}/publish | version:publish |
| POST | /platform/projects/{project_id}/versions/{version_id}/restore | version:publish |
Membros
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/members | project:view |
| POST | /platform/projects/{project_id}/members | member:manage |
| POST | /platform/projects/{project_id}/members/assign | member:manage |
Auditoria
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/audit | audit:view |
| GET | /platform/projects/{project_id}/audit | audit:view |
Integrações Git
| Método | Caminho | Permissão |
|---|---|---|
| GET | /platform/projects/{project_id}/git-bindings | project:view |
Mais detalhes de git bindings em Endpoints de organização.
Projetos
GET /platform/projects
Lista projetos da organização ativa.
Response 200: array de ProjectRecord.
[
{
"id": "prj_01H…",
"slug": "edge-rules",
"name": "Edge rules",
"description": "Regras do time de edge",
"decoders_xml": "<decoders>…</decoders>",
"rules_xml": "<group name=\"custom\">…</group>",
"default_log_format": "syslog",
"include_disk_defaults": true,
"include_disk_custom": true,
"active_baseline_id": "base_01H…",
"active_baseline_name": "baseline-4.10",
"case_count": 12,
"workspace_count": 3,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-04-24T14:00:00Z"
}
]
POST /platform/projects
Cria um novo projeto.
Request body (ProjectCreateRequest):
{
"name": "Edge rules",
"description": "Regras customizadas do time de edge",
"decoders_xml": "<decoders>\n</decoders>",
"rules_xml": "<group name=\"custom\">\n</group>",
"default_log_format": "syslog",
"include_disk_defaults": true,
"include_disk_custom": true,
"active_baseline_id": null
}
Validações:
name— 1–120 chars.description— 0–2000 chars.decoders_xml,rules_xml— até 2 MB cada.default_log_format—auto,syslog,json,eventchannel,plain.
Response 200: ProjectRecord.
GET /platform/projects/{project_id}
Busca projeto específico.
Response 200: ProjectRecord.
PATCH /platform/projects/{project_id}
Atualização parcial. Envie apenas os campos a alterar.
Request body (ProjectUpdateRequest) — todos os campos opcionais.
Response 200: ProjectRecord.
GET /platform/projects/{project_id}/overview
Painel consolidado: score de qualidade, policy, semantic counts, versões e auditoria recente.
Response 200 (ProjectOverviewResponse):
{
"project": { "...": "ProjectRecord" },
"quality_score": 87,
"quality_gate_policy": { "...": "QualityGatePolicyRecord" },
"quality_gate_result": { "passed": true, "...": "..." },
"semantic_counts": {
"total_rules": 120, "total_decoders": 45,
"root_decoders": 12, "terminal_decoders": 33,
"correlation_rules": 8, "mitre_tagged_rules": 45,
"...": "..."
},
"recent_versions": [ "ProjectVersionRecord[]" ],
"recent_audit": [ "AuditEventRecord[]" ],
"diagnostics_by_severity": {"error": 0, "warning": 3, "info": 12},
"diagnostics_by_code": {"rule_overlap": 2, "decoder_unused": 1}
}
GET /platform/projects/{project_id}/report
Relatório completo para exportação: validação + regressão + scores.
Response 200: ProjectReportResponse.
POST /platform/projects/{project_id}/impact/{workspace_id}
Compara o estado atual do projeto contra o conteúdo de um workspace (candidato a publicar). Retorna diff por caso.
Response 200 (ProjectImpactResponse):
{
"project": { "...": "ProjectRecord" },
"workspace": { "...": "WorkspaceRecord" },
"current_quality_score": 85,
"candidate_quality_score": 92,
"current_diagnostics_by_severity": {"error": 2, "warning": 5},
"candidate_diagnostics_by_severity": {"error": 0, "warning": 3},
"changed_cases": 4,
"improved_cases": 3,
"regressed_cases": 1,
"unchanged_cases": 15,
"cases": [
{
"case_id": "case_...",
"case_name": "SSH brute force",
"before_passed": false,
"after_passed": true,
"change_type": "improved",
"...": "..."
}
]
}
Conteúdo
GET /platform/projects/{project_id}/rules
Lista as regras (com metadata) do projeto.
Response 200: array de RuleCatalogItem. Cada item:
{
"rule_id": "100010",
"level": 5,
"description": "Tentativa de login suspeita",
"groups": ["authentication_failed", "local"],
"decoded_as": "sshd",
"source_file": "local_rules.xml",
"source_line": 15,
"dependency_count": 0,
"dependent_rule_count": 2,
"field_matcher_count": 3,
"uses_frequency": false,
"uses_correlation": false,
"noalert": false,
"mitre_ids": ["T1110"]
}
GET /platform/projects/{project_id}/decoders
Lista os decoders do projeto.
Response 200: array de DecoderCatalogItem.
{
"name": "sshd-custom",
"parent": "sshd",
"source_file": "local_decoders.xml",
"source_line": 8,
"order": ["srcip", "dstuser"],
"child_count": 0,
"referenced_rule_count": 4,
"reachable_from_rule": true,
"has_regex": true,
"chain_depth": 2,
"fts_fields": ["dstuser"]
}
Qualidade
GET /platform/projects/{project_id}/quality-gate
Retorna a policy atual: thresholds de score, diagnósticos máximos por severidade, etc.
Response 200: QualityGatePolicyRecord.
PATCH /platform/projects/{project_id}/quality-gate
Atualiza a policy. Request parcial com thresholds.
Response 200: QualityGatePolicyRecord.
Casos de teste
Caso = evento + expectativa. Rodando, verifica se o comportamento atual do ruleset corresponde ao esperado.
POST /platform/projects/{project_id}/cases
Cria um caso.
Request body (CaseCreateRequest):
{
"name": "SSH brute force",
"description": "Failed password SSH deve casar regra 5716",
"event_text": "Jan 10 12:00:01 web01 sshd[1234]: Failed password for root",
"log_format": "syslog",
"location": "/var/log/auth.log",
"session_id": "ssh-correlation",
"expected_decoder": "sshd",
"expected_rule": "5716",
"expected_rule_ids": ["5716"],
"expected_fields": { "dstuser": "root", "srcip": "10.0.0.5" }
}
Limites:
event_text— até 8 MB.expected_fields— até 100 entradas (chave ≤ 255, valor ≤ 1024).expected_rule_ids— até 200 entradas.
Response 200: CaseRecord.
PATCH /platform/projects/{project_id}/cases/{case_id}
Atualiza parcialmente. Campos opcionais.
DELETE /platform/projects/{project_id}/cases/{case_id}
Remove o caso. Response 204 No Content.
POST /platform/projects/{project_id}/cases/run
Executa todos os casos do projeto.
Response 200 (CaseBatchRunResponse):
{
"total_cases": 20,
"passed_cases": 18,
"failed_cases": 2,
"results": [
{
"case": { "...": "CaseRecord" },
"passed": true,
"checks": [
{ "label": "Matched expected rule", "expected": "5716", "actual": "5716", "passed": true }
],
"analysis": { "...": "LogtestResponse" }
}
]
}
Emite webhooks: regression.completed, regression.passed ou regression.failed.
POST /platform/projects/{project_id}/cases/{case_id}/run
Roda um caso isolado.
Response 200: CaseRunResponse.
Workspaces
Workspace = área de edição isolada com seu próprio ruleset. Publica virando uma versão.
GET /platform/projects/{project_id}/workspaces
Lista workspaces abertos.
Response 200: array de WorkspaceRecord.
POST /platform/projects/{project_id}/workspaces
Cria workspace.
Request body (WorkspaceCreateRequest):
{
"name": "Refactor sshd",
"description": "Refazer regras de brute force",
"decoders_xml": "<decoders>…</decoders>",
"rules_xml": "<group name=\"custom\">…</group>",
"event_text": "exemplo de evento",
"log_format": "syslog",
"session_id": null,
"include_disk_defaults": true,
"include_disk_custom": true
}
Response 200: WorkspaceRecord.
PATCH /platform/projects/{project_id}/workspaces/{workspace_id}
Atualiza conteúdo. Aceita opcionalmente source_files[] quando o workspace origina de Git (preserva provenance por arquivo).
Response 200: WorkspaceRecord.
Revisões
POST /platform/projects/{project_id}/reviews
Abre uma revisão sobre um workspace.
Request body (ReviewCreateRequest): { title, workspace_id, reviewer_ids, notes }.
Response 200: ReviewRecord.
PATCH /platform/projects/{project_id}/reviews/{review_id}
Atualiza status (approved, changes_requested, rejected, closed). Permissão: review:approve.
POST /platform/projects/{project_id}/reviews/{review_id}/comments
Adiciona comentário à revisão.
Request body (ReviewCommentCreateRequest): { body: string }.
Webhook emitido: review.created, review.approved, review.changes_requested, review.rejected.
Versões
Versão = snapshot publicado, imutável. Ciclo típico: criar (draft) → validar (quality gate) → publicar.
POST /platform/projects/{project_id}/versions
Cria uma versão.
Request body (ProjectVersionCreateRequest):
{
"name": "v2026.04",
"notes": "Corrige sshd brute force",
"source_workspace_id": "ws_01H…",
"source_review_id": "rev_01H…"
}
Response 200: ProjectVersionRecord com status="draft".
POST /platform/projects/{project_id}/versions/{version_id}/publish
Publica a versão. O servidor roda o quality gate e só promove se passar.
Response 200 (ProjectVersionPublishResponse):
{
"version": { "...": "ProjectVersionRecord" },
"published": true,
"quality_gate_result": {
"passed": true,
"failed_rules": [],
"...": "..."
}
}
Webhook emitido: version.created, version.published, ou publish.failed.
POST /platform/projects/{project_id}/versions/{version_id}/restore
Restaura o conteúdo desta versão para o projeto ativo.
Response 200: ProjectRecord.
Membros do projeto
POST /platform/projects/{project_id}/members
Cria usuário novo já anexado ao projeto (análogo a /auth/organizations/{id}/members, mas adiciona vínculo com o projeto).
POST /platform/projects/{project_id}/members/assign
Liga um usuário existente da organização ao projeto.
Request body (ProjectMemberAssignRequest):
{ "user_id": "usr_...", "role": "engineer" }
Auditoria
GET /platform/audit
Todos os eventos auditados da organização ativa.
Response 200: array de AuditEventRecord. Cada evento traz actor_*, action, resource_*, diff, created_at.
GET /platform/projects/{project_id}/audit
Mesmo, filtrado por projeto.
Estruturas compartilhadas
CaseRecord
{
"id": "string",
"project_id": "string",
"name": "string",
"description": "string",
"event_text": "string",
"log_format": "auto|syslog|json|eventchannel|plain",
"location": "string|null",
"session_id": "string",
"expected_decoder": "string|null",
"expected_rule": "string|null",
"expected_fields": {"key": "value"},
"expected_rule_ids": ["string"],
"created_at": "ISO 8601",
"updated_at": "ISO 8601"
}
WorkspaceRecord
Inclui o conteúdo editável + provenance Git (quando aplicável):
{
"id": "string", "project_id": "string",
"name": "string", "description": "string",
"decoders_xml": "…", "rules_xml": "…",
"event_text": "string", "log_format": "…",
"session_id": "string",
"include_disk_defaults": true, "include_disk_custom": true,
"source_files": [
{ "path": "rules/local.xml", "kind": "rules", "xml": "…", "sha": "…", "rule_ids": ["100010"], "decoder_names": [] }
],
"git_binding_id": "string|null",
"git_repo": "string|null",
"git_branch": "string|null",
"git_commit_sha": "string|null",
"created_at": "…", "updated_at": "…"
}
ProjectVersionRecord
{
"id": "string", "project_id": "string",
"source_workspace_id": "string|null",
"source_review_id": "string|null",
"name": "string", "notes": "string",
"status": "draft|published|archived",
"quality_score": 87,
"regression_passed": true,
"total_rules": 120, "total_decoders": 45,
"created_at": "…", "updated_at": "…", "published_at": "…"
}