fix(ops): fail closed on unmeasured CAPPO validation - #31
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe validation route now requires a successful CAPPO health probe before PGL anchoring. It returns ChangesValidation route
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant ValidateRoute
participant CAPPO
participant PGL
Client->>ValidateRoute: POST /api/ops/validate
ValidateRoute->>CAPPO: health probe
CAPPO-->>ValidateRoute: OK response
ValidateRoute->>PGL: evidence request with latency
PGL-->>ValidateRoute: evidence anchor hash
ValidateRoute-->>Client: success response with hash
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/app/api/ops/validate/route.test.tsOops! Something went wrong! :( ESLint: 10.8.1 TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///.eslintrc.json?mtime=1786195158862" needs an import attribute of "type: json" src/app/api/ops/validate/route.tsOops! Something went wrong! :( ESLint: 10.8.1 TypeError [ERR_IMPORT_ATTRIBUTE_MISSING]: Module "file:///.eslintrc.json?mtime=1786195158862" needs an import attribute of "type: json" 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. Comment |
reprewindai-dev
commented
Aug 8, 2026
@coderabbitai review Please review the current exact head with emphasis on source-of-truth behavior: CAPPO connection/non-2xx failures must not produce fabricated latency, failed CAPPO validation must prevent PGL anchoring, client errors must not leak raw upstream exception details, and successful responses must distinguish observed CAPPO timing from durable Gnomledger/PGL evidence. Keep runtime/deployment claims out of scope unless backed by measured evidence. |
🧩 Analysis chain🏁 Script executed: #!/bin/bashset -euo pipefail
echo'--- PR metadata and changed files ---'
gh pr view 31 --repo reprewindai-dev/cAPI --json headRefOid,baseRefOid,files,title,url
echoecho'--- Diff against PR base ---'
gh pr diff 31 --repo reprewindai-dev/cAPI --color=never
echoecho'--- Candidate files ---'
fd -t f 'route(\.test)?\.(ts|tsx|js|jsx)$|validate'.| sed -n '1,160p'echoecho'--- Route/test outlines ---'forfin$(fd -t f .| rg '(^|/)(route|route\.test)\.(ts|tsx|js|jsx)$'| rg 'ops|validate');doecho"### $f"
ast-grep outline "$f" --items all ||truedoneLength of output: 10199 🏁 Script executed: #!/bin/bashset -euo pipefail
echo'--- Route implementation ---'
cat -n src/app/api/ops/validate/route.ts
echoecho'--- Focused test ---'
cat -n src/app/api/ops/validate/route.test.ts
echoecho'--- Endpoint consumers and response-field conventions ---'
rg -n -C 4 --glob '!src/app/api/ops/validate/route.ts' --glob '!src/app/api/ops/validate/route.test.ts' \
'(api/ops/validate|anchorHash|evidence_hash|latency_ms|cappo_status|pgl_status)' src README.md package.json 2>/dev/null ||trueechoecho'--- Project test/type/build scripts and TypeScript settings ---'if [ -f package.json ];then
node -e "const p=require('./package.json'); console.log(JSON.stringify({scripts:p.scripts,devDependencies:p.devDependencies,dependencies:p.dependencies},null,2))"fi
fd -t f '^(tsconfig.*\.json|vitest.*\.(ts|js|mts|mjs)|next\.config\..*)$'. -x sh -c 'echo "### $1"; cat -n "$1"' sh {}Length of output: 25675 🏁 Script executed: #!/bin/bashset -euo pipefail
repo='reprewindai-dev/cAPI'
head='b57012fd6069de77fa4af183ccf0ef6229a2ccf7'echo'--- PR head verification ---'
gh pr view 31 --repo "$repo" --json headRefOid,isDraft,mergeStateStatus,url
echoecho'--- Checks for exact head ---'
gh pr checks 31 --repo "$repo" --json name,state,workflow,link,bucket ||trueechoecho'--- Commit check-runs and statuses for exact head ---'
gh api "repos/$repo/commits/$head/check-runs?per_page=100" \
--jq '.check_runs[] | {name, status, conclusion, details_url, app: .app.slug}'
gh api "repos/$repo/commits/$head/status" \
--jq '{state, statuses: [.statuses[] | {context, state, target_url}]}'Length of output: 2472
No source-level findings.
The required merge gates are not complete on this exact head. The GitHub Actions ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/app/api/ops/validate/route.ts`:
- Around line 53-64: Wrap the PGL fetch and pglRes.json() operations in the
route handler’s local try/catch so transport, timeout, DNS, and
response-decoding failures return the existing controlled 502 response instead
of reaching the outer 500 handler. Preserve the current non-OK status handling
and add regression coverage for rejected PGL requests and invalid PGL JSON.
🪄 Autofix
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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1f62ffb7-0457-4bfd-b0d9-29d4bba1eb7d
📒 Files selected for processing (2)
src/app/api/ops/validate/route.test.tssrc/app/api/ops/validate/route.ts
| signal: AbortSignal.timeout(3000), | ||
| }); | ||
| if (!pglRes.ok) { | ||
| logs.push(`[PGL] Error: returned status ${pglRes.status}. Aborting — no fallback hash.`); | ||
| return NextResponse.json( | ||
| { error: 'PGL commitment failed', pgl_status: pglRes.status, logs }, | ||
| { status: 502 } | ||
| { status: 502 }, | ||
| ); | ||
| } | ||
| const pglData = await pglRes.json(); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Return 502 for PGL transport and response-decoding failures.
If the PGL fetch call rejects, such as on timeout or DNS failure, the outer handler returns 500. If pglRes.json() rejects, the outer handler also returns 500. Both cases are PGL anchoring failures.
Wrap the PGL request and JSON decoding in a local try/catch. Return the existing controlled 502 response from that handler. Add regression tests for a rejected PGL request and invalid PGL JSON.
🤖 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 `@src/app/api/ops/validate/route.ts` around lines 53 - 64, Wrap the PGL fetch
and pglRes.json() operations in the route handler’s local try/catch so
transport, timeout, DNS, and response-decoding failures return the existing
controlled 502 response instead of reaching the outer 500 handler. Preserve the
current non-OK status handling and add regression coverage for rejected PGL
requests and invalid PGL JSON.
Source-of-truth correction
Current
mainremoved synthetic PGL fallback hashes, but/api/ops/validatestill swallows a failed CAPPO health fetch and then reports the elapsed wall-clock time aslatency to cappo-backend. That can manufacture a plausible measurement even when no CAPPO HTTP response was observed.Change
Truth boundary
This establishes source behavior only. It does not verify CAPPO
8002, cAPI3003, Gnomledger8001, container listeners, deployed SHA, or Traefik routing.Required merge gates
npm test -- src/app/api/ops/validate/route.test.tsnpm testKeep draft until those checks execute successfully.
Summary by CodeRabbit
Bug Fixes
Tests