Skip to content

feat: 006 pinned scanner wrapper 및 sandbox lifecycle 구현 - #253

Merged
goodtu02 merged 3 commits into
devfrom
feat/252-006-scanner-wrapper-lifecycle
Jul 24, 2026
Merged

feat: 006 pinned scanner wrapper 및 sandbox lifecycle 구현#253
goodtu02 merged 3 commits into
devfrom
feat/252-006-scanner-wrapper-lifecycle

Conversation

@goodtu02

@goodtu02 goodtu02 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🎋 작업 중인 브랜치 및 이슈

🔎 주요 변경 사항

  • OpenGrep, Trivy, Syft를 고정 이미지·고정 인자·shell-less 실행으로 제한하는 공유 SAST wrapper 계약과 어댑터를 구현했습니다.
  • 고객 코드 실행, 빌드·패키지 설치, 저장소 도구 설정·suppression 사용, 동적 설정, 공개 egress를 차단하고 scanner별 offline 정책을 강제했습니다.
  • Fast 스캔 입력을 attested allowlist와 preflight digest에 결합된 platform-owned read-only selected mount로 제한하고, Deep 스캔만 repository root를 사용하도록 분리했습니다.
  • scanner 직전 workspace re-manifest, signed runtime attestation, 시도 번호·누적 deadline 검증, 실행 결과 관찰값 및 0-byte artifact 거부를 추가했습니다.
  • SastScanAttempt 영속화, scan별 active attempt 단일성, retry-eligible attempt 1에만 허용되는 attempt 2, final audit 결합, cleanup lifecycle 및 overdue reconciliation을 구현했습니다.
  • fetch 단계는 signed repository-binding SCM host만 허용하고 credential wipe/revoke 후 scanner 단계의 Result Ingress·telemetry-only egress로 전환하도록 provisioning contract를 분리했습니다.
  • 운영 환경에서 mock 분석·legacy scan 경로가 fail-closed 되도록 분리하고, mock/production scanner-run 조회를 하나의 최소 공개 타입으로 통일했습니다.
  • 기존 ScannerRun·AuditEvent 제약은 NOT VALID 후 online validation, 인덱스는 concurrent build로 구성했습니다.
  • 환경 변수 예시, 006 계약·quickstart·tasks와 회귀 테스트를 동기화했습니다.

✅ 컨벤션 확인

  • 브랜치명이 type/issue-number-short-feature 형식을 따르나요?
  • 이슈 제목과 PR 제목을 동일하게 작성했나요?
  • 커밋 메시지가 <type>: <description> 형식을 따르나요?

Check List

  • Assignees 등록을 하였나요?
  • 라벨(Label) 등록을 하였나요?
  • PR 머지 전 반드시 CI가 정상적으로 작동하는지 확인했나요?

검증

  • corepack pnpm lint
  • corepack pnpm test (shared 38, AI 17, web 54, API 74 suites / 307 tests, GitHub·CI·deployment contract 19)
  • corepack pnpm typecheck
  • corepack pnpm build
  • node --test test/runtime/*.test.mjs
  • prisma validate
  • git diff --check

006 진행 상태

  • T025-T028 완료
  • 다음 작업: T029 per-scan write-only artifact ingress 및 workload identity 검증

Closes #252

Summary by CodeRabbit

  • New Features

    • Added attested, sandboxed SAST scanning with pinned scanner execution and verified cleanup.
    • Added scan-attempt lifecycle tracking, audit visibility, retry handling, and overdue-attempt reconciliation.
    • Added stronger runtime isolation, including restricted egress, non-root execution, and fail-closed behavior.
  • Bug Fixes

    • Legacy analysis and scan paths now fail safely outside test-only mock mode.
    • Requests using caller-controlled legacy execution settings are rejected.
  • Documentation

    • Updated deployment configuration, bootstrap guidance, and production runtime contracts.

@goodtu02 goodtu02 added the ✨ feat 새로운 기능 추가 label Jul 24, 2026
@goodtu02 goodtu02 self-assigned this Jul 24, 2026
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@goodtu02, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a1ee74c-516e-47ec-b951-031208cbbbba

📥 Commits

Reviewing files that changed from the base of the PR and between 9c640eb and 90aa26a.

📒 Files selected for processing (22)
  • apps/api/package.json
  • apps/api/prisma/migrations/20260724150000_sast_scanner_runtime_lifecycle/migration.sql
  • apps/api/scripts/apply-online-sast-runtime-schema.mjs
  • apps/api/src/client/analysis/analysis-api.module.ts
  • apps/api/src/scan-plane/prisma-sast-scanner-runtime.store.ts
  • apps/api/src/scan-plane/scan-plane.service.ts
  • apps/api/src/scan-plane/scan-plane.types.ts
  • apps/api/src/scan-plane/scanner-sandbox-adapter.service.ts
  • apps/api/src/scan-plane/scanner-workspace-manifest.service.ts
  • apps/api/test/client/analysis/analysis-api.module.e2e-spec.ts
  • apps/api/test/scan-plane/prisma-sast-scanner-runtime.store.e2e-spec.ts
  • apps/api/test/scan-plane/sast-scanner-runtime.e2e-spec.ts
  • apps/api/test/scan-plane/scan-plane-production-read.e2e-spec.ts
  • apps/api/test/scan-plane/scan-plane.e2e-spec.ts
  • apps/api/test/scan-plane/scanner-runtime-persistence.e2e-spec.ts
  • deploy/oracle/BOOTSTRAP.md
  • deploy/scanner-sandbox/provisioning-contract.json
  • packages/shared/src/types/sast-wrapper.ts
  • packages/shared/test/shared-contract-exports.test.mjs
  • specs/006-production-sast-runtime-design/contracts/sast-runtime.md
  • specs/006-production-sast-runtime-design/quickstart.md
  • test/github-actions/scanner-sandbox-provisioning.test.mjs
📝 Walkthrough

Walkthrough

Introduces a plan-bound SAST scanner wrapper and attested sandbox lifecycle with strict validation, cleanup evidence, persistent attempt tracking, production fail-closed analysis routing, reconciliation, deployment contracts, and end-to-end coverage.

Changes

SAST runtime boundary

Layer / File(s) Summary
Runtime contracts and persistence schema
packages/shared/src/types/sast-wrapper.ts, apps/api/prisma/*
Adds shared wrapper types and validators, SAST attempt lifecycle models, scanner-run metadata, audit-event links, constraints, indexes, and lifecycle statuses.
Pinned wrapper and attestation validation
apps/api/src/scan-plane/scanner-sandbox-adapter.service.ts, apps/api/src/scan-plane/sandbox-runtime-attestation.service.ts, apps/api/src/scan-plane/scanner-workspace-manifest.service.ts
Generates immutable scanner policies and commands, verifies signed runtime and cleanup claims, validates workspace manifests, and provides a fail-closed sandbox provider.
Attempt execution and reconciliation
apps/api/src/scan-plane/sast-scanner-runtime.service.ts, apps/api/src/scan-plane/prisma-sast-scanner-runtime.store.ts, apps/api/src/scan-plane/sast-attempt-reconciliation.task.ts
Orchestrates attested scanner execution, deadlines, cleanup, audit signals, durable records, attempt finalization, and overdue-attempt failure handling.
Scan-plane wiring and fail-closed routing
apps/api/src/scan-plane/*, apps/api/src/client/analysis/*, apps/api/src/scan/*, apps/api/src/config/*
Wires the runtime into Scan Plane, isolates mock routes to test fixtures, blocks legacy analysis outside tests, adds attestation/reconciliation configuration, and marks scan-plane responses as non-cacheable.
Deployment contracts and validation coverage
deploy/*, specs/006-production-sast-runtime-design/*, apps/api/test/*, test/github-actions/*
Updates sandbox provisioning and bootstrap requirements, marks runtime tasks complete, and adds contract, persistence, execution, API, configuration, and routing tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • AigisAI/AegisAI_v2#124 — Extends the production-scan Prisma entities introduced by this earlier schema work.
  • AigisAI/AegisAI_v2#140 — Reworks the Scan Plane sandbox adapter flow replaced by the wrapper-based runtime.
  • AigisAI/AegisAI_v2#251 — Supplies repository preflight, attestation, and credential-lease primitives used by this runtime.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed [#252] The PR covers wrapper generation, attestation, cleanup lifecycle, production mock rejection, and the requested regression/contract coverage.
Out of Scope Changes check ✅ Passed The changes appear focused on the scanner-wrapper lifecycle, supporting contracts, tests, docs, and env/config updates, with no clear unrelated scope.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: implementing the pinned scanner wrapper and sandbox lifecycle.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c640eb2a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/api/src/scan-plane/scanner-sandbox-adapter.service.ts Outdated
Comment thread apps/api/src/scan-plane/prisma-sast-scanner-runtime.store.ts
Comment thread deploy/scanner-sandbox/provisioning-contract.json Outdated
Comment thread packages/shared/src/types/sast-wrapper.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/api/test/scan-plane/scan-plane.e2e-spec.ts (1)

155-170: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Prove the rejected legacy request never invokes execution.

The 403 assertion permits a regression where validation occurs after sandbox/scanner dispatch. Restore an assertion that the execution-adapter mock has zero calls after this request.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/test/scan-plane/scan-plane.e2e-spec.ts` around lines 155 - 170, Add
an assertion after the rejected request in the test case “rejects the legacy
caller-controlled workspace, timeout, and isolation execution shape” verifying
the execution-adapter mock has zero calls. Keep the existing 403 and
response-secret assertions unchanged, and use the mock symbol already defined
for execution dispatch.
🧹 Nitpick comments (2)
apps/api/test/client/analysis/analysis-api.module.e2e-spec.ts (1)

11-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the routing tests environment-independent and complete the matrix.

AnalysisApiModule selects its provider when the module is imported, so the first test depends on inherited CI environment variables rather than explicitly proving the test/mock contract. Isolate the import after setting the expected environment, and add the missing NODE_ENV: 'test' + ANALYSIS_CLIENT_MODE: 'internal' case asserting false.

Also applies to: 19-38

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/test/client/analysis/analysis-api.module.e2e-spec.ts` around lines
11 - 16, Update the routing tests around AnalysisApiModule to set the required
environment variables before importing or compiling the module, preventing
inherited CI state from affecting provider selection. Complete the test matrix
with the NODE_ENV='test' and ANALYSIS_CLIENT_MODE='internal' scenario, asserting
the expected false result, and isolate or reset module imports between cases so
each configuration is evaluated independently.
apps/api/prisma/migrations/20260724150000_sast_scanner_runtime_lifecycle/migration.sql (1)

167-277: 🩺 Stability & Availability | 🔵 Trivial

Blocking locks when altering existing ScannerRun / AuditEvent.

The new-table portion is fine (empty table), but the ScannerRun and AuditEvent alterations add foreign keys, CHECK constraints, and non-concurrent indexes that require full table scans and take SHARE ROW EXCLUSIVE locks, blocking writes for the duration on already-populated tables. If these tables are large in production, plan the deploy for a maintenance window (or split constraint creation into NOT VALID + later VALIDATE CONSTRAINT outside the migration transaction). Note the runtime_metadata_check is correctly gated on attemptId IS NOT NULL, so existing rows won't fail validation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/api/prisma/migrations/20260724150000_sast_scanner_runtime_lifecycle/migration.sql`
around lines 167 - 277, Update the existing ScannerRun and AuditEvent
alterations to avoid long blocking locks on populated tables: create foreign
keys and CHECK constraints as NOT VALID, then validate them separately outside
the migration transaction, and build the new indexes concurrently. Preserve the
attemptId-gated behavior of ScannerRun_runtime_metadata_check so existing rows
remain valid.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/scan-plane/scan-plane.service.ts`:
- Around line 85-122: Normalize listScannerRuns to an explicit, documented
return shape shared by both mock and persisted branches. Update the mock
scannerRuns mapping and Prisma select to expose the same fields, including
handling rawArtifactObjectKey and digest/termination fields consistently, or
declare an intentional union if the contract requires it; ensure consumers
receive a stable type in both modes.

In `@packages/shared/test/shared-contract-exports.test.mjs`:
- Around line 55-66: Update the export validation in the shared contract export
test to enumerate all exported declarations from contract and assert that the
complete set exactly matches the existing allow-list. Retain the current
required-export coverage while failing when any additional public interface,
const, function, or type is introduced.

---

Outside diff comments:
In `@apps/api/test/scan-plane/scan-plane.e2e-spec.ts`:
- Around line 155-170: Add an assertion after the rejected request in the test
case “rejects the legacy caller-controlled workspace, timeout, and isolation
execution shape” verifying the execution-adapter mock has zero calls. Keep the
existing 403 and response-secret assertions unchanged, and use the mock symbol
already defined for execution dispatch.

---

Nitpick comments:
In
`@apps/api/prisma/migrations/20260724150000_sast_scanner_runtime_lifecycle/migration.sql`:
- Around line 167-277: Update the existing ScannerRun and AuditEvent alterations
to avoid long blocking locks on populated tables: create foreign keys and CHECK
constraints as NOT VALID, then validate them separately outside the migration
transaction, and build the new indexes concurrently. Preserve the
attemptId-gated behavior of ScannerRun_runtime_metadata_check so existing rows
remain valid.

In `@apps/api/test/client/analysis/analysis-api.module.e2e-spec.ts`:
- Around line 11-16: Update the routing tests around AnalysisApiModule to set
the required environment variables before importing or compiling the module,
preventing inherited CI state from affecting provider selection. Complete the
test matrix with the NODE_ENV='test' and ANALYSIS_CLIENT_MODE='internal'
scenario, asserting the expected false result, and isolate or reset module
imports between cases so each configuration is evaluated independently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ed9eb263-ebf4-4a2c-9776-99ad0b18e127

📥 Commits

Reviewing files that changed from the base of the PR and between 02fb14b and 9c640eb.

📒 Files selected for processing (48)
  • .env.example
  • apps/api/.env.example
  • apps/api/prisma/migrations/20260724150000_sast_scanner_runtime_lifecycle/migration.sql
  • apps/api/prisma/schema.prisma
  • apps/api/src/bootstrap/configure-app.ts
  • apps/api/src/client/analysis/analysis-api.module.ts
  • apps/api/src/client/analysis/analysis-fixture.policy.ts
  • apps/api/src/client/analysis/disabled-analysis-api.client.ts
  • apps/api/src/client/analysis/mock-analysis-api.client.ts
  • apps/api/src/config/config.schema.ts
  • apps/api/src/config/config.types.ts
  • apps/api/src/scan-plane/prisma-sast-scanner-runtime.store.ts
  • apps/api/src/scan-plane/sandbox-runtime-attestation.service.ts
  • apps/api/src/scan-plane/sast-attempt-reconciliation.task.ts
  • apps/api/src/scan-plane/sast-scanner-runtime.service.ts
  • apps/api/src/scan-plane/sast-scanner-runtime.store.ts
  • apps/api/src/scan-plane/scan-plane-mock.controller.ts
  • apps/api/src/scan-plane/scan-plane.controller.ts
  • apps/api/src/scan-plane/scan-plane.dto.ts
  • apps/api/src/scan-plane/scan-plane.module.ts
  • apps/api/src/scan-plane/scan-plane.service.ts
  • apps/api/src/scan-plane/scan-plane.types.ts
  • apps/api/src/scan-plane/scanner-runtime.errors.ts
  • apps/api/src/scan-plane/scanner-sandbox-adapter.service.ts
  • apps/api/src/scan-plane/scanner-sandbox-runtime.provider.ts
  • apps/api/src/scan-plane/scanner-workspace-manifest.service.ts
  • apps/api/src/scan/scan.processor.ts
  • apps/api/src/scan/scan.service.ts
  • apps/api/test/client/analysis/analysis-api.module.e2e-spec.ts
  • apps/api/test/config/config.env-files.e2e-spec.ts
  • apps/api/test/scan-plane/prisma-sast-scanner-runtime.store.e2e-spec.ts
  • apps/api/test/scan-plane/sast-attempt-reconciliation.task.e2e-spec.ts
  • apps/api/test/scan-plane/sast-scanner-runtime.e2e-spec.ts
  • apps/api/test/scan-plane/scan-plane-production-read.e2e-spec.ts
  • apps/api/test/scan-plane/scan-plane.e2e-spec.ts
  • apps/api/test/scan-plane/scanner-runtime-persistence.e2e-spec.ts
  • apps/api/test/scan/scan.processor.e2e-spec.ts
  • apps/api/test/scan/scan.service.e2e-spec.ts
  • deploy/oracle/.env.example
  • deploy/oracle/BOOTSTRAP.md
  • deploy/scanner-sandbox/provisioning-contract.json
  • packages/shared/src/index.ts
  • packages/shared/src/types/sast-wrapper.ts
  • packages/shared/test/shared-contract-exports.test.mjs
  • specs/006-production-sast-runtime-design/contracts/sast-runtime.md
  • specs/006-production-sast-runtime-design/quickstart.md
  • specs/006-production-sast-runtime-design/tasks.md
  • test/github-actions/scanner-sandbox-provisioning.test.mjs
💤 Files with no reviewable changes (1)
  • apps/api/src/scan-plane/scan-plane.types.ts

Comment thread apps/api/src/scan-plane/scan-plane.service.ts Outdated
Comment thread packages/shared/test/shared-contract-exports.test.mjs Outdated
@goodtu02
goodtu02 merged commit 6c57222 into dev Jul 24, 2026
2 checks passed
@goodtu02
goodtu02 deleted the feat/252-006-scanner-wrapper-lifecycle branch July 24, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 006 pinned scanner wrapper 및 sandbox lifecycle 구현

1 participant