lastlight 0.1.15 → 0.2.1
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/README.md +265 -118
- package/agent-context/rules.md +62 -9
- package/agent-context/security.md +69 -0
- package/config/default.yaml +89 -0
- package/deploy/.env.production.example +20 -2
- package/deploy/entrypoint.sh +16 -17
- package/deploy/native/README.md +160 -0
- package/deploy/native/install.sh +110 -0
- package/deploy/native/lastlight.env.example +95 -0
- package/deploy/native/lastlight.service +50 -0
- package/deploy/sandbox-entrypoint.sh +59 -42
- package/dist/admin/auth.d.ts +1 -1
- package/dist/admin/auth.js +3 -1
- package/dist/admin/auth.js.map +1 -1
- package/dist/admin/chat-session-reader.d.ts +11 -14
- package/dist/admin/chat-session-reader.js +27 -51
- package/dist/admin/chat-session-reader.js.map +1 -1
- package/dist/admin/docker.d.ts +37 -0
- package/dist/admin/docker.js +86 -1
- package/dist/admin/docker.js.map +1 -1
- package/dist/admin/index.js +38 -3
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/log-search.test.d.ts +1 -0
- package/dist/admin/log-search.test.js +78 -0
- package/dist/admin/log-search.test.js.map +1 -0
- package/dist/admin/routes.d.ts +52 -3
- package/dist/admin/routes.js +780 -63
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/routes.test.js +680 -14
- package/dist/admin/routes.test.js.map +1 -1
- package/dist/admin/server-logs.test.d.ts +1 -0
- package/dist/admin/server-logs.test.js +58 -0
- package/dist/admin/server-logs.test.js.map +1 -0
- package/dist/admin/sessions.d.ts +26 -39
- package/dist/admin/sessions.js +86 -310
- package/dist/admin/sessions.js.map +1 -1
- package/dist/admin/sessions.test.d.ts +1 -0
- package/dist/admin/sessions.test.js +78 -0
- package/dist/admin/sessions.test.js.map +1 -0
- package/dist/admin/version.d.ts +15 -0
- package/dist/admin/version.js +73 -0
- package/dist/admin/version.js.map +1 -0
- package/dist/admin/version.test.d.ts +1 -0
- package/dist/admin/version.test.js +71 -0
- package/dist/admin/version.test.js.map +1 -0
- package/dist/cli-config.d.ts +55 -0
- package/dist/cli-config.js +119 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/cli-config.test.d.ts +1 -0
- package/dist/cli-config.test.js +92 -0
- package/dist/cli-config.test.js.map +1 -0
- package/dist/cli-format.d.ts +19 -0
- package/dist/cli-format.js +107 -0
- package/dist/cli-format.js.map +1 -0
- package/dist/cli-server.d.ts +73 -0
- package/dist/cli-server.js +347 -0
- package/dist/cli-server.js.map +1 -0
- package/dist/cli-server.test.d.ts +1 -0
- package/dist/cli-server.test.js +38 -0
- package/dist/cli-server.test.js.map +1 -0
- package/dist/cli-timeline.d.ts +35 -0
- package/dist/cli-timeline.js +373 -0
- package/dist/cli-timeline.js.map +1 -0
- package/dist/cli-timeline.test.d.ts +1 -0
- package/dist/cli-timeline.test.js +104 -0
- package/dist/cli-timeline.test.js.map +1 -0
- package/dist/cli.d.ts +0 -19
- package/dist/cli.js +910 -194
- package/dist/cli.js.map +1 -1
- package/dist/config-overlay.test.d.ts +1 -0
- package/dist/config-overlay.test.js +112 -0
- package/dist/config-overlay.test.js.map +1 -0
- package/dist/config-resolve.d.ts +28 -0
- package/dist/config-resolve.js +47 -0
- package/dist/config-resolve.js.map +1 -0
- package/dist/config-resolve.test.d.ts +1 -0
- package/dist/config-resolve.test.js +68 -0
- package/dist/config-resolve.test.js.map +1 -0
- package/dist/config.d.ts +62 -49
- package/dist/config.js +452 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +201 -32
- package/dist/config.test.js.map +1 -1
- package/dist/connectors/github-webhook.js +83 -5
- package/dist/connectors/github-webhook.js.map +1 -1
- package/dist/connectors/github-webhook.test.d.ts +1 -0
- package/dist/connectors/github-webhook.test.js +156 -0
- package/dist/connectors/github-webhook.test.js.map +1 -0
- package/dist/connectors/messaging/session-manager.d.ts +18 -0
- package/dist/connectors/messaging/session-manager.js +83 -2
- package/dist/connectors/messaging/session-manager.js.map +1 -1
- package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
- package/dist/connectors/messaging/session-manager.test.js +144 -0
- package/dist/connectors/messaging/session-manager.test.js.map +1 -0
- package/dist/connectors/slack/connector.d.ts +9 -0
- package/dist/connectors/slack/connector.js +15 -0
- package/dist/connectors/slack/connector.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.js +81 -0
- package/dist/connectors/slack/mrkdwn.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.test.js +49 -0
- package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
- package/dist/connectors/types.d.ts +1 -1
- package/dist/cron/fanout.d.ts +33 -0
- package/dist/cron/fanout.js +55 -0
- package/dist/cron/fanout.js.map +1 -0
- package/dist/cron/fanout.test.d.ts +1 -0
- package/dist/cron/fanout.test.js +73 -0
- package/dist/cron/fanout.test.js.map +1 -0
- package/dist/cron/jobs.d.ts +5 -0
- package/dist/cron/jobs.js +10 -3
- package/dist/cron/jobs.js.map +1 -1
- package/dist/cron/scheduler.d.ts +12 -0
- package/dist/cron/scheduler.js +27 -1
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/engine/agent-executor.d.ts +158 -0
- package/dist/engine/agent-executor.js +1140 -0
- package/dist/engine/agent-executor.js.map +1 -0
- package/dist/engine/agent-executor.test.d.ts +1 -0
- package/dist/engine/agent-executor.test.js +395 -0
- package/dist/engine/agent-executor.test.js.map +1 -0
- package/dist/engine/chat-runner.d.ts +123 -0
- package/dist/engine/chat-runner.js +379 -0
- package/dist/engine/chat-runner.js.map +1 -0
- package/dist/engine/chat-runner.test.d.ts +1 -0
- package/dist/engine/chat-runner.test.js +104 -0
- package/dist/engine/chat-runner.test.js.map +1 -0
- package/dist/engine/chat-skills.d.ts +45 -0
- package/dist/engine/chat-skills.js +184 -0
- package/dist/engine/chat-skills.js.map +1 -0
- package/dist/engine/chat-skills.test.d.ts +1 -0
- package/dist/engine/chat-skills.test.js +20 -0
- package/dist/engine/chat-skills.test.js.map +1 -0
- package/dist/engine/chat.d.ts +20 -23
- package/dist/engine/chat.js +251 -155
- package/dist/engine/chat.js.map +1 -1
- package/dist/engine/chat.test.d.ts +1 -0
- package/dist/engine/chat.test.js +42 -0
- package/dist/engine/chat.test.js.map +1 -0
- package/dist/engine/classifier.d.ts +35 -2
- package/dist/engine/classifier.js +170 -31
- package/dist/engine/classifier.js.map +1 -1
- package/dist/engine/classifier.test.d.ts +1 -0
- package/dist/engine/classifier.test.js +115 -0
- package/dist/engine/classifier.test.js.map +1 -0
- package/dist/engine/dispatcher.d.ts +60 -0
- package/dist/engine/dispatcher.js +601 -0
- package/dist/engine/dispatcher.js.map +1 -0
- package/dist/engine/dispatcher.test.d.ts +1 -0
- package/dist/engine/dispatcher.test.js +511 -0
- package/dist/engine/dispatcher.test.js.map +1 -0
- package/dist/engine/event-shim.d.ts +117 -0
- package/dist/engine/event-shim.js +435 -0
- package/dist/engine/event-shim.js.map +1 -0
- package/dist/engine/event-shim.test.d.ts +1 -0
- package/dist/engine/event-shim.test.js +194 -0
- package/dist/engine/event-shim.test.js.map +1 -0
- package/dist/engine/git-auth.d.ts +13 -17
- package/dist/engine/git-auth.js +99 -42
- package/dist/engine/git-auth.js.map +1 -1
- package/dist/engine/git-auth.test.d.ts +1 -0
- package/dist/engine/git-auth.test.js +117 -0
- package/dist/engine/git-auth.test.js.map +1 -0
- package/dist/engine/github-app-client.d.ts +7 -0
- package/dist/engine/github-app-client.js +16 -0
- package/dist/engine/github-app-client.js.map +1 -0
- package/dist/engine/github-app-client.test.d.ts +1 -0
- package/dist/engine/github-app-client.test.js +44 -0
- package/dist/engine/github-app-client.test.js.map +1 -0
- package/dist/engine/github-tools.d.ts +12 -0
- package/dist/engine/github-tools.js +261 -0
- package/dist/engine/github-tools.js.map +1 -0
- package/dist/engine/github.d.ts +1027 -43
- package/dist/engine/github.js +153 -14
- package/dist/engine/github.js.map +1 -1
- package/dist/engine/llm.d.ts +47 -0
- package/dist/engine/llm.js +221 -0
- package/dist/engine/llm.js.map +1 -0
- package/dist/engine/llm.test.d.ts +1 -0
- package/dist/engine/llm.test.js +189 -0
- package/dist/engine/llm.test.js.map +1 -0
- package/dist/engine/profiles.d.ts +249 -0
- package/dist/engine/profiles.js +42 -0
- package/dist/engine/profiles.js.map +1 -0
- package/dist/engine/router.d.ts +12 -6
- package/dist/engine/router.js +339 -81
- package/dist/engine/router.js.map +1 -1
- package/dist/engine/router.test.js +428 -78
- package/dist/engine/router.test.js.map +1 -1
- package/dist/engine/screen.d.ts +41 -0
- package/dist/engine/screen.js +93 -0
- package/dist/engine/screen.js.map +1 -0
- package/dist/engine/screen.test.d.ts +1 -0
- package/dist/engine/screen.test.js +82 -0
- package/dist/engine/screen.test.js.map +1 -0
- package/dist/index.js +377 -432
- package/dist/index.js.map +1 -1
- package/dist/managed-repos.d.ts +7 -9
- package/dist/managed-repos.js +12 -15
- package/dist/managed-repos.js.map +1 -1
- package/dist/managed-repos.test.js +24 -19
- package/dist/managed-repos.test.js.map +1 -1
- package/dist/notify/index.d.ts +15 -0
- package/dist/notify/index.js +6 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/model.d.ts +57 -0
- package/dist/notify/model.js +89 -0
- package/dist/notify/model.js.map +1 -0
- package/dist/notify/model.test.d.ts +1 -0
- package/dist/notify/model.test.js +109 -0
- package/dist/notify/model.test.js.map +1 -0
- package/dist/notify/notifier.d.ts +17 -0
- package/dist/notify/notifier.js +87 -0
- package/dist/notify/notifier.js.map +1 -0
- package/dist/notify/notifier.test.d.ts +1 -0
- package/dist/notify/notifier.test.js +100 -0
- package/dist/notify/notifier.test.js.map +1 -0
- package/dist/notify/render.d.ts +21 -0
- package/dist/notify/render.js +59 -0
- package/dist/notify/render.js.map +1 -0
- package/dist/notify/render.test.d.ts +1 -0
- package/dist/notify/render.test.js +65 -0
- package/dist/notify/render.test.js.map +1 -0
- package/dist/notify/transports/github.d.ts +26 -0
- package/dist/notify/transports/github.js +26 -0
- package/dist/notify/transports/github.js.map +1 -0
- package/dist/notify/transports/slack.d.ts +26 -0
- package/dist/notify/transports/slack.js +28 -0
- package/dist/notify/transports/slack.js.map +1 -0
- package/dist/notify/transports.test.d.ts +1 -0
- package/dist/notify/transports.test.js +71 -0
- package/dist/notify/transports.test.js.map +1 -0
- package/dist/notify/types.d.ts +95 -0
- package/dist/notify/types.js +16 -0
- package/dist/notify/types.js.map +1 -0
- package/dist/sandbox/docker-compose.test.d.ts +1 -0
- package/dist/sandbox/docker-compose.test.js +128 -0
- package/dist/sandbox/docker-compose.test.js.map +1 -0
- package/dist/sandbox/docker.d.ts +97 -9
- package/dist/sandbox/docker.js +192 -41
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/docker.test.d.ts +1 -0
- package/dist/sandbox/docker.test.js +137 -0
- package/dist/sandbox/docker.test.js.map +1 -0
- package/dist/sandbox/egress-allowlist.d.ts +69 -0
- package/dist/sandbox/egress-allowlist.js +164 -0
- package/dist/sandbox/egress-allowlist.js.map +1 -0
- package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
- package/dist/sandbox/egress-allowlist.test.js +65 -0
- package/dist/sandbox/egress-allowlist.test.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.d.ts +127 -0
- package/dist/sandbox/egress-firewall-config.js +434 -0
- package/dist/sandbox/egress-firewall-config.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
- package/dist/sandbox/egress-firewall-config.test.js +244 -0
- package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
- package/dist/sandbox/images.d.ts +23 -0
- package/dist/sandbox/images.js +55 -0
- package/dist/sandbox/images.js.map +1 -0
- package/dist/sandbox/index.d.ts +82 -3
- package/dist/sandbox/index.js +223 -93
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/index.test.d.ts +1 -0
- package/dist/sandbox/index.test.js +157 -0
- package/dist/sandbox/index.test.js.map +1 -0
- package/dist/session-log.d.ts +63 -0
- package/dist/session-log.js +290 -0
- package/dist/session-log.js.map +1 -0
- package/dist/session-log.test.d.ts +1 -0
- package/dist/session-log.test.js +85 -0
- package/dist/session-log.test.js.map +1 -0
- package/dist/setup.d.ts +30 -1
- package/dist/setup.js +241 -25
- package/dist/setup.js.map +1 -1
- package/dist/setup.test.js +138 -6
- package/dist/setup.test.js.map +1 -1
- package/dist/state/approval-store.d.ts +86 -0
- package/dist/state/approval-store.js +140 -0
- package/dist/state/approval-store.js.map +1 -0
- package/dist/state/build-assets.d.ts +50 -0
- package/dist/state/build-assets.js +154 -0
- package/dist/state/build-assets.js.map +1 -0
- package/dist/state/build-assets.test.d.ts +1 -0
- package/dist/state/build-assets.test.js +106 -0
- package/dist/state/build-assets.test.js.map +1 -0
- package/dist/state/db.d.ts +65 -333
- package/dist/state/db.js +112 -835
- package/dist/state/db.js.map +1 -1
- package/dist/state/db.test.js +127 -91
- package/dist/state/db.test.js.map +1 -1
- package/dist/state/execution-store.d.ts +257 -0
- package/dist/state/execution-store.js +527 -0
- package/dist/state/execution-store.js.map +1 -0
- package/dist/state/migrate.d.ts +15 -0
- package/dist/state/migrate.js +175 -0
- package/dist/state/migrate.js.map +1 -0
- package/dist/state/workflow-run-store.d.ts +195 -0
- package/dist/state/workflow-run-store.js +363 -0
- package/dist/state/workflow-run-store.js.map +1 -0
- package/dist/state/workflow-run-store.test.d.ts +1 -0
- package/dist/state/workflow-run-store.test.js +264 -0
- package/dist/state/workflow-run-store.test.js.map +1 -0
- package/dist/telemetry/index.d.ts +38 -0
- package/dist/telemetry/index.js +253 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/index.test.d.ts +1 -0
- package/dist/telemetry/index.test.js +73 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/pi-events.d.ts +12 -0
- package/dist/telemetry/pi-events.js +134 -0
- package/dist/telemetry/pi-events.js.map +1 -0
- package/dist/telemetry/pi-events.test.d.ts +1 -0
- package/dist/telemetry/pi-events.test.js +69 -0
- package/dist/telemetry/pi-events.test.js.map +1 -0
- package/dist/workflows/dag.d.ts +13 -1
- package/dist/workflows/dag.js +7 -3
- package/dist/workflows/dag.js.map +1 -1
- package/dist/workflows/dag.test.js +22 -0
- package/dist/workflows/dag.test.js.map +1 -1
- package/dist/workflows/golden-build.test.d.ts +1 -0
- package/dist/workflows/golden-build.test.js +45 -0
- package/dist/workflows/golden-build.test.js.map +1 -0
- package/dist/workflows/loader-overlay.test.d.ts +1 -0
- package/dist/workflows/loader-overlay.test.js +101 -0
- package/dist/workflows/loader-overlay.test.js.map +1 -0
- package/dist/workflows/loader.d.ts +36 -11
- package/dist/workflows/loader.js +311 -87
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loader.test.js +114 -10
- package/dist/workflows/loader.test.js.map +1 -1
- package/dist/workflows/loop-eval.js +2 -0
- package/dist/workflows/loop-eval.js.map +1 -1
- package/dist/workflows/loop-eval.test.js +14 -0
- package/dist/workflows/loop-eval.test.js.map +1 -1
- package/dist/workflows/phase-executor.d.ts +145 -0
- package/dist/workflows/phase-executor.js +691 -0
- package/dist/workflows/phase-executor.js.map +1 -0
- package/dist/workflows/phase-executor.test.d.ts +1 -0
- package/dist/workflows/phase-executor.test.js +434 -0
- package/dist/workflows/phase-executor.test.js.map +1 -0
- package/dist/workflows/phase-ref.d.ts +44 -0
- package/dist/workflows/phase-ref.js +78 -0
- package/dist/workflows/phase-ref.js.map +1 -0
- package/dist/workflows/phase-ref.test.d.ts +1 -0
- package/dist/workflows/phase-ref.test.js +24 -0
- package/dist/workflows/phase-ref.test.js.map +1 -0
- package/dist/workflows/resume.d.ts +5 -11
- package/dist/workflows/resume.js +88 -7
- package/dist/workflows/resume.js.map +1 -1
- package/dist/workflows/runner.d.ts +34 -27
- package/dist/workflows/runner.js +252 -930
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/runner.test.js +346 -35
- package/dist/workflows/runner.test.js.map +1 -1
- package/dist/workflows/schema.d.ts +52 -10
- package/dist/workflows/schema.js +147 -7
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/simple.d.ts +67 -3
- package/dist/workflows/simple.js +248 -87
- package/dist/workflows/simple.js.map +1 -1
- package/dist/workflows/simple.test.d.ts +1 -0
- package/dist/workflows/simple.test.js +107 -0
- package/dist/workflows/simple.test.js.map +1 -0
- package/dist/workflows/templates.d.ts +29 -0
- package/dist/workflows/templates.js +42 -4
- package/dist/workflows/templates.js.map +1 -1
- package/dist/workflows/templates.test.js +103 -0
- package/dist/workflows/templates.test.js.map +1 -1
- package/dist/workflows/triggers.d.ts +21 -0
- package/dist/workflows/triggers.js +44 -0
- package/dist/workflows/triggers.js.map +1 -0
- package/dist/workflows/verdict.d.ts +19 -0
- package/dist/workflows/verdict.js +30 -0
- package/dist/workflows/verdict.js.map +1 -0
- package/dist/workflows/verdict.test.d.ts +1 -0
- package/dist/workflows/verdict.test.js +44 -0
- package/dist/workflows/verdict.test.js.map +1 -0
- package/dist/worktree/manager.d.ts +1 -1
- package/dist/worktree/manager.js +14 -14
- package/dist/worktree/manager.js.map +1 -1
- package/dist/worktree/manager.test.d.ts +1 -0
- package/dist/worktree/manager.test.js +87 -0
- package/dist/worktree/manager.test.js.map +1 -0
- package/docker-compose.yml +206 -5
- package/package.json +19 -9
- package/sandbox.Dockerfile +97 -18
- package/skills/README.md +40 -0
- package/skills/browser-qa/SKILL.md +193 -0
- package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
- package/skills/building/SKILL.md +95 -0
- package/skills/chat/SKILL.md +30 -11
- package/skills/code-review/SKILL.md +59 -0
- package/skills/debug-production/SKILL.md +108 -0
- package/skills/demo/SKILL.md +194 -0
- package/skills/demo/scripts/compose-demo.sh +205 -0
- package/skills/issue-answer/SKILL.md +90 -0
- package/skills/issue-comment/SKILL.md +38 -24
- package/skills/issue-triage/SKILL.md +103 -37
- package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
- package/skills/pr-comment/SKILL.md +64 -0
- package/skills/pr-review/SKILL.md +65 -49
- package/skills/qa-test/SKILL.md +97 -0
- package/skills/repo-health/SKILL.md +48 -45
- package/skills/security-feedback/SKILL.md +173 -0
- package/skills/security-feedback/references/templates.md +77 -0
- package/skills/security-review/SKILL.md +213 -0
- package/skills/security-review/references/issue-format.md +302 -0
- package/skills/verify/SKILL.md +118 -0
- package/workflows/answer.yaml +37 -0
- package/workflows/build.yaml +32 -22
- package/workflows/cron-security.yaml +6 -0
- package/workflows/demo.yaml +55 -0
- package/workflows/explore.yaml +9 -0
- package/workflows/pr-comment.yaml +16 -0
- package/workflows/pr-fix.yaml +3 -0
- package/workflows/pr-review.yaml +4 -1
- package/workflows/prompts/answer.md +67 -0
- package/workflows/prompts/architect.md +24 -7
- package/workflows/prompts/demo.md +100 -0
- package/workflows/prompts/executor.md +29 -20
- package/workflows/prompts/explore-ask.md +51 -22
- package/workflows/prompts/explore-publish.md +2 -2
- package/workflows/prompts/explore-read.md +24 -10
- package/workflows/prompts/explore-synthesize.md +15 -8
- package/workflows/prompts/fix.md +9 -10
- package/workflows/prompts/guardrails.md +26 -8
- package/workflows/prompts/pr-fix.md +6 -7
- package/workflows/prompts/pr.md +11 -10
- package/workflows/prompts/qa-browser.md +95 -0
- package/workflows/prompts/qa-synth.md +44 -0
- package/workflows/prompts/qa-test.md +60 -0
- package/workflows/prompts/re-reviewer.md +8 -9
- package/workflows/prompts/reviewer.md +10 -9
- package/workflows/prompts/verify-browser.md +93 -0
- package/workflows/prompts/verify-synth.md +44 -0
- package/workflows/prompts/verify.md +63 -0
- package/workflows/qa-test.yaml +87 -0
- package/workflows/security-feedback.yaml +25 -0
- package/workflows/security-review.yaml +29 -0
- package/workflows/verify.yaml +85 -0
- package/deploy/mcp-config.tmpl.json +0 -14
- package/dist/cron/rate-limits.d.ts +0 -26
- package/dist/cron/rate-limits.js +0 -193
- package/dist/cron/rate-limits.js.map +0 -1
- package/dist/engine/executor.d.ts +0 -75
- package/dist/engine/executor.js +0 -292
- package/dist/engine/executor.js.map +0 -1
- package/mcp-github-app/package.json +0 -18
- package/mcp-github-app/src/auth.js +0 -66
- package/mcp-github-app/src/github.js +0 -371
- package/mcp-github-app/src/index.js +0 -534
- package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
- package/skills/github/DESCRIPTION.md +0 -3
- package/skills/github/codebase-inspection/SKILL.md +0 -115
- package/skills/github/github-auth/SKILL.md +0 -54
- package/skills/github/github-auth/scripts/gh-env.sh +0 -66
- package/skills/github/github-code-review/SKILL.md +0 -480
- package/skills/github/github-code-review/references/review-output-template.md +0 -74
- package/skills/github/github-issues/SKILL.md +0 -369
- package/skills/github/github-issues/templates/bug-report.md +0 -35
- package/skills/github/github-issues/templates/feature-request.md +0 -31
- package/skills/github/github-pr-workflow/SKILL.md +0 -395
- package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
- package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
- package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
- package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
- package/skills/github/github-repo-management/SKILL.md +0 -515
- package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
- package/skills/github-orchestrator/SKILL.md +0 -103
- package/skills/mcp/DESCRIPTION.md +0 -3
- package/skills/mcp/mcporter/SKILL.md +0 -122
- package/skills/mcp/native-mcp/SKILL.md +0 -356
- package/skills/software-development/architect/SKILL.md +0 -154
- package/skills/software-development/assure-guardrails/SKILL.md +0 -239
- package/skills/software-development/plan/SKILL.md +0 -64
- package/skills/software-development/requesting-code-review/SKILL.md +0 -291
- package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
- package/skills/software-development/systematic-debugging/SKILL.md +0 -366
- package/skills/software-development/test-driven-development/SKILL.md +0 -342
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-feedback
|
|
3
|
+
description: Process a maintainer's comment on a security scan-summary issue — break selected findings out into individual actionable issues, or record accepted risks / false positives in SECURITY.md.
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
tags: [github, security, feedback]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Security Feedback
|
|
9
|
+
|
|
10
|
+
A maintainer commented on a `security`-labelled issue — almost always a per-run
|
|
11
|
+
**security scan summary** (one issue per scan, a task-list of findings). Based on
|
|
12
|
+
the comment, either:
|
|
13
|
+
|
|
14
|
+
- **Break selected findings into individual issues** (each can later feed `build`). Primary flow.
|
|
15
|
+
- **Record a suppression** in `SECURITY.md` (accepted risk / false positive).
|
|
16
|
+
- Reply for discussion, or ignore noise.
|
|
17
|
+
|
|
18
|
+
The parent issue's grammar is the contract defined in
|
|
19
|
+
`skills/security-review/references/issue-format.md`. This skill is staged into its
|
|
20
|
+
own workspace and **cannot read that file**, so it carries its own copy of the
|
|
21
|
+
row/severity regex below — **if you change the grammar, update both in lockstep.**
|
|
22
|
+
|
|
23
|
+
## Context
|
|
24
|
+
|
|
25
|
+
- `context.repo` — `owner/name`
|
|
26
|
+
- `context.issueNumber` — the security summary issue (parent)
|
|
27
|
+
- `context.commentBody` — the triggering comment
|
|
28
|
+
- `context.sender` — the commenter's GitHub login
|
|
29
|
+
|
|
30
|
+
The parent body is not passed — fetch it at step 1.
|
|
31
|
+
|
|
32
|
+
## 1. Fetch and parse the parent issue
|
|
33
|
+
|
|
34
|
+
`github_get_issue({ owner, repo, issue_number: issueNumber })`.
|
|
35
|
+
|
|
36
|
+
**Version check.** The body MUST start with `<!-- lastlight-security-scan-version: 1 -->`.
|
|
37
|
+
If the marker is missing or the version isn't `1`, reply: "Unknown scan-summary
|
|
38
|
+
format — this skill is at version 1 but the parent reports a different version.
|
|
39
|
+
Ask the maintainer to re-run `@last-light security-review`." Do not parse further.
|
|
40
|
+
|
|
41
|
+
**Parse each finding row** with this canonical regex (all three states):
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
/^- \[([ x])\] <!-- item:(\d+) fp:([0-9a-f]{8,}) --> (?:~~)?\*\*(.+?)\*\* — `([^`]+):(\d+)` \(([a-z][a-z0-9-]*) · `([^`]+)`\)(?:~~ → #(\d+))?$/m
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Captures: `checkbox` (` `/`x`), `item`, `fp`, `title`, `file`, `line`, `tool`,
|
|
48
|
+
`rule`, and `subIssueNumber` (only when already broken out). Derive per row:
|
|
49
|
+
|
|
50
|
+
| Derived | Definition |
|
|
51
|
+
|---------|------------|
|
|
52
|
+
| `alreadyBrokenOut` | `subIssueNumber != null` — turned into a sub-issue on a prior run |
|
|
53
|
+
| `userTicked` | `checkbox === "x" && !alreadyBrokenOut` — the maintainer ticked the box, selecting it |
|
|
54
|
+
|
|
55
|
+
`userTicked` is the primary selection signal; `alreadyBrokenOut` rows are never
|
|
56
|
+
re-selected regardless of checkbox state.
|
|
57
|
+
|
|
58
|
+
**Severity** comes from the nearest preceding section header (tolerating a
|
|
59
|
+
trailing truncation suffix like `(showing first 7 of 25)`):
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
/^### (🔴|🟠|🟡|🟢) (Critical|High|Medium|Low) \((\d+)\)(?:\s.*)?$/m
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Map Critical/High/Medium/Low → `p0-critical`/`p1-high`/`p2-medium`/`p3-low`.
|
|
66
|
+
|
|
67
|
+
**Parse the `<details>` block** after each row (starts `<details><summary>Details</summary>`,
|
|
68
|
+
ends `</details>`): the fenced block → `snippet` + `language`; paragraphs between
|
|
69
|
+
the fence and `**Suggested fix:**` → `explanation`; text after `**Suggested fix:**`
|
|
70
|
+
→ `suggestedFix`.
|
|
71
|
+
|
|
72
|
+
Store each finding as `{ item, fp, title, file, line, tool, rule, severity,
|
|
73
|
+
language, snippet, explanation, suggestedFix, userTicked, alreadyBrokenOut, subIssueNumber? }`.
|
|
74
|
+
|
|
75
|
+
## 2. Classify the comment intent
|
|
76
|
+
|
|
77
|
+
Pick the single best-fit bucket:
|
|
78
|
+
|
|
79
|
+
- **create-issues** — break selected findings out. Signals: bare `@last-light
|
|
80
|
+
create issues` (defaults to ticked), "create issues for…", "make issues for…",
|
|
81
|
+
"break out…", "file sub-issues for…", "create an issue for items 1, 3".
|
|
82
|
+
- **accept-risk** — accept a finding's risk. Signals: "accept-risk:", "we know
|
|
83
|
+
about this", "won't fix", "accepted".
|
|
84
|
+
- **false-positive** — not real. Signals: "false-positive:", "not a vulnerability",
|
|
85
|
+
"not applicable".
|
|
86
|
+
- **reopen** — re-evaluate a suppressed finding. Signals: "reopen", "re-evaluate".
|
|
87
|
+
- **discuss** — a question or conversation about the findings.
|
|
88
|
+
- **ignore** — noise (thanks, unrelated remark).
|
|
89
|
+
|
|
90
|
+
`accept-risk` / `false-positive` / `reopen` MUST name a specific finding via
|
|
91
|
+
`item N` / `item: N` — fall through to `discuss` if unresolved.
|
|
92
|
+
|
|
93
|
+
## 3. Act
|
|
94
|
+
|
|
95
|
+
### create-issues
|
|
96
|
+
|
|
97
|
+
1. **Resolve the selection** (first match wins):
|
|
98
|
+
- **`ticked` / `checked` / `selected`** → every `userTicked` finding. Preferred UX.
|
|
99
|
+
- **Default (no qualifier)** → treat as `ticked`. If no rows are ticked, reply:
|
|
100
|
+
```
|
|
101
|
+
No rows are ticked. Tick the checkboxes on the findings you want broken out, then comment again — or use one of:
|
|
102
|
+
- `@last-light create issues for the criticals`
|
|
103
|
+
- `@last-light create issues for items 1, 3, 5`
|
|
104
|
+
- `@last-light create issues for all`
|
|
105
|
+
```
|
|
106
|
+
- `all` / `every` → every parsed finding regardless of tick state.
|
|
107
|
+
- `criticals` / `the criticals` / `p0-critical` → every `p0-critical` (same for
|
|
108
|
+
highs/mediums/lows). A count in the comment ("5 criticals") is ignored.
|
|
109
|
+
- `items N, M` / `item N` → specific 1-based item numbers from `<!-- item:N -->`.
|
|
110
|
+
|
|
111
|
+
In every form, silently drop `alreadyBrokenOut` findings and mention them in the
|
|
112
|
+
summary. If the selection is empty, reply:
|
|
113
|
+
```
|
|
114
|
+
No findings matched `{selection text}`. This scan has: {nC} critical, {nH} high, {nM} medium, {nL} low. Ticked: {nTicked}. Already broken out: {nDone}.
|
|
115
|
+
```
|
|
116
|
+
and create nothing. If the form is unrecognised (ambiguous), ask for clarification — don't guess.
|
|
117
|
+
|
|
118
|
+
2. **For each selected finding**, `github_create_issue` using the sub-issue body
|
|
119
|
+
template in [references/templates.md](references/templates.md). Record each new
|
|
120
|
+
`subIssueNumber` against its `item`.
|
|
121
|
+
|
|
122
|
+
3. **Rewrite the parent body.** For every finding just broken out, transition its
|
|
123
|
+
row to **broken-out**:
|
|
124
|
+
```
|
|
125
|
+
- [x] <!-- item:N fp:FP --> ~~**TITLE** — `FILE:LINE` (TOOL · `RULE`)~~ → #SUBISSUE
|
|
126
|
+
```
|
|
127
|
+
(checkbox `[x]`, title+location wrapped in `~~…~~`, ` → #SUBISSUE` appended).
|
|
128
|
+
Match by `item:N`. Do **not** touch rows that weren't selected, even if ticked.
|
|
129
|
+
Preserve all other content byte-for-byte. `github_update_issue`.
|
|
130
|
+
|
|
131
|
+
4. **Post a summary comment** on the parent:
|
|
132
|
+
```
|
|
133
|
+
Created {N} sub-issue(s) at @{sender}'s request:
|
|
134
|
+
|
|
135
|
+
- #{subN1} — {title 1} (item {item1})
|
|
136
|
+
…
|
|
137
|
+
|
|
138
|
+
{if any skipped}: Skipped {M} item(s) already broken out: items {list}.
|
|
139
|
+
|
|
140
|
+
Comment `@last-light build` on any sub-issue to start a fix.
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### accept-risk / false-positive
|
|
144
|
+
|
|
145
|
+
1. Resolve the target by `item N`; fall through to `discuss` if absent/unknown.
|
|
146
|
+
2. Extract the reason (text after the first `:`, trimmed; "no reason given" if absent).
|
|
147
|
+
3. `github_clone_repo`. Read `SECURITY.md`; create from the scaffold in
|
|
148
|
+
[references/templates.md](references/templates.md) if missing.
|
|
149
|
+
4. Append a row to the matching table (accepted risks OR false positives) per the
|
|
150
|
+
template.
|
|
151
|
+
5. Commit on branch `security/feedback-{parentIssueNumber}-{shortFingerprint}`,
|
|
152
|
+
push, and open a PR titled `security: record {accept-risk|false-positive} for {shortFingerprint}`.
|
|
153
|
+
6. Comment on the parent: `Opened PR #{prNumber} to record this in SECURITY.md.
|
|
154
|
+
Once merged, this finding will be suppressed in future scans.`
|
|
155
|
+
7. Do **not** tick the task-list checkbox — that marker is reserved for "broken out to sub-issue".
|
|
156
|
+
|
|
157
|
+
### reopen
|
|
158
|
+
|
|
159
|
+
Reply: "To re-evaluate this finding, run `@last-light security-review` — the next
|
|
160
|
+
scan re-picks it up if `SECURITY.md` has been updated." Do not modify `SECURITY.md`.
|
|
161
|
+
|
|
162
|
+
### discuss
|
|
163
|
+
|
|
164
|
+
Reply conversationally using the finding's `<details>` block (risk, tool, suggested
|
|
165
|
+
fix). Don't modify `SECURITY.md` or create sub-issues.
|
|
166
|
+
|
|
167
|
+
### ignore
|
|
168
|
+
|
|
169
|
+
Take no action.
|
|
170
|
+
|
|
171
|
+
## Tool usage
|
|
172
|
+
|
|
173
|
+
GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or raw HTTP.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# security-feedback templates
|
|
2
|
+
|
|
3
|
+
## Sub-issue body (create-issues)
|
|
4
|
+
|
|
5
|
+
`github_create_issue` with `title` = the finding's `title` (exactly as parsed, no
|
|
6
|
+
prefix/suffix), `labels` = `["security", severity]` (e.g. `["security",
|
|
7
|
+
"p0-critical"]`), and this body:
|
|
8
|
+
|
|
9
|
+
````markdown
|
|
10
|
+
<!-- fp:{fingerprint} -->
|
|
11
|
+
<!-- parent-security-scan: #{parentIssueNumber} -->
|
|
12
|
+
|
|
13
|
+
Broken out from security scan #{parentIssueNumber} on {today's date} at @{sender}'s request.
|
|
14
|
+
|
|
15
|
+
**File**: `{file}:{line}`
|
|
16
|
+
**Tool**: {tool} · `{rule}`
|
|
17
|
+
**Severity**: {severity}
|
|
18
|
+
|
|
19
|
+
```{language}
|
|
20
|
+
{snippet}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
{explanation}
|
|
24
|
+
|
|
25
|
+
## Suggested fix
|
|
26
|
+
|
|
27
|
+
{suggestedFix}
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
_To build a fix for this finding, comment `@last-light build` on this issue._
|
|
32
|
+
````
|
|
33
|
+
|
|
34
|
+
## SECURITY.md scaffold (accept-risk / false-positive)
|
|
35
|
+
|
|
36
|
+
Create this if `SECURITY.md` is missing, then append the row:
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
# SECURITY.md
|
|
40
|
+
|
|
41
|
+
This file configures the Last Light security scanner for this repository.
|
|
42
|
+
|
|
43
|
+
## Tool configuration
|
|
44
|
+
|
|
45
|
+
| Tool | Severity floor |
|
|
46
|
+
|------|---------------|
|
|
47
|
+
| npm-audit | medium |
|
|
48
|
+
| semgrep | medium |
|
|
49
|
+
| gitleaks | high |
|
|
50
|
+
| claude | medium |
|
|
51
|
+
|
|
52
|
+
## Accepted risks
|
|
53
|
+
|
|
54
|
+
Findings in this table are known risks the maintainers have explicitly accepted.
|
|
55
|
+
The scanner will not re-file issues for these findings.
|
|
56
|
+
|
|
57
|
+
| Fingerprint | Title | Reason | Date | Issue |
|
|
58
|
+
|-------------|-------|--------|------|-------|
|
|
59
|
+
|
|
60
|
+
## False positives
|
|
61
|
+
|
|
62
|
+
Findings in this table have been classified as not real security issues.
|
|
63
|
+
The scanner will not re-file issues for these findings.
|
|
64
|
+
|
|
65
|
+
| Fingerprint | Title | Reason | Date | Issue |
|
|
66
|
+
|-------------|-------|--------|------|-------|
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Appended row (to whichever table matches the intent):
|
|
70
|
+
|
|
71
|
+
| Column | Value |
|
|
72
|
+
|--------|-------|
|
|
73
|
+
| Fingerprint | First 16 hex chars of the finding's `fp` |
|
|
74
|
+
| Title | Finding's `title` |
|
|
75
|
+
| Reason | Extracted reason (text after the first `:`; "no reason given" if absent) |
|
|
76
|
+
| Date | Today's date (YYYY-MM-DD, UTC) |
|
|
77
|
+
| Issue | `#{parentIssueNumber}` |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-review
|
|
3
|
+
description: Diff-scoped security review of SDLC concerns GitHub's scanners miss — workflow/CI hardening, auth changes, secret handling, supply-chain churn. Files one dated summary issue with a task-list of findings. Use on a security cron or when asked to scan a repo.
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
tags: [github, security, review]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Security Review
|
|
9
|
+
|
|
10
|
+
Review **what changed in the repo since the last scan** with a security lens,
|
|
11
|
+
focused on SDLC concerns that GitHub's built-in scanners (Dependabot, Code
|
|
12
|
+
Scanning, Secret Scanning) and Renovate don't cover. File **one summary issue
|
|
13
|
+
per run**, dated, containing a GitHub task list of any findings. Honour
|
|
14
|
+
`SECURITY.md` to suppress accepted risks and false positives.
|
|
15
|
+
|
|
16
|
+
This is **not** a general vulnerability scanner. It does not run `npm audit`
|
|
17
|
+
(Dependabot does). It does not run `semgrep --config auto` over the whole tree
|
|
18
|
+
(Code Scanning does). It looks at the diff since the prior scan and surfaces what
|
|
19
|
+
humans introduced — CI hardening, auth changes, secret handling in new code,
|
|
20
|
+
supply-chain churn.
|
|
21
|
+
|
|
22
|
+
The summary issue's structure is the machine-parsed contract a maintainer's
|
|
23
|
+
later comment is processed against (the `security-feedback` skill). It is defined
|
|
24
|
+
in **[references/issue-format.md](references/issue-format.md)** — follow it
|
|
25
|
+
exactly when composing the issue (§9).
|
|
26
|
+
|
|
27
|
+
## Context
|
|
28
|
+
|
|
29
|
+
- `context.repo` — `owner/name` to scan
|
|
30
|
+
- `context.deliverSlackSummary` — if true, output a one-line Slack summary as the final response
|
|
31
|
+
- `context.issueDir` — directory for the run summary file (e.g. `.lastlight/security-<date>`)
|
|
32
|
+
|
|
33
|
+
## Procedure
|
|
34
|
+
|
|
35
|
+
### 1. Clone, find the prior-scan anchor, read SECURITY.md
|
|
36
|
+
|
|
37
|
+
1. Clone the target repo via `github_clone_repo`.
|
|
38
|
+
2. **Prior scan anchor.** Query issues labelled `security-scan` (open OR closed),
|
|
39
|
+
newest first. Read the latest one's body for the
|
|
40
|
+
`<!-- lastlight-security-scan-ts: ... -->` comment and use that ISO-8601
|
|
41
|
+
timestamp as `priorScanTs`. No prior scan issue → `priorScanTs = now - 30 days`
|
|
42
|
+
(bootstrap floor — keeps the first run finite).
|
|
43
|
+
3. Read `SECURITY.md` at the repo root (if present): per-tool severity floors
|
|
44
|
+
(default `medium`; skip `low`/`info`), the accepted-risks table, and the
|
|
45
|
+
false-positives table (both keyed by finding fingerprint).
|
|
46
|
+
|
|
47
|
+
### 1.5. Compute the changeset
|
|
48
|
+
|
|
49
|
+
Most weeks the diff is dominated by Renovate/Dependabot churn — strip it so the
|
|
50
|
+
scope is what humans wrote.
|
|
51
|
+
|
|
52
|
+
1. `git log --since="${priorScanTs}" --pretty=format:'%H|%an|%ae|%s'`.
|
|
53
|
+
2. Drop a commit when **either**: author email matches
|
|
54
|
+
`*[bot]@users.noreply.github.com` and name is `dependabot[bot]` /
|
|
55
|
+
`renovate[bot]` / `github-actions[bot]`; OR the subject starts with
|
|
56
|
+
`chore(deps)`, `chore(deps-dev)`, `build(deps)`, `build(deps-dev)`, `fix(deps)`.
|
|
57
|
+
3. Accumulate changed files from the surviving commits
|
|
58
|
+
(`git diff-tree --no-commit-id --name-only -r ${sha}`) into a deduped
|
|
59
|
+
`changedFiles` set.
|
|
60
|
+
4. Drop entries that are **only** lockfiles (`package-lock.json`, `pnpm-lock.yaml`,
|
|
61
|
+
`yarn.lock`, `bun.lockb`, `Gemfile.lock`, `poetry.lock`, `uv.lock`,
|
|
62
|
+
`Cargo.lock`, `composer.lock`) — catches lockfile changes mixed into human commits.
|
|
63
|
+
5. Build `commitsReviewed` = surviving commits as `{ shortSha, subject }` (used in the scope note).
|
|
64
|
+
|
|
65
|
+
**Early exit.** If `changedFiles` is empty after filtering, **stop**: run no
|
|
66
|
+
scanner, create no issue, emit no Slack message. Write the run summary file (§10)
|
|
67
|
+
recording "no relevant changes since prior scan" and return.
|
|
68
|
+
|
|
69
|
+
### 2. Ensure labels exist
|
|
70
|
+
|
|
71
|
+
`github_create_label` for each (idempotent — ignore 422):
|
|
72
|
+
|
|
73
|
+
| Label | Color | Purpose |
|
|
74
|
+
|-------|-------|---------|
|
|
75
|
+
| `security` | `ee0701` | Any security-related issue |
|
|
76
|
+
| `security-scan` | `fbca04` | The per-run summary issue |
|
|
77
|
+
| `p0-critical` | `b60205` | Severity |
|
|
78
|
+
| `p1-high` | `d93f0b` | Severity |
|
|
79
|
+
| `p2-medium` | `fbca04` | Severity |
|
|
80
|
+
| `p3-low` | `0e8a16` | Severity |
|
|
81
|
+
|
|
82
|
+
### 3. Run change-scoped scanners
|
|
83
|
+
|
|
84
|
+
Three sources, all narrowed to the changeset. Do **not** run `npm audit` or
|
|
85
|
+
`semgrep --config auto .` over the whole tree (covered elsewhere; the noise
|
|
86
|
+
drowns the signal).
|
|
87
|
+
|
|
88
|
+
- **Gitleaks (commit range):**
|
|
89
|
+
`gitleaks detect --source . --log-opts="--since=${priorScanTs}" --report-format json --report-path /tmp/gitleaks.json`
|
|
90
|
+
— secrets introduced in the new history.
|
|
91
|
+
- **Semgrep (changed files only):**
|
|
92
|
+
`semgrep --config auto --json $(printf -- '--include=%s ' "${changedFiles[@]}")`
|
|
93
|
+
— only files that changed; far less noise.
|
|
94
|
+
- **Claude SDLC review** — the unique value-add. Read `git diff ${priorScanTs}..HEAD`
|
|
95
|
+
plus the current contents of changed files against the checklist below. Each
|
|
96
|
+
match becomes a finding with `tool: "claude"` and the §4 severity.
|
|
97
|
+
|
|
98
|
+
- **GitHub Actions / CI** (`.github/workflows/*.yml`): actions pinned by
|
|
99
|
+
floating ref (`@main`/`@master`/`@v1`) not a commit SHA; `pull_request_target`
|
|
100
|
+
that checks out the PR head; missing top-level/job `permissions:` block;
|
|
101
|
+
`${{ secrets.* }}` interpolated into shell/`run:`/echo where it can land in
|
|
102
|
+
logs; untrusted PR body/title/branch interpolated into a `run:` block.
|
|
103
|
+
- **Dockerfile / compose**: base images on floating tags (no digest) introduced
|
|
104
|
+
here; new `RUN curl … | sh` / `wget … | bash`; new `--privileged`/`--cap-add`,
|
|
105
|
+
removed `security_opt`/`read_only` hardening; new host-exposed ports without need.
|
|
106
|
+
- **Auth / authorization**: modified middleware, route guards, role checks, CORS,
|
|
107
|
+
JWT verification, OAuth handlers, webhook signature verification (HMAC compare,
|
|
108
|
+
`crypto.timingSafeEqual` replaced with `===`).
|
|
109
|
+
- **Secret handling in new code**: new `process.env.*` reads whose value flows
|
|
110
|
+
into a log or HTTP response; new code logging Authorization headers/cookies/tokens;
|
|
111
|
+
hardcoded key/URL-shaped literals gitleaks missed.
|
|
112
|
+
- **Shell exec on attacker-influenced args**: new `execSync`/`exec`/`spawn` where
|
|
113
|
+
any argument is non-static (concatenation, interpolation, request-derived).
|
|
114
|
+
- **Supply-chain churn** (`package.json` diff): **new** top-level
|
|
115
|
+
`dependencies`/`devDependencies` entries (not version bumps — filtered at §1.5);
|
|
116
|
+
flag package name + publisher, higher severity for typosquat-shaped names;
|
|
117
|
+
removed integrity controls (`npm ci` → `npm install`, dropped `--ignore-scripts`
|
|
118
|
+
or provenance flags).
|
|
119
|
+
- **Release / publish flows**: changes to publish scripts, `npm publish`, release
|
|
120
|
+
CI steps, signing keys — anything touching what users download.
|
|
121
|
+
|
|
122
|
+
If the only changes are docs/tests/unrelated config and none of the above
|
|
123
|
+
applied, the run legitimately has **no findings** — proceed to §8.
|
|
124
|
+
|
|
125
|
+
### 4. Normalize findings
|
|
126
|
+
|
|
127
|
+
Convert each to: `{ fingerprint, severity, tool, rule, file, line, title,
|
|
128
|
+
language, snippet, explanation, suggestedFix }`.
|
|
129
|
+
|
|
130
|
+
- `fingerprint` = `sha1(tool + ":" + rule + ":" + file + ":" + 3-line-context)`, lowercase hex.
|
|
131
|
+
- `severity` ∈ `p0-critical | p1-high | p2-medium | p3-low`.
|
|
132
|
+
- `tool` ∈ `npm-audit | semgrep | gitleaks | claude` (lowercase, hyphenated).
|
|
133
|
+
- `rule` = tool-native id, as-is. `file` = repo-relative, forward slashes.
|
|
134
|
+
- `line` = 1-based; `0` when not line-scoped. `title` = one line, no backticks/asterisks.
|
|
135
|
+
|
|
136
|
+
Severity mapping: npm-audit critical/high/moderate/low → p0/p1/p2/p3;
|
|
137
|
+
semgrep ERROR/WARNING/INFO → p1/p2/p3; gitleaks (all) → p1-high;
|
|
138
|
+
claude critical/high/medium/low → p0/p1/p2/p3.
|
|
139
|
+
|
|
140
|
+
### 5. Apply severity floor
|
|
141
|
+
|
|
142
|
+
Drop findings below the SECURITY.md floor (default `medium` → drops `p3-low`).
|
|
143
|
+
|
|
144
|
+
### 6. Filter accepted risks / false positives
|
|
145
|
+
|
|
146
|
+
Drop findings whose fingerprint prefix (first 16 hex chars) appears in the
|
|
147
|
+
SECURITY.md accepted-risks or false-positives tables.
|
|
148
|
+
|
|
149
|
+
### 7. Sort and cap
|
|
150
|
+
|
|
151
|
+
Sort by `(severity rank p0<p1<p2<p3, then file asc, then line asc)`.
|
|
152
|
+
|
|
153
|
+
The issue body has a hard 65,536-char GitHub limit. Cap: keep **ALL** `p0-critical`
|
|
154
|
+
and **ALL** `p1-high`; keep at most **10** of `p2-medium`+`p3-low` combined (the
|
|
155
|
+
first 10 after the sort). Assign 1-based `item` numbers top-to-bottom across the
|
|
156
|
+
**kept** findings. `overflow` = survived-filtering minus kept; surface it in the
|
|
157
|
+
overflow note.
|
|
158
|
+
|
|
159
|
+
The cap intentionally puts no ceiling on critical/high — if a misconfigured
|
|
160
|
+
scanner emits hundreds of highs and the body still overflows, raise the
|
|
161
|
+
`SECURITY.md` floor or tune the scanner's rule severities (fix at the source, not
|
|
162
|
+
by hiding real findings).
|
|
163
|
+
|
|
164
|
+
### 8. Early exit: no findings
|
|
165
|
+
|
|
166
|
+
If the filtered-and-capped list is empty, **do not** create the summary issue.
|
|
167
|
+
Write the run summary file (§10) recording why and return **silently** — no Slack
|
|
168
|
+
message. The cron is intentionally low-noise: only actual findings surface.
|
|
169
|
+
|
|
170
|
+
### 9. Compose and create the summary issue
|
|
171
|
+
|
|
172
|
+
Render the body per [references/issue-format.md](references/issue-format.md) and
|
|
173
|
+
`github_create_issue` with `title: Security scan — {YYYY-MM-DD}` (UTC),
|
|
174
|
+
`labels: ["security", "security-scan"]`. Record `summaryIssueNumber`. Do **not**
|
|
175
|
+
touch prior `security-scan` issues — each scan is a point-in-time snapshot.
|
|
176
|
+
|
|
177
|
+
### 10. Write the run summary file
|
|
178
|
+
|
|
179
|
+
Write `{issueDir}/security-summary.md`:
|
|
180
|
+
|
|
181
|
+
```markdown
|
|
182
|
+
# Security Scan Summary — {repo}
|
|
183
|
+
|
|
184
|
+
**Date**: {YYYY-MM-DD}
|
|
185
|
+
**Prior scan anchor**: {priorScanTs} (issue #{priorScanIssueNumber} or "bootstrap floor")
|
|
186
|
+
**Commits reviewed**: {N} (after filtering Renovate/Dependabot/lockfile-only)
|
|
187
|
+
**Changed files**: {nFiles}
|
|
188
|
+
**Summary issue**: #{summaryIssueNumber} (or "none — no findings")
|
|
189
|
+
|
|
190
|
+
**Scanner raw counts**: gitleaks: {n}, semgrep: {n}, claude: {n}
|
|
191
|
+
**After severity floor**: {n}
|
|
192
|
+
**After SECURITY.md filtering**: {n} (filed)
|
|
193
|
+
**Suppressed**: {n} (accepted: {nA}, false-positive: {nFP})
|
|
194
|
+
{if overflow > 0}: **Overflow**: {overflow} lower-severity findings omitted (cap: ALL critical/high + first 10 medium/low)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
On a §1.5 early exit, still write the file and state `**Early exit**: no human
|
|
198
|
+
commits since prior scan`.
|
|
199
|
+
|
|
200
|
+
### 11. Slack summary (optional)
|
|
201
|
+
|
|
202
|
+
If `context.deliverSlackSummary` is true, output as the final response:
|
|
203
|
+
|
|
204
|
+
- **With findings:**
|
|
205
|
+
```
|
|
206
|
+
*Security scan: {repo}* — {n} findings filed in #{summaryIssueNumber} ({N} commits since {priorScanDate})
|
|
207
|
+
Critical: {nC} · High: {nH} · Medium: {nM} · Low: {nL}
|
|
208
|
+
```
|
|
209
|
+
- **No findings** (scanners ran clean) or **§1.5 early exit** → emit nothing;
|
|
210
|
+
silence matches the cron's low-noise design. The run summary file still records
|
|
211
|
+
what was reviewed.
|
|
212
|
+
|
|
213
|
+
Otherwise output the run summary file contents as the final response.
|