Pular para o conteúdo principal

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étodoCaminhoPermissão
GET/platform/dashboardproject:view
GET/platform/projectsproject:view
POST/platform/projectsproject:create
GET/platform/projects/{project_id}project:view
PATCH/platform/projects/{project_id}project:edit
GET/platform/projects/{project_id}/overviewproject:view
GET/platform/projects/{project_id}/reportproject:view
POST/platform/projects/{project_id}/impact/{workspace_id}project:view

Conteúdo (regras e decoders do projeto)

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/rulesproject:view
GET/platform/projects/{project_id}/decodersproject:view

Qualidade

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/quality-gateproject:view
PATCH/platform/projects/{project_id}/quality-gateproject:edit

Casos de teste

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/casesproject:view
POST/platform/projects/{project_id}/casescase: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/runcase:run
POST/platform/projects/{project_id}/cases/{case_id}/runcase:run

Workspaces (snapshots editáveis)

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/workspacesproject:view
POST/platform/projects/{project_id}/workspacesworkspace:create
GET/platform/projects/{project_id}/workspaces/{workspace_id}project:view
PATCH/platform/projects/{project_id}/workspaces/{workspace_id}workspace:create

Revisões

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/reviewsproject:view
POST/platform/projects/{project_id}/reviewsreview:create
PATCH/platform/projects/{project_id}/reviews/{review_id}review:approve
GET/platform/projects/{project_id}/reviews/{review_id}/commentsproject:view
POST/platform/projects/{project_id}/reviews/{review_id}/commentsreview:comment

Versões

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/versionsproject:view
POST/platform/projects/{project_id}/versionsversion:create
POST/platform/projects/{project_id}/versions/{version_id}/publishversion:publish
POST/platform/projects/{project_id}/versions/{version_id}/restoreversion:publish

Membros

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/membersproject:view
POST/platform/projects/{project_id}/membersmember:manage
POST/platform/projects/{project_id}/members/assignmember:manage

Auditoria

MétodoCaminhoPermissão
GET/platform/auditaudit:view
GET/platform/projects/{project_id}/auditaudit:view

Integrações Git

MétodoCaminhoPermissão
GET/platform/projects/{project_id}/git-bindingsproject: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_formatauto, 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": "…"
}