@orkastery/cli 0.5.3 → 0.6.0
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.
- package/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +195 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/autoridade.json +56 -0
- package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
- package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
- package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
- package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
- package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
- package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
- package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
- package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
- package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
- package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
- package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +121 -0
- package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
- package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
- package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
- package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
- package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
- package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
- package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
- package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
- package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
- package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
- package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
- package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
- package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
- package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
- package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
- package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
- package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
- package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
- package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
- package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +3 -3
- package/adapters/openclaw/README.md +83 -10
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
- package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
- package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
- package/assets/docs-en/produto/README.md +14 -0
- package/assets/docs-en/produto/_modelo-feature.md +62 -0
- package/assets/docs-en/roadmap/README.md +14 -0
- package/assets/docs-en/roadmap/_modelo-item.md +75 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +193 -15
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +13 -2
- package/dist/agents-md.js +24 -15
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +68 -48
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +98 -43
- package/dist/branch-de-estado.js +39 -9
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +35 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +500 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +183 -0
- package/dist/ci.js +255 -46
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +350 -0
- package/dist/claims.js +13 -10
- package/dist/company-brain-client.js +45 -3
- package/dist/company-brain-journal.js +2 -1
- package/dist/company-brain-migration.js +47 -6
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +405 -0
- package/dist/conducao-texto.js +12 -18
- package/dist/conducao.js +206 -59
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +514 -0
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +103 -82
- package/dist/doctor-forja.js +345 -0
- package/dist/doctor-pulse-cron.js +294 -27
- package/dist/doctor-rede.js +18 -17
- package/dist/doctor.js +278 -116
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +158 -57
- package/dist/escopo-escrita.js +10 -1
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +42 -17
- package/dist/evalrunner.js +35 -32
- package/dist/experiencia-instalacao.js +45 -25
- package/dist/fabrica-batida.js +323 -0
- package/dist/fabrica-estado.js +49 -16
- package/dist/fabrica-publicar.js +3 -1
- package/dist/fila-pesada.js +444 -0
- package/dist/fix.js +24 -21
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +124 -81
- package/dist/gates.js +3 -28
- package/dist/handoff.js +33 -19
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +53 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +72 -3
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-tempo-parado.js +4 -4
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +63 -64
- package/dist/horario.js +30 -7
- package/dist/hosts.js +155 -134
- package/dist/impedimento.js +108 -14
- package/dist/index.js +1421 -1019
- package/dist/indice-vetorial.js +14 -12
- package/dist/indice.js +7 -1
- package/dist/init.js +54 -49
- package/dist/instabilidade.js +144 -0
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +213 -88
- package/dist/intelligence-graph-contexto.js +56 -17
- package/dist/intelligence-graph-contract.js +2 -1
- package/dist/intelligence-graph-extract-md.js +56 -4
- package/dist/intelligence-graph-extract-ts.js +71 -3
- package/dist/intelligence-graph-query.js +96 -34
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +46 -2
- package/dist/licoes.js +12 -11
- package/dist/liveness.js +6 -3
- package/dist/locale-accounts.js +220 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +833 -0
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +290 -0
- package/dist/locale-gerados.js +165 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +182 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-onboarding.js +92 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-phase.js +151 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +349 -0
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +524 -0
- package/dist/locale-roadmap.js +102 -0
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +597 -0
- package/dist/locale-thread.js +421 -0
- package/dist/locale-verify.js +201 -0
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +1258 -0
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +415 -13
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +31 -7
- package/dist/master-digest.js +6 -1
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +14 -8
- package/dist/master.js +139 -65
- package/dist/mcp-artifacts.js +11 -2
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-git.js +23 -6
- package/dist/mcp-grafo.js +7 -4
- package/dist/mcp-install.js +73 -8
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +90 -16
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +71 -25
- package/dist/mcp-transportes.js +17 -0
- package/dist/mcp-verify.js +6 -1
- package/dist/memoria.js +63 -58
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +20 -24
- package/dist/network-roadmap.js +90 -51
- package/dist/noctum-aceite.js +789 -0
- package/dist/noctum-arco.js +1418 -0
- package/dist/noctum-capacidade.js +141 -0
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +482 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1169 -0
- package/dist/noctum-envelope.js +1046 -0
- package/dist/noctum-execucao.js +376 -0
- package/dist/noctum-fechamento.js +405 -0
- package/dist/noctum-fila.js +314 -0
- package/dist/noctum-guarda.js +256 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +383 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +362 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +591 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +827 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +639 -0
- package/dist/ocupacao.js +32 -3
- package/dist/onboarding.js +56 -26
- package/dist/orkmind.js +48 -25
- package/dist/orquestracao.js +44 -47
- package/dist/parado-no-condutor.js +174 -127
- package/dist/phase.js +144 -63
- package/dist/policies.js +37 -4
- package/dist/portfolio.js +4 -2
- package/dist/postura-local.js +235 -0
- package/dist/preflight.js +11 -10
- package/dist/procedencia.js +220 -0
- package/dist/projeto-alvo.js +186 -24
- package/dist/prompts.js +140 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +151 -24
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +188 -22
- package/dist/ratelimit.js +16 -6
- package/dist/recall.js +14 -13
- package/dist/redacao-saida.js +63 -0
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +66 -47
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +451 -212
- package/dist/roadmap-reservas.js +45 -28
- package/dist/roadmap-status.js +129 -33
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +284 -32
- package/dist/runtime-escada.js +423 -0
- package/dist/runtime-profiles.js +103 -46
- package/dist/runtimes.js +2 -1
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +355 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +188 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +26 -5
- package/dist/session-watcher-claude.js +81 -20
- package/dist/session-watcher.js +340 -42
- package/dist/sessoes-contas.js +10 -1
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +59 -58
- package/dist/ship-publicar.js +971 -0
- package/dist/ship.js +243 -97
- package/dist/steal.js +77 -0
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +12 -11
- package/dist/thread.js +274 -100
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +13 -3
- package/dist/varredura-acoes.js +507 -0
- package/dist/verify.js +608 -76
- package/dist/vida-da-thread.js +254 -0
- package/dist/worktree-local.js +167 -0
- package/dist/worktree.js +99 -83
- package/dist/yaml.js +27 -8
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +9 -4
- package/references/security-checklist.md +3 -3
- package/schemas/code-artifact-graph.v1.schema.json +2 -1
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stack detection for `ork security-scan` and `ork init` (spec section 7). Looks at the repository root and its
|
|
4
|
+
* first-level subfolders only, skipping vendored or generated folders.
|
|
5
|
+
*
|
|
6
|
+
* Markers: JS/TS by `package.json`; Python by `pyproject.toml`, `requirements*.txt`, `uv.lock`, `poetry.lock` or
|
|
7
|
+
* `Pipfile.lock`; Go by `go.mod`. One entry per (stack, dir).
|
|
8
|
+
*
|
|
9
|
+
* Order of the result is deterministic: the root first, then subfolders in byte order of the name; within a
|
|
10
|
+
* directory, the order js, python, go.
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.detectStacks = detectStacks;
|
|
47
|
+
exports.hasStackManifest = hasStackManifest;
|
|
48
|
+
const fs = __importStar(require("node:fs"));
|
|
49
|
+
const path = __importStar(require("node:path"));
|
|
50
|
+
const IGNORED_DIRS = new Set(['node_modules', '.git', '.orkastery', 'vendor', 'dist']);
|
|
51
|
+
const PYTHON_FILES = new Set(['pyproject.toml', 'uv.lock', 'poetry.lock', 'Pipfile.lock']);
|
|
52
|
+
const STACK_ORDER = ['js', 'python', 'go'];
|
|
53
|
+
function stacksIn(absDir) {
|
|
54
|
+
let entries;
|
|
55
|
+
try {
|
|
56
|
+
entries = fs.readdirSync(absDir, { withFileTypes: true });
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const found = new Set();
|
|
62
|
+
for (const e of entries) {
|
|
63
|
+
if (e.isDirectory())
|
|
64
|
+
continue;
|
|
65
|
+
if (e.name === 'package.json')
|
|
66
|
+
found.add('js');
|
|
67
|
+
else if (e.name === 'go.mod')
|
|
68
|
+
found.add('go');
|
|
69
|
+
else if (PYTHON_FILES.has(e.name) || /^requirements.*\.txt$/.test(e.name))
|
|
70
|
+
found.add('python');
|
|
71
|
+
}
|
|
72
|
+
return STACK_ORDER.filter((s) => found.has(s));
|
|
73
|
+
}
|
|
74
|
+
function detectStacks(root) {
|
|
75
|
+
const result = [];
|
|
76
|
+
for (const stack of stacksIn(root))
|
|
77
|
+
result.push({ stack, dir: '.' });
|
|
78
|
+
let subdirs = [];
|
|
79
|
+
try {
|
|
80
|
+
subdirs = fs.readdirSync(root, { withFileTypes: true })
|
|
81
|
+
.filter((e) => e.isDirectory() && !IGNORED_DIRS.has(e.name))
|
|
82
|
+
.map((e) => e.name)
|
|
83
|
+
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
for (const name of subdirs) {
|
|
89
|
+
for (const stack of stacksIn(path.join(root, name)))
|
|
90
|
+
result.push({ stack, dir: name });
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
/** Whether `dir` (relative to `root`) holds a manifest of `stack`, by the same marker file names `detectStacks` uses. */
|
|
95
|
+
function hasStackManifest(root, stack, dir) {
|
|
96
|
+
return stacksIn(path.join(root, dir)).includes(stack);
|
|
97
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CONFIG_FILES = void 0;
|
|
37
|
+
exports.defaultProbe = defaultProbe;
|
|
38
|
+
exports.chooseExecutor = chooseExecutor;
|
|
39
|
+
exports.nativeVersionOf = nativeVersionOf;
|
|
40
|
+
exports.defaultsDir = defaultsDir;
|
|
41
|
+
exports.expand = expand;
|
|
42
|
+
exports.ensureImage = ensureImage;
|
|
43
|
+
exports.runDocker = runDocker;
|
|
44
|
+
exports.runNative = runNative;
|
|
45
|
+
/**
|
|
46
|
+
* How one catalog tool runs on this machine (spec section 5.2): its Docker image by digest when Docker answers, else
|
|
47
|
+
* the native binary when its version matches `native.versionPattern`, else `unavailable` with the reason. The run of
|
|
48
|
+
* one argv, in a hardened container or natively, is here too; the scan round that calls it is run.ts.
|
|
49
|
+
*/
|
|
50
|
+
const node_child_process_1 = require("node:child_process");
|
|
51
|
+
const crypto = __importStar(require("node:crypto"));
|
|
52
|
+
const fs = __importStar(require("node:fs"));
|
|
53
|
+
const path = __importStar(require("node:path"));
|
|
54
|
+
const guard_1 = require("./guard");
|
|
55
|
+
const PROBE_TIMEOUT_MS = 20000;
|
|
56
|
+
/** The probe of this machine, through the PATH. Each answer is computed once per probe. */
|
|
57
|
+
function defaultProbe() {
|
|
58
|
+
const memo = new Map();
|
|
59
|
+
const once = (key, f) => { if (!memo.has(key))
|
|
60
|
+
memo.set(key, f()); return memo.get(key); };
|
|
61
|
+
const ok = (cmd, args) => {
|
|
62
|
+
const r = (0, node_child_process_1.spawnSync)(cmd, args, { stdio: 'ignore', timeout: PROBE_TIMEOUT_MS });
|
|
63
|
+
return !r.error && r.status === 0;
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
dockerCli: () => once('cli', () => ok('docker', ['--version'])),
|
|
67
|
+
dockerDaemon: () => once('daemon', () => ok('docker', ['info', '--format', '{{.ServerVersion}}'])),
|
|
68
|
+
nativeVersion: (bin, args) => once(`native:${bin} ${args.join(' ')}`, () => {
|
|
69
|
+
const r = (0, node_child_process_1.spawnSync)(bin, args, { encoding: 'utf8', timeout: PROBE_TIMEOUT_MS });
|
|
70
|
+
return r.error || r.status !== 0 ? null : `${r.stdout ?? ''}${r.stderr ?? ''}`;
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Docker → native → unavailable. Without a usable Docker, the native binary runs when its version matches
|
|
76
|
+
* `native.versionPattern`; a binary answering another version is `binary-version-mismatch`; otherwise (no native entry,
|
|
77
|
+
* or the binary absent) the reason is Docker's own, `docker-missing` or `docker-daemon-down`: Docker is the path the
|
|
78
|
+
* catalog pins. A tool whose wrapper installs pinned packages (`install`) never runs natively: nothing installs on the
|
|
79
|
+
* host. `binary-missing` stays in the type for the doctor (Task 9) and is not produced here.
|
|
80
|
+
*/
|
|
81
|
+
function chooseExecutor(tool, probe) {
|
|
82
|
+
const cli = probe.dockerCli();
|
|
83
|
+
if (cli && probe.dockerDaemon())
|
|
84
|
+
return { kind: 'docker' };
|
|
85
|
+
const dockerReason = cli ? 'docker-daemon-down' : 'docker-missing';
|
|
86
|
+
if (!tool.native || tool.install)
|
|
87
|
+
return { kind: 'unavailable', reason: dockerReason };
|
|
88
|
+
const out = probe.nativeVersion(tool.native.bin, tool.native.versionArgs);
|
|
89
|
+
if (out === null)
|
|
90
|
+
return { kind: 'unavailable', reason: dockerReason };
|
|
91
|
+
return new RegExp(tool.native.versionPattern, 'm').test(out) ? { kind: 'native' } : { kind: 'unavailable', reason: 'binary-version-mismatch' };
|
|
92
|
+
}
|
|
93
|
+
/** The version string the native binary reports (the `versionPattern` match). */
|
|
94
|
+
function nativeVersionOf(tool, probe) {
|
|
95
|
+
const out = tool.native ? probe.nativeVersion(tool.native.bin, tool.native.versionArgs) : null;
|
|
96
|
+
return (out && tool.native && new RegExp(tool.native.versionPattern, 'm').exec(out)?.[0]) || tool.version;
|
|
97
|
+
}
|
|
98
|
+
/** Embedded tool configs (`{config}`), next to the catalog; dist/security-scan or dist-test/src/security-scan. */
|
|
99
|
+
function defaultsDir() {
|
|
100
|
+
const dir = [path.join(__dirname, '..', '..', 'assets', 'security-scan', 'defaults'),
|
|
101
|
+
path.join(__dirname, '..', '..', '..', 'assets', 'security-scan', 'defaults')].find(fs.existsSync);
|
|
102
|
+
if (!dir)
|
|
103
|
+
throw Error('security-scan.catalog.unavailable');
|
|
104
|
+
return dir;
|
|
105
|
+
}
|
|
106
|
+
/** Config file name per tool; the project's `.ork-security/<name>` wins over the embedded default. */
|
|
107
|
+
exports.CONFIG_FILES = { gitleaks: 'gitleaks.toml', eslint: 'eslint.config.mjs', ruff: 'ruff.toml', 'golangci-lint': '.golangci.yml' };
|
|
108
|
+
const CONTAINER = { src: '/src', out: '/out', config: '/config' };
|
|
109
|
+
const MAX_BUFFER = 512 * 1024 * 1024;
|
|
110
|
+
function expand(arg, values) {
|
|
111
|
+
return arg.replace(/\{(src|out|base|config|install|stackDir)\}/g, (_, k) => values[k]);
|
|
112
|
+
}
|
|
113
|
+
/** {stackDir} as an argument: a directory named `-x` would read as an option, so it goes as `./-x`. */
|
|
114
|
+
const stackDirArg = (dir) => (dir.startsWith('-') ? `./${dir}` : dir);
|
|
115
|
+
/** uid:gid of the container user: the caller's (so the output dir it writes is the caller's), never root. */
|
|
116
|
+
function containerUser() {
|
|
117
|
+
const uid = process.getuid?.() ?? 65534;
|
|
118
|
+
return uid === 0 ? '65534:65534' : `${uid}:${process.getgid?.() ?? 65534}`;
|
|
119
|
+
}
|
|
120
|
+
/** Image present locally, else pulled within `timeoutMs`; memoized per image by the caller. */
|
|
121
|
+
function ensureImage(image, timeoutMs) {
|
|
122
|
+
if (timeoutMs <= 0)
|
|
123
|
+
return false;
|
|
124
|
+
const present = (0, node_child_process_1.spawnSync)('docker', ['image', 'inspect', image], { stdio: 'ignore', timeout: Math.min(PROBE_TIMEOUT_MS, timeoutMs) });
|
|
125
|
+
if (!present.error && present.status === 0)
|
|
126
|
+
return true;
|
|
127
|
+
const pull = (0, node_child_process_1.spawnSync)('docker', ['pull', '--quiet', image], { stdio: 'ignore', timeout: timeoutMs, killSignal: 'SIGKILL' });
|
|
128
|
+
return !pull.error && pull.status === 0;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Runs one argv in the tool's image: digest, `--rm`, non-root `--user`, repository at /src read-only, the output dir at
|
|
132
|
+
* /out, embedded or project config read-only, a tmpfs /tmp, `--network none` when catalogued, only the catalog `env`
|
|
133
|
+
* (nothing of the host environment), and a `--name` so a timed-out container is removed (`docker rm -f`), since killing
|
|
134
|
+
* the CLI leaves the container running.
|
|
135
|
+
*/
|
|
136
|
+
function runDocker(inv) {
|
|
137
|
+
const { tool } = inv;
|
|
138
|
+
const name = `ork-security-scan-${tool.name}-${crypto.randomBytes(6).toString('hex')}`;
|
|
139
|
+
const configCtr = inv.configHost ? `${CONTAINER.config}/${path.basename(inv.configHost)}` : '';
|
|
140
|
+
if (process.getuid?.() === 0)
|
|
141
|
+
fs.chmodSync(inv.outHost, 0o777);
|
|
142
|
+
const values = { src: CONTAINER.src, out: CONTAINER.out, base: inv.base, config: configCtr, install: (tool.install ?? []).join(' '), stackDir: stackDirArg(inv.stackDir) };
|
|
143
|
+
const args = ['run', '--rm', '--name', name, '--pull', 'never', '--user', containerUser(),
|
|
144
|
+
'--cap-drop', 'ALL', '--security-opt', 'no-new-privileges',
|
|
145
|
+
...(tool.network === 'none' ? ['--network', 'none'] : []),
|
|
146
|
+
'--tmpfs', '/tmp:exec,mode=1777',
|
|
147
|
+
'-v', `${inv.srcHost}:${CONTAINER.src}:ro`, '-v', `${inv.outHost}:${CONTAINER.out}`,
|
|
148
|
+
...(inv.configHost ? ['-v', `${inv.configHost}:${configCtr}:ro`] : []),
|
|
149
|
+
...(inv.sameMounts ?? []).flatMap(m => ['-v', `${m}:${m}:ro`]),
|
|
150
|
+
...(tool.cacheMounts ?? []).flatMap(m => ['-v', `${m.host}:${m.container}`]),
|
|
151
|
+
'-w', CONTAINER.src,
|
|
152
|
+
...Object.entries(tool.env ?? {}).flatMap(([k, v]) => ['-e', `${k}=${v}`]),
|
|
153
|
+
'--entrypoint', tool.containerBin ?? inv.argv[0], tool.image,
|
|
154
|
+
...inv.argv.slice(1).map(a => expand(a, values))];
|
|
155
|
+
inv.guard?.add('containers', name);
|
|
156
|
+
const r = (0, node_child_process_1.spawnSync)('docker', args, { encoding: 'utf8', timeout: inv.timeoutMs, killSignal: 'SIGKILL', maxBuffer: MAX_BUFFER, env: process.env });
|
|
157
|
+
const timedOut = r.error?.code === 'ETIMEDOUT';
|
|
158
|
+
if (timedOut || r.error)
|
|
159
|
+
(0, node_child_process_1.spawnSync)('docker', ['rm', '-f', name], { stdio: 'ignore', timeout: PROBE_TIMEOUT_MS });
|
|
160
|
+
inv.guard?.remove('containers', name);
|
|
161
|
+
return { status: r.status, timedOut, stdout: r.stdout ?? '', stderr: r.stderr ?? '' };
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Runs one argv with the native binary, in the scanned tree, with the host paths in the placeholders. The host
|
|
165
|
+
* environment is kept (it is the user's own binary), with the catalog `env` on top except HOME. The tool runs through
|
|
166
|
+
* the launcher of guard.ts as the leader of its own process group, so the timeout kills the whole group (an `sh`
|
|
167
|
+
* wrapper's grandchildren included), not only the direct child.
|
|
168
|
+
*/
|
|
169
|
+
function runNative(inv) {
|
|
170
|
+
const { tool } = inv;
|
|
171
|
+
const values = { src: inv.srcHost, out: inv.outHost, base: inv.base, config: inv.configHost ?? '', install: '', stackDir: stackDirArg(inv.stackDir) };
|
|
172
|
+
const env = { ...process.env };
|
|
173
|
+
for (const [k, v] of Object.entries(tool.env ?? {}))
|
|
174
|
+
if (k !== 'HOME')
|
|
175
|
+
env[k] = v;
|
|
176
|
+
const [bin, ...rest] = inv.argv.map(a => expand(a, values));
|
|
177
|
+
const pgidFile = inv.guard?.pgidFile() ?? path.join(inv.outHost, '.native.pgid');
|
|
178
|
+
const marker = `${pgidFile}${guard_1.LAUNCH_TIMEOUT_SUFFIX}`;
|
|
179
|
+
try {
|
|
180
|
+
const r = (0, node_child_process_1.spawnSync)(process.execPath, (0, guard_1.launcherArgs)(pgidFile, inv.timeoutMs, bin, rest), { cwd: inv.srcHost, encoding: 'utf8', timeout: inv.timeoutMs + 10000, killSignal: 'SIGKILL', maxBuffer: MAX_BUFFER, env });
|
|
181
|
+
const timedOut = fs.existsSync(marker) || r.error?.code === 'ETIMEDOUT';
|
|
182
|
+
return { status: r.status, timedOut, stdout: r.stdout ?? '', stderr: r.stderr ?? '' };
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
fs.rmSync(marker, { force: true });
|
|
186
|
+
fs.rmSync(pgidFile, { force: true });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LAUNCH_TIMEOUT_SUFFIX = exports.RoundGuard = void 0;
|
|
37
|
+
exports.launcherArgs = launcherArgs;
|
|
38
|
+
/**
|
|
39
|
+
* Cleanup of a scan round that dies on a signal, and the process-group launcher of native tools.
|
|
40
|
+
*
|
|
41
|
+
* Why not SIGTERM/SIGINT handlers in the round: `runScan` is synchronous (spawnSync), and a JS signal handler only runs
|
|
42
|
+
* on the event loop. Measured on Node 22: with a SIGTERM handler installed, a SIGTERM sent while spawnSync waits is
|
|
43
|
+
* swallowed (the handler never runs, the process does not exit and the child keeps its full timeout). Without a
|
|
44
|
+
* handler the process dies at once with 128+signal (the conventional code `ork verify`'s timeout(1) expects), but
|
|
45
|
+
* skips every `finally`. So the round keeps the default signal behaviour and the cleanup lives in a REAPER: a detached
|
|
46
|
+
* process (its own session, out of the group timeout(1) signals) started with the round, that watches the round's pid.
|
|
47
|
+
* The round records in a state file what must not outlive it (worktrees, raw output dirs, the current container, the
|
|
48
|
+
* group of the current native tool); when the round ends normally it cleans up itself and removes the state, and the
|
|
49
|
+
* reaper exits; when the round's pid disappears first, the reaper does the cleanup.
|
|
50
|
+
*
|
|
51
|
+
* Native tools run through the LAUNCHER mode of this file: the tool starts as the leader of its own process group, and
|
|
52
|
+
* the launcher kills the whole group on the timeout, on a signal to itself, and when the tool exits (no `sh` wrapper
|
|
53
|
+
* grandchild survives). It writes the group id next to the reaper state so the reaper can kill it too.
|
|
54
|
+
*/
|
|
55
|
+
const node_child_process_1 = require("node:child_process");
|
|
56
|
+
const fs = __importStar(require("node:fs"));
|
|
57
|
+
const os = __importStar(require("node:os"));
|
|
58
|
+
const path = __importStar(require("node:path"));
|
|
59
|
+
const STATE = 'state.json';
|
|
60
|
+
const POLL_MS = 200;
|
|
61
|
+
/** Parent side: the state file the reaper reads, kept current by the round. */
|
|
62
|
+
class RoundGuard {
|
|
63
|
+
dir;
|
|
64
|
+
state;
|
|
65
|
+
constructor(mainRoot) {
|
|
66
|
+
this.dir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'ork-security-scan-guard-')));
|
|
67
|
+
this.state = { mainRoot, worktrees: [], outDirs: [], containers: [] };
|
|
68
|
+
this.save();
|
|
69
|
+
const reaper = (0, node_child_process_1.spawn)(process.execPath, [__filename, 'reap', this.dir, String(process.pid)], { detached: true, stdio: 'ignore', env: process.env });
|
|
70
|
+
reaper.unref();
|
|
71
|
+
}
|
|
72
|
+
save() {
|
|
73
|
+
const tmp = path.join(this.dir, `${STATE}.tmp`);
|
|
74
|
+
fs.writeFileSync(tmp, JSON.stringify(this.state), { mode: 0o600 });
|
|
75
|
+
fs.renameSync(tmp, path.join(this.dir, STATE));
|
|
76
|
+
}
|
|
77
|
+
add(kind, value) { this.state[kind].push(value); this.save(); }
|
|
78
|
+
remove(kind, value) {
|
|
79
|
+
this.state[kind] = this.state[kind].filter(v => v !== value);
|
|
80
|
+
this.save();
|
|
81
|
+
}
|
|
82
|
+
/** File where the launcher of a native tool writes its process group id. */
|
|
83
|
+
pgidFile() { return path.join(this.dir, `native-${process.hrtime.bigint()}.pgid`); }
|
|
84
|
+
/** The round ended (normally or by an exception): everything is cleaned here, and the reaper exits on its own. */
|
|
85
|
+
close() {
|
|
86
|
+
cleanup(this.dir, this.state);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.RoundGuard = RoundGuard;
|
|
90
|
+
function git(cwd, args) {
|
|
91
|
+
const r = (0, node_child_process_1.spawnSync)('git', args, { cwd, stdio: 'ignore', timeout: 60000 });
|
|
92
|
+
return !r.error && r.status === 0;
|
|
93
|
+
}
|
|
94
|
+
function cleanup(dir, state) {
|
|
95
|
+
for (const name of state.containers)
|
|
96
|
+
(0, node_child_process_1.spawnSync)('docker', ['rm', '-f', name], { stdio: 'ignore', timeout: 30000 });
|
|
97
|
+
for (const f of fs.existsSync(dir) ? fs.readdirSync(dir).filter(n => n.endsWith('.pgid')) : []) {
|
|
98
|
+
const pgid = Number(fs.readFileSync(path.join(dir, f), 'utf8'));
|
|
99
|
+
if (pgid > 1)
|
|
100
|
+
try {
|
|
101
|
+
process.kill(-pgid, 'SIGKILL');
|
|
102
|
+
}
|
|
103
|
+
catch { /* already gone */ }
|
|
104
|
+
}
|
|
105
|
+
let removeFailed = false;
|
|
106
|
+
for (const wt of state.worktrees) {
|
|
107
|
+
if (!git(state.mainRoot, ['worktree', 'remove', '--force', wt]))
|
|
108
|
+
removeFailed = true;
|
|
109
|
+
fs.rmSync(path.dirname(wt), { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
// Prune only what a failed remove left registered: a blanket prune would also drop other sessions' stale entries.
|
|
112
|
+
if (removeFailed)
|
|
113
|
+
git(state.mainRoot, ['worktree', 'prune']);
|
|
114
|
+
for (const out of state.outDirs)
|
|
115
|
+
fs.rmSync(out, { recursive: true, force: true });
|
|
116
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
function alive(pid) {
|
|
119
|
+
try {
|
|
120
|
+
process.kill(pid, 0);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
return e.code === 'EPERM';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function reap(dir, pid) {
|
|
128
|
+
const timer = setInterval(() => {
|
|
129
|
+
const file = path.join(dir, STATE);
|
|
130
|
+
if (!fs.existsSync(file)) {
|
|
131
|
+
clearInterval(timer);
|
|
132
|
+
return;
|
|
133
|
+
} // the round cleaned up itself
|
|
134
|
+
if (alive(pid))
|
|
135
|
+
return;
|
|
136
|
+
clearInterval(timer);
|
|
137
|
+
let state;
|
|
138
|
+
try {
|
|
139
|
+
state = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
cleanup(dir, state);
|
|
145
|
+
}, POLL_MS);
|
|
146
|
+
}
|
|
147
|
+
/** Exit code of the launcher when it killed the tool on its timeout (the parent reads it with the marker file). */
|
|
148
|
+
exports.LAUNCH_TIMEOUT_SUFFIX = '.timeout';
|
|
149
|
+
function launch(pgidFile, timeoutMs, bin, args) {
|
|
150
|
+
const child = (0, node_child_process_1.spawn)(bin, args, { detached: true, stdio: 'inherit' });
|
|
151
|
+
const kill = () => { if (child.pid)
|
|
152
|
+
try {
|
|
153
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
154
|
+
}
|
|
155
|
+
catch { /* gone */ } };
|
|
156
|
+
child.on('error', e => { process.stderr.write(`${e.message}\n`); process.exit(127); });
|
|
157
|
+
if (child.pid)
|
|
158
|
+
fs.writeFileSync(pgidFile, String(child.pid));
|
|
159
|
+
const timer = setTimeout(() => { fs.writeFileSync(`${pgidFile}${exports.LAUNCH_TIMEOUT_SUFFIX}`, ''); kill(); }, timeoutMs);
|
|
160
|
+
for (const s of ['SIGTERM', 'SIGINT', 'SIGHUP']) {
|
|
161
|
+
process.on(s, () => { kill(); process.exit(128 + (os.constants.signals[s] ?? 15)); });
|
|
162
|
+
}
|
|
163
|
+
child.on('exit', (code, signal) => {
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
kill(); // background processes the tool left in its group
|
|
166
|
+
fs.rmSync(pgidFile, { force: true });
|
|
167
|
+
process.exit(code ?? 128 + (signal ? os.constants.signals[signal] ?? 9 : 9));
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/** argv for the launcher of one native tool run. */
|
|
171
|
+
function launcherArgs(pgidFile, timeoutMs, bin, args) {
|
|
172
|
+
return [__filename, 'launch', pgidFile, String(timeoutMs), bin, ...args];
|
|
173
|
+
}
|
|
174
|
+
if (require.main === module) {
|
|
175
|
+
const [mode, a, b, ...rest] = process.argv.slice(2);
|
|
176
|
+
if (mode === 'reap')
|
|
177
|
+
reap(a, Number(b));
|
|
178
|
+
else if (mode === 'launch')
|
|
179
|
+
launch(a, Number(b), rest[0], rest.slice(1));
|
|
180
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PREFIXO_DA_IMAGEM_DE_LINT = void 0;
|
|
37
|
+
exports.tagDaImagemDeLint = tagDaImagemDeLint;
|
|
38
|
+
exports.dockerfileDeLint = dockerfileDeLint;
|
|
39
|
+
exports.garantirImagemDeLint = garantirImagemDeLint;
|
|
40
|
+
exports.eslintComImagem = eslintComImagem;
|
|
41
|
+
/**
|
|
42
|
+
* RM-072 (D11 da ork-check5x): a imagem de lint pre-montada do Agile Check.
|
|
43
|
+
*
|
|
44
|
+
* O `eslint` do catalogo roda na imagem do node e faz `npm install` do `eslint`, do `typescript-eslint` e do `typescript`
|
|
45
|
+
* a cada execucao, na HEAD e na base. O Agile monta uma vez a imagem local `orkastery-eslint-agil:<hash>` a partir do
|
|
46
|
+
* mesmo digest do node e do mesmo `install` do catalogo (com `--ignore-scripts`), e roda o mesmo script com o
|
|
47
|
+
* `node_modules` da imagem no lugar do `npm install`: as mesmas versoes, a mesma config e as mesmas opcoes, sem rede. O
|
|
48
|
+
* hash junta imagem, `install` e versao, entao catalogo novo gera imagem nova. Sem a imagem, o `eslint` do catalogo.
|
|
49
|
+
*/
|
|
50
|
+
const node_child_process_1 = require("node:child_process");
|
|
51
|
+
const crypto = __importStar(require("node:crypto"));
|
|
52
|
+
exports.PREFIXO_DA_IMAGEM_DE_LINT = 'orkastery-eslint-agil';
|
|
53
|
+
/** O trecho do script do catalogo que a imagem substitui. */
|
|
54
|
+
const INSTALACAO_DO_CATALOGO = 'npm install --prefix /tmp/lint --ignore-scripts --no-audit --no-fund --no-save {install} >&2';
|
|
55
|
+
const NODE_MODULES_DA_IMAGEM = 'ln -s /opt/lint/node_modules /tmp/lint/node_modules';
|
|
56
|
+
const PRAZO_DA_CONSULTA_MS = 20_000;
|
|
57
|
+
/** A tag da imagem local: o hash da imagem do catalogo, do `install` e da versao. */
|
|
58
|
+
function tagDaImagemDeLint(t) {
|
|
59
|
+
const hash = crypto.createHash('sha256').update(JSON.stringify({ image: t.image, install: t.install ?? [], version: t.version }))
|
|
60
|
+
.digest('hex').slice(0, 16);
|
|
61
|
+
return `${exports.PREFIXO_DA_IMAGEM_DE_LINT}:${hash}`;
|
|
62
|
+
}
|
|
63
|
+
/** O Dockerfile da imagem: o node do catalogo, pelo digest, com o `install` do catalogo em /opt/lint. */
|
|
64
|
+
function dockerfileDeLint(t) {
|
|
65
|
+
return [`FROM ${t.image}`,
|
|
66
|
+
`RUN mkdir -p /opt/lint && npm install --prefix /opt/lint --ignore-scripts --no-audit --no-fund --no-save ${(t.install ?? []).join(' ')}`,
|
|
67
|
+
''].join('\n');
|
|
68
|
+
}
|
|
69
|
+
/** A imagem local presente, ou montada agora; o motivo quando nao deu (sem rede, build que falhou, prazo). */
|
|
70
|
+
function garantirImagemDeLint(t, prazoMs) {
|
|
71
|
+
const tag = tagDaImagemDeLint(t);
|
|
72
|
+
const presente = (0, node_child_process_1.spawnSync)('docker', ['image', 'inspect', tag], { stdio: 'ignore', timeout: PRAZO_DA_CONSULTA_MS });
|
|
73
|
+
if (!presente.error && presente.status === 0)
|
|
74
|
+
return { tag };
|
|
75
|
+
if (prazoMs <= 0)
|
|
76
|
+
return { motivo: 'sem prazo para montar a imagem' };
|
|
77
|
+
const build = (0, node_child_process_1.spawnSync)('docker', ['build', '--quiet', '-t', tag, '-'], { input: dockerfileDeLint(t), encoding: 'utf8', timeout: prazoMs,
|
|
78
|
+
killSignal: 'SIGKILL', maxBuffer: 16 * 1024 * 1024 });
|
|
79
|
+
if (build.error || build.status !== 0) {
|
|
80
|
+
const ultima = (build.stderr ?? '').split('\n').filter((l) => l.trim()).pop()?.trim().slice(0, 160) ?? '';
|
|
81
|
+
return { motivo: `docker build ${build.error ? build.error.code ?? build.error.message : `saiu ${build.status}`}` +
|
|
82
|
+
`${ultima ? `: ${ultima}` : ''}` };
|
|
83
|
+
}
|
|
84
|
+
return { tag };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* O `eslint` com a imagem local: o mesmo script, com o `node_modules` da imagem no lugar do `npm install`, e sem rede.
|
|
88
|
+
* `null` quando o script do catalogo nao tem o trecho esperado (catalogo mudou): o Agile usa o do catalogo.
|
|
89
|
+
*/
|
|
90
|
+
function eslintComImagem(t, tag) {
|
|
91
|
+
const script = t.args[2];
|
|
92
|
+
if (t.args[0] !== 'sh' || typeof script !== 'string' || !script.includes(INSTALACAO_DO_CATALOGO))
|
|
93
|
+
return null;
|
|
94
|
+
return { ...t, image: tag, network: 'none', args: [t.args[0], t.args[1], script.replace(INSTALACAO_DO_CATALOGO, NODE_MODULES_DA_IMAGEM),
|
|
95
|
+
...t.args.slice(3)] };
|
|
96
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.actionlint = actionlint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** actionlint JSON: paths are relative to the repository root (it runs from there). The snippet is its first source line (the rest is the caret ruler, which moves with the column). */
|
|
6
|
+
function actionlint(output, ctx) {
|
|
7
|
+
const list = (0, util_1.parseReport)('actionlint', output);
|
|
8
|
+
return list.map(e => ({
|
|
9
|
+
tool: 'actionlint', rule: `actionlint/${e.kind ?? 'error'}`, category: 'workflow', severity: (0, util_1.mapSeverity)('actionlint', 'any'),
|
|
10
|
+
file: (0, util_1.repoPath)(e.filepath, ctx), line: e.line, message: e.message ?? '', snippet: (e.snippet ?? e.message ?? '').split('\n')[0],
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eslint = eslint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** ESLint JSON: `filePath` is absolute inside the container. A message without a rule is a parse error. */
|
|
6
|
+
function eslint(output, ctx) {
|
|
7
|
+
const files = (0, util_1.parseReport)('eslint', output);
|
|
8
|
+
return files.flatMap(f => (0, util_1.asArray)(f.messages).map(m => ({
|
|
9
|
+
tool: 'eslint', rule: m.ruleId ?? 'parse-error', category: 'quality', severity: (0, util_1.mapSeverity)('eslint', m.severity), stack: 'js',
|
|
10
|
+
file: (0, util_1.repoPath)(f.filePath, ctx), line: m.line, message: m.message ?? '', snippet: m.message ?? '',
|
|
11
|
+
})));
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitleaks = gitleaks;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** The secret value never leaves this function: the snippet is its sha256, and Match/Secret/commit data are dropped. */
|
|
6
|
+
function gitleaks(output, ctx) {
|
|
7
|
+
const leaks = (0, util_1.parseReport)('gitleaks', output);
|
|
8
|
+
return leaks.map(l => ({
|
|
9
|
+
tool: 'gitleaks', rule: l.RuleID ?? 'unknown', category: 'secret', severity: (0, util_1.mapSeverity)('gitleaks', 'any'),
|
|
10
|
+
file: (0, util_1.repoPath)(l.File ?? '', ctx), line: l.StartLine, message: l.Description ?? l.RuleID ?? 'secret',
|
|
11
|
+
snippet: (0, util_1.sha256)(l.Secret ?? l.Match ?? ''),
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.golangciLint = golangciLint;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/** golangci-lint JSON: runs inside the stack directory, so `Pos.Filename` is relative to it (or `../src/..` from the root mount). */
|
|
6
|
+
function golangciLint(output, ctx) {
|
|
7
|
+
const report = (0, util_1.parseReport)('golangci-lint', output);
|
|
8
|
+
return (0, util_1.asArray)(report.Issues).map(i => ({
|
|
9
|
+
tool: 'golangci-lint', rule: i.FromLinter ?? 'unknown', category: 'quality', severity: (0, util_1.mapSeverity)('golangci-lint', i.FromLinter), stack: 'go',
|
|
10
|
+
file: (0, util_1.repoPath)(i.Pos?.Filename ?? '', ctx, 'stack'), line: i.Pos?.Line, message: i.Text ?? '',
|
|
11
|
+
snippet: (0, util_1.asArray)(i.SourceLines).join('\n') || (i.Text ?? ''),
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.govulncheck = govulncheck;
|
|
4
|
+
const util_1 = require("./util");
|
|
5
|
+
/**
|
|
6
|
+
* govulncheck `-format json` is a stream. One finding per advisory and vulnerable module; `reachable` is true when
|
|
7
|
+
* some trace of it has a function frame in the user's own module (the first SBOM module, the one without version).
|
|
8
|
+
*/
|
|
9
|
+
function govulncheck(output, ctx) {
|
|
10
|
+
const messages = (0, util_1.parseReport)('govulncheck', output);
|
|
11
|
+
const main = messages.find(m => m.SBOM)?.SBOM?.modules?.[0]?.path;
|
|
12
|
+
const summaries = new Map();
|
|
13
|
+
for (const m of messages)
|
|
14
|
+
if (m.osv)
|
|
15
|
+
summaries.set(m.osv.id, m.osv.summary ?? m.osv.id);
|
|
16
|
+
const byKey = new Map();
|
|
17
|
+
for (const m of messages) {
|
|
18
|
+
if (!m.finding)
|
|
19
|
+
continue;
|
|
20
|
+
const trace = (0, util_1.asArray)(m.finding.trace);
|
|
21
|
+
const module = trace[0]?.module ?? 'unknown';
|
|
22
|
+
const calledFromMain = main !== undefined && trace.some(fr => fr.module === main && fr.function !== undefined);
|
|
23
|
+
const key = `${m.finding.osv}|${module}`;
|
|
24
|
+
const known = byKey.get(key);
|
|
25
|
+
if (known) {
|
|
26
|
+
if (calledFromMain)
|
|
27
|
+
known.reachable = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
byKey.set(key, {
|
|
31
|
+
tool: 'govulncheck', rule: m.finding.osv, category: 'dependency', severity: (0, util_1.mapSeverity)('govulncheck', 'any'), stack: 'go',
|
|
32
|
+
file: (0, util_1.stackFile)('go.mod', ctx), message: summaries.get(m.finding.osv) ?? m.finding.osv, snippet: module, reachable: calledFromMain,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return [...byKey.values()];
|
|
36
|
+
}
|