Skip to content

fix(security): trust forwarding IPs only from configured proxies - #587

Open
seonghobae wants to merge 121 commits into
developfrom
fix/trusted-rate-limit-client-ip
Open

fix(security): trust forwarding IPs only from configured proxies#587
seonghobae wants to merge 121 commits into
developfrom
fix/trusted-rate-limit-client-ip

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Problem

Protected develop still contains multiple buyer-relevant trust-boundary weaknesses that this descendant repairs together: caller-controlled forwarding identity for the opt-in limiter, incomplete invitation/OIDC hardening, Unicode-inconsistent account identity, and an unauthenticated Stripe webhook path that can promote an organization from caller-supplied JSON. This PR removes those direct trust assumptions while preserving fail-closed operational evidence.

Exact current identity

  • contributor branch: fix/trusted-rate-limit-client-ip
  • exact contributor head: 660d27259c7027f6807f01a35caec87b4bd4ce5e
  • exact head tree: 6aee02140021b316d92195ce50977f47300ad150
  • protected live base: develop@2c328875e00e86537df3e965170be80532571cad
  • synthetic GitHub PR merge revision: e6baf270a91fe9df60f2e772ddabaf2d503a05cb
  • ancestry: 117 commits ahead, 0 behind; merge base is the protected live base
  • Ready/non-draft and mechanically mergeable at the latest fresh refetch
  • every review thread is resolved, but no qualifying independent APPROVED review exists

Any head/base/review/check movement invalidates revision-sensitive evidence until freshly revalidated. This body is traceability, not merge authority.

Security / availability contract

  • X-Forwarded-For is ignored unless the immediate network peer is explicitly listed in SCOPEWEAVE_TRUSTED_PROXY_IPS; trusted hops are parsed right-to-left and canonicalized, including IPv4-mapped/scoped IPv6 handling, while malformed evidence fails closed.
  • SCOPEWEAVE_RATE_LIMIT_BUCKETS_MAX bounds process-local client state; overflow identities share a fail-closed bucket. Numeric limiter configuration is safe-integer validated, with SCOPEWEAVE_RATE_LIMIT_MAX=0 as the explicit opt-out.
  • Public and supported direct-consumer entrypoints apply the same abuse-control boundary before invitation/OIDC guards and their database work. Blocked 429 requests remain represented in JSON and Prometheus request/4xx observability without exposing client identity.
  • Pending invite bearer tokens are not exposed by ordinary roster reads; explicit invite creation remains the one-time token handoff.
  • OIDC state is bounded/expiring; production OIDC validates discovered HTTPS authorization/token/JWKS endpoints, preserves provider metadata consistency, and leaves the unsupported core production OIDC path fail-closed.
  • Password, invitation, and production OIDC account paths share one JavaScript Unicode email canonicalization contract. Legacy canonical collisions are detected before rewrite inside an immediate transaction and stop startup with the conflicting IDs rather than silently merging tenant/user authority.
  • Stripe webhook verification binds HMAC validation to the exact bounded raw bytes, rejects stale/tampered/unsigned requests, and validates event shape only after authentication. A signed delivery is not entitlement authority: this PR acknowledges a verified event but does not derive orgs.plan from event payload. Durable provider-authoritative billing/reconciliation remains owned by [Commercial Gap] Build monotonic, auditable Stripe subscription lifecycle #488 and its active stack.
  • Deployment/runtime prerequisites and the process-local abuse-control limitation are documented in docs/deploy.md and the doctoring notes.

Exact-current-head evidence

All evidence below is anchored to contributor head 660d27259c7027f6807f01a35caec87b4bd4ce5e unless noted otherwise.

  • Server Tests run 33232835264, unit/API job 99048556600: checked out the exact contributor head under supported Node 22.13.0; unit/API suites and the owned c8 production-coverage path completed successfully. The browser E2E lane for the same exact head also completed successfully.
  • SAST Semgrep run 33232835232, job 99048567150: explicitly verified expected_sha == actual_sha == 660d272..., used the pinned scanner image, scanned 74 files with 257 rules, and reported zero findings. The historical synthetic-checkout defect previously recorded in this body does not reproduce on this exact head.
  • Security Scan, Dependency Review, Fuzz, the repository-native OSV Scanner workflow, CodeQL, and Semgrep OSS completed successfully on this head.
  • Stripe regressions prove an unsigned webhook cannot upgrade an organization and that even a correctly signed callback does not grant entitlement before durable provider reconciliation.
  • Unicode identity regressions cover canonical-equivalent non-ASCII legacy addresses, deterministic fail-closed collision handling, successful unambiguous migration, and uniqueness after canonicalization.
  • Current review-thread sweep returns zero unresolved threads. The newest Devin environment/rollout observations were verified against this exact head and resolved without source churn because they do not demonstrate current defects: Node 20 is outside the declared runtime, and canonical-email collision startup failure is the intentional ambiguity guard.

GitHub Advanced Security currently also emits neutral PR-attribution checks for osv-scanner (99048594787, “1 configuration not found”) and Trivy. These are not named branch-protection contexts or organization-required workflows. The repository-native OSV workflow itself succeeds, and the exact osvscanner.yml blob is unchanged from protected develop; the neutral GHAS attribution signal is therefore not being promoted to passing evidence or used as merge authority.

Current non-passing required control-plane evidence

Active organization ruleset 18156473 applies to the default branch and requires one approving review, resolution of review threads, and the centrally owned required workflows close-empty-pr.yml, opencode-review.yml, pr-review-merge-scheduler.yml, security-scan.yml, strix.yml, sast-semgrep.yml, and noema-review.yml. It dismisses stale reviews on push.

Two required central review lanes are currently non-passing for reasons outside the ScopeWeave source boundary:

  1. OpenCode — check/job 99048617966, run 33232834290, fails because there is no formal opencode-agent APPROVED or CHANGES_REQUESTED review whose commit_id equals 660d272.... The gate correctly rejects fallback/model-unavailable text as approval. The real central provider/review owner path has fresh exact-head reproduction and acceptance evidence in ContextualWisdomLab/.github#624; ScopeWeave does not synthesize a verdict or churn this clean head.
  2. Strix — job 99048593265, run 33232834363, fails closed after the central review sidecar (pinned to contextual-orchestrator@b21645116b352967e50fc497b87eb745b9cc8c61) first receives a 413, retries with reduced context, then routes a text security-review request through /v1/orchestrator/free to incompatible video-model candidates including Hunyuan Video and Veo variants and repeatedly receives HTTP 500 internal_error. No authoritative Strix report is produced. The real causal owner path is now advanced on existing ContextualWisdomLab/contextual-orchestrator#901 with the exact run/SHA, capability-routing RED acceptance, smallest-remedy boundary, and unchanged downstream GREEN canary.

These are review/control-plane failures, not evidence of an unaddressed ScopeWeave source finding. They remain non-passing until their owners repair the causal route and regenerate authoritative evidence on this unchanged head or its freshly revalidated successor.

Merge gate

Do not merge or enable auto-merge until the unchanged exact contributor head remains reconciled to protected develop, all applicable branch-protection and organization-required workflows are substantively terminal-passing on the correct revision, every current valid finding is addressed, and ruleset 18156473 has a qualifying independent approval that remains valid for the current head. In particular, OpenCode and Strix must regenerate authoritative current-head evidence after their owner repairs; model-only/fallback/status-only evidence cannot substitute for the formal review contract.

Pending, queued, skipped-required, cancelled, absent, neutral-required, failed, stale, predecessor, synthetic-only, placeholder-only, status-only, author-only, model-only, rate-limited, or infrastructure-only evidence is non-passing when applicable. A green CI result never excuses a semantic regression or missing required review/security authority.

Summary by CodeRabbit

  • 보안 강화

    • 초대·공개 공유 토큰이 요청 및 rate-limit 로그에서 자동 마스킹됩니다.
    • Stripe 웹훅의 서명, 타임스탬프, 본문 무결성을 검증하며 유효하지 않은 요청은 거부합니다.
    • OIDC 통신에서 안전한 공개 HTTPS 대상만 허용하고 응답 크기를 제한합니다.
  • 개선 사항

    • 이메일을 정규화해 대소문자·공백 차이로 인한 중복 계정을 방지합니다.
    • 로그인 및 가입 이메일 처리가 일관되게 개선되었습니다.
    • rate-limit 적용과 관측성이 강화되었습니다.
  • 문서

    • 배포 환경 변수와 Stripe 웹훅·프록시 보안 경계를 문서화했습니다.

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 25 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a4896379-64ee-4ffd-a616-b448c109b888

📥 Commits

Reviewing files that changed from the base of the PR and between 70928aa and f36eb24.

📒 Files selected for processing (11)
  • CHANGELOG.md
  • server/application_routes.mjs
  • server/application_routes_core.mjs
  • server/application_routes_implementation.mjs
  • server/db.mjs
  • server/public_https_transport.mjs
  • tests/api/email-identity.test.mjs
  • tests/api/email-unicode-identity.test.mjs
  • tests/api/oidc-provider-metadata.test.mjs
  • tests/api/rate-limit-shared-boundary.test.mjs
  • tests/unit/public-https-transport.test.mjs
📝 Walkthrough

Walkthrough

공개 앱의 rate-limit 구현을 공유 모듈로 통합했습니다. trusted proxy 식별과 로그 마스킹을 강화했습니다. 생산 OIDC, 공용 HTTPS 전송, 이메일 정규화 및 Stripe 웹훅 검증 경계를 추가했습니다. 회귀 테스트와 CI checkout 검증을 갱신했습니다.

Changes

보안 경계와 라우팅

Layer / File(s) Summary
전송 엔벨로프와 rate-limit
server/rate_limit.mjs, server/app.mjs, server/app_routes.mjs, docs/doctoring/trusted-proxy-client-ip.md, tests/api/ratelimit.test.mjs, tests/api/rate-limit-*.test.mjs
공유 rate-limit 모듈이 trusted proxy 체인, IP 정규화, bounded bucket, overflow bucket, 429 응답, 지표 및 로그 마스킹을 처리합니다.
보호 라우트 그래프와 이메일·OIDC
server/application_routes.mjs, server/application_routes_core.mjs, server/application_routes_implementation.mjs, server/auth.mjs, server/db.mjs, server/signup_metrics.mjs, tests/api/email-*.test.mjs, tests/api/oidc-*.test.mjs, tests/api/invite-security.test.mjs
라우트 그래프가 canonical email, 인증, 초대 보호 및 OIDC PKCE 흐름을 제공합니다. OIDC discovery와 JWKS 요청은 검증된 metadata와 공용 HTTPS 전송을 사용합니다. 미설정 생산 OIDC는 fail-closed 처리합니다.
공용 HTTPS 전송
server/public_https_transport.mjs, server/application_routes.mjs, tests/unit/public-https-transport.test.mjs
DNS 결과와 HTTPS 목적지를 검증합니다. 응답 크기를 제한하고 GET·HEAD 요청만 안전하게 재시도합니다.
Stripe 웹훅 검증 경계
server/stripe_webhook.mjs, server/application_routes_implementation.mjs, docs/doctoring/stripe-webhook-trust-boundary.md, CHANGELOG.md, tests/api/stripe-webhook.test.mjs, tests/unit/stripe-webhook-boundary.test.mjs
웹훅은 제한된 원시 본문을 HMAC-SHA-256으로 검증한 뒤 JSON을 파싱합니다. 유효한 요청은 확인 응답만 반환하며 플랜을 변경하지 않습니다.
회귀 검증과 CI checkout
.github/workflows/*.yml, package.json, tests/unit/coverage-script-contract.test.mjs, tests/unit/dependency-review-merge-base-contract.test.mjs, tests/unit/rate-limit-observability-failure.test.mjs, tests/unit/toast-accessibility.test.mjs, docs/deploy.md, index.html
CI가 PR head 저장소와 SHA를 확인합니다. dependency review는 현재 base branch와 검증된 merge base를 사용합니다. coverage 실행 대상과 실제 정적 파일 제공 검증을 갱신했습니다.

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

Merge Risk: 🟠 High · up to 70928

The PR strengthens proxy-derived rate limiting and account trust boundaries, but supported production OIDC logins can still fail because the token request body is incompatible with the outbound transport. Merge should wait for that compatibility fix; one related test also needs deterministic environment setup.

Sequence Diagram(s)

sequenceDiagram
  participant Stripe
  participant PublicApp as server/app.mjs
  participant Verifier as verifyStripeWebhookRequest
  Stripe->>PublicApp: 원시 웹훅 요청
  PublicApp->>Verifier: 본문과 stripe-signature 전달
  Verifier-->>PublicApp: 검증된 이벤트 또는 오류
  PublicApp-->>Stripe: received 응답 또는 HTTP 오류
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.68% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 77 functions across 30 files. (3 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 설정된 프록시에서만 전달 IP를 신뢰하도록 변경한 핵심 보안 수정 사항을 정확하고 간결하게 설명합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 24.68% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 77 functions across 30 files. (3 skipped: 3 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/trusted-rate-limit-client-ip

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.

Keep the public copy-and-replace composition and make the protected-graph
Stripe route fail closed on HMAC verification so a direct mount cannot
upgrade orgs.plan from unsigned JSON. Record the trust boundary in
CHANGELOG and doctoring.
Replace the source-text serve-path assertion with a runtime Hono route-graph regression that fails while the public facade registers /toast-state.css twice. Remove the redundant facade route so the protected route graph remains the single SaaS implementation.
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

Copy link
Copy Markdown
Contributor Author

@opencode-agent review

Please review exact current head 7430bb2b64e442f6b218d09c5bfa894ea3f2ceb9 against protected develop@2c328875e00e86537df3e965170be80532571cad. Do not reuse predecessor-head evidence. All currently enumerated inline threads are resolved and the latest exact-head Devin pass reported 0 new findings, but the required OpenCode job is fail-closed because no authenticated current-head APPROVED/CHANGES_REQUESTED verdict exists.

Verify from current source before issuing a SHA-bound verdict:

  • trusted transport-peer/X-Forwarded-For chain canonicalization, including scoped IPv6 and mapped IPv4;
  • bounded/shared limiter semantics plus 429 observability and metrics-folding failure isolation;
  • production-vs-development OIDC selection, validated discovery metadata endpoints, token/JWKS validation, bounded state, Unicode/case email identity migration and lookup;
  • exactly-once signup accounting across password signup, production OIDC and development mock SSO;
  • invite/share bearer-token redaction and identity binding;
  • dependency-review merge-base and immutable exact-head semantics; and
  • re-check whether any current calendar/event-stream or other long-lived/session-bearing route can accept a JWT after its token_version is revoked. An older CodeRabbit walkthrough named that risk only through predecessor f6bd5ea10491cd626557960b40a44234d4fd3c16; do not carry it forward unless the current 7430bb2 source or a realistic reproduction still demonstrates it.

If a current defect is found, identify the first failing boundary and the smallest realistic RED regression rather than relying on historical summary text.

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

@opencode-agent review

Review exact current head 70928aa0c80857410050fb5032b918d19fedbd23 only against protected develop@2c328875e00e86537df3e965170be80532571cad. This head contains the completed test-first runtime-boundary repair: deliberate RED d7575ce48f2a9c6b8b38501b222f6c2eef627598 proved the manifest incorrectly admitted Node 23.4 despite DatabaseSync.function() requiring 23.5 on the 23.x line; current package.json and lockfile now declare ^22.13.0 || >=23.5.0, and the new runtime contract is wired into unit and owned c8 coverage cases. Exact-current-head Server Tests, Fuzz, OSV Scanner, Security Scan, Dependency Review, and SAST Semgrep are terminal-success; coverage-evidence is terminal-success; every current inline review thread is resolved. The current required opencode-review run failed closed solely because no authenticated APPROVED or CHANGES_REQUESTED OpenCode verdict exists for 70928aa.... Strix is independently still in progress and is not being counted as passing. Please verify the current changed source/tests and anchor any formal verdict to 70928aa0c80857410050fb5032b918d19fedbd23; do not transfer predecessor-head verdicts.

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 0 new potential issues.

Devin Review

coderabbitai[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 0 new potential issues.

Devin Review

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

OpenCode reviewed the current-head product diff. Coverage is a separate gate.

Changed files

  • .github/workflows/dependency-review.yml — GitHub Actions review job
  • .github/workflows/server-tests.yml — GitHub Actions review job
  • CHANGELOG.md — repository behavior
  • docs/deploy.md — operator or user guidance
  • docs/doctoring/stripe-webhook-trust-boundary.md — operator or user guidance
  • docs/doctoring/trusted-proxy-client-ip.md — operator or user guidance
  • index.html — repository behavior
  • package-lock.json — repository behavior
  • package.json — repository behavior
  • server/app.mjs — TypeScript or JavaScript runtime
  • server/app_routes.mjs — TypeScript or JavaScript runtime
  • server/application_routes.mjs — TypeScript or JavaScript runtime
  • server/application_routes_core.mjs — TypeScript or JavaScript runtime
  • server/application_routes_implementation.mjs — TypeScript or JavaScript runtime
  • server/auth.mjs — TypeScript or JavaScript runtime
  • server/db.mjs — TypeScript or JavaScript runtime
  • server/public_https_transport.mjs — TypeScript or JavaScript runtime
  • server/rate_limit.mjs — TypeScript or JavaScript runtime
  • server/signup_metrics.mjs — TypeScript or JavaScript runtime
  • server/stripe_webhook.mjs — TypeScript or JavaScript runtime
  • tests/api/email-identity.test.mjs — regression suite
  • tests/api/email-unicode-identity.test.mjs — regression suite
  • tests/api/invite-security.test.mjs — regression suite
  • tests/api/oidc-core-production-failclosed.test.mjs — regression suite
  • tests/api/oidc-production-boundary.test.mjs — regression suite
  • tests/api/oidc-provider-metadata.test.mjs — regression suite
  • tests/api/rate-limit-prometheus.test.mjs — regression suite
  • tests/api/rate-limit-shared-boundary.test.mjs — regression suite
  • tests/api/ratelimit.test.mjs — regression suite
  • tests/api/security-guard-abuse-controls.test.mjs — regression suite
  • tests/api/stripe-webhook.test.mjs — regression suite
  • tests/unit/coverage-script-contract.test.mjs — regression suite
  • tests/unit/dependency-review-merge-base-contract.test.mjs — regression suite
  • tests/unit/node-runtime-contract.test.mjs — regression suite
  • tests/unit/public-https-transport.test.mjs — regression suite
  • tests/unit/rate-limit-observability-failure.test.mjs — regression suite
  • tests/unit/rate-limit-scoped-ipv6.test.mjs — regression suite
  • tests/unit/stripe-webhook-boundary.test.mjs — regression suite
  • tests/unit/toast-accessibility.test.mjs — regression suite

Changed behavior

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: dependency-review.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: dependency-review.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Workflow: server-tests.yml"]
  S2 --> I2["GitHub Actions review job"]
  I2 --> R2["Review risk: Workflow: server-tests.yml"]
  R2 --> V2["actionlint plus required checks"]
  Evidence --> S3["Repository file: CHANGELOG.md"]
  S3 --> I3["repository behavior"]
  I3 --> R3["Review risk: Repository file: CHANGELOG.md"]
  R3 --> V3["required checks"]
  Evidence --> S4["Docs: deploy.md (3 files)"]
  S4 --> I4["operator or user guidance"]
  I4 --> R4["Review risk: Docs: deploy.md (3 files)"]
  R4 --> V4["docs review"]
  Evidence --> S5["Repository file: index.html"]
  S5 --> I5["repository behavior"]
  I5 --> R5["Review risk: Repository file: index.html"]
  R5 --> V5["required checks"]
  Evidence --> S6["Repository file: package-lock.json"]
  S6 --> I6["repository behavior"]
  I6 --> R6["Review risk: Repository file: package-lock.json"]
  R6 --> V6["required checks"]
  Evidence --> S7["Repository file: package.json"]
  S7 --> I7["repository behavior"]
  I7 --> R7["Review risk: Repository file: package.json"]
  R7 --> V7["required checks"]
  Evidence --> S8["TypeScript/JavaScript: app.mjs (11 files)"]
  S8 --> I8["TypeScript or JavaScript runtime"]
  I8 --> R8["Review risk: TypeScript/JavaScript: app.mjs (11 files)"]
  R8 --> V8["package test plus coverage"]
  Evidence --> S9["Test: email-identity.test.mjs (11 files)"]
  S9 --> I9["regression suite"]
  I9 --> R9["Review risk: Test: email-identity.test.mjs (11 files)"]
  R9 --> V9["targeted test run"]
  Evidence --> S10["Test: coverage-script-contract.test.mjs (8 files)"]
  S10 --> I10["regression suite"]
  I10 --> R10["Review risk: Test: coverage-script-contract.test.mjs (8 files)"]
  R10 --> V10["targeted test run"]
Loading

Findings

No source-backed product finding is synthesized from the coverage gate. A coverage miss belongs in the status comment.

  • Head SHA: f36eb24a7ab47b880a1115a0d978a6011fa26048
  • Workflow run: 33239412993
  • Workflow attempt: 1
  • Coverage gate: failure

Review outcome

Coverage is a gate, not the review. This body reviews the changed product files.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: dependency-review.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: dependency-review.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Workflow: server-tests.yml"]
  S2 --> I2["GitHub Actions review job"]
  I2 --> R2["Review risk: Workflow: server-tests.yml"]
  R2 --> V2["actionlint plus required checks"]
  Evidence --> S3["Repository file: CHANGELOG.md"]
  S3 --> I3["repository behavior"]
  I3 --> R3["Review risk: Repository file: CHANGELOG.md"]
  R3 --> V3["required checks"]
  Evidence --> S4["Docs: deploy.md (3 files)"]
  S4 --> I4["operator or user guidance"]
  I4 --> R4["Review risk: Docs: deploy.md (3 files)"]
  R4 --> V4["docs review"]
  Evidence --> S5["Repository file: index.html"]
  S5 --> I5["repository behavior"]
  I5 --> R5["Review risk: Repository file: index.html"]
  R5 --> V5["required checks"]
  Evidence --> S6["Repository file: package-lock.json"]
  S6 --> I6["repository behavior"]
  I6 --> R6["Review risk: Repository file: package-lock.json"]
  R6 --> V6["required checks"]
  Evidence --> S7["Repository file: package.json"]
  S7 --> I7["repository behavior"]
  I7 --> R7["Review risk: Repository file: package.json"]
  R7 --> V7["required checks"]
  Evidence --> S8["TypeScript/JavaScript: app.mjs (11 files)"]
  S8 --> I8["TypeScript or JavaScript runtime"]
  I8 --> R8["Review risk: TypeScript/JavaScript: app.mjs (11 files)"]
  R8 --> V8["package test plus coverage"]
  Evidence --> S9["Test: email-identity.test.mjs (11 files)"]
  S9 --> I9["regression suite"]
  I9 --> R9["Review risk: Test: email-identity.test.mjs (11 files)"]
  R9 --> V9["targeted test run"]
  Evidence --> S10["Test: coverage-script-contract.test.mjs (8 files)"]
  S10 --> I10["regression suite"]
  I10 --> R10["Review risk: Test: coverage-script-contract.test.mjs (8 files)"]
  R10 --> V10["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

Coverage evidence did not pass, so approval is blocked. The formal pull-request review is the source-backed diff review, not this status comment.

@seonghobae seonghobae added bug Something isn't working priority: high High-priority or P1 work labels Sep 7, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: high High-priority or P1 work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant