Skip to content

fix(approvals): validate request_credential payload at creation#44

Merged
antoinekm merged 2 commits into
masterfrom
fix/credential-request-validation
Jun 30, 2026
Merged

fix(approvals): validate request_credential payload at creation#44
antoinekm merged 2 commits into
masterfrom
fix/credential-request-validation

Conversation

@antoinekm

@antoinekm antoinekm commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Problem

The base createApprovalSchema only checks that payload is an object (z.record(z.string(), z.unknown())), so per-type validation never runs at creation. An agent can therefore persist a malformed request_credential (e.g. key instead of envKey, free-form note/purpose instead of reason, no howToObtain/browserAgentPrompt).

Such a request:

  • renders degraded in the board UI (Env var shows , placeholder is $ENV, no how-to section), since the credential renderer reads the exact envKey/reason/howToObtain fields;
  • cannot be completed: provide-credential re-parses the payload with requestCredentialSchema and would throw on the missing envKey.

So the documented capability-request schema was only a suggestion, not enforced.

Fix

Validate the payload against requestCredentialSchema at creation time in POST /companies/:id/approvals. A malformed request_credential is now rejected up front with a 400 Validation error (with details) that the requesting agent can read and self-correct. The check is scoped to request_credential only, so other approval types keep their free-form payloads.

Tests

  • malformed request_credential payload -> 400, create not called;
  • well-formed payload -> 201.

Approvals route suite green (13/13), server typecheck clean.

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation for approval creation so malformed credential-request payloads are rejected earlier with a clear validation error.
    • Valid approval requests continue to be accepted and processed successfully.
    • Added coverage to confirm invalid payloads are blocked and valid requests are created as expected.

The base createApprovalSchema only checks that payload is an object, so an
agent could persist a malformed request_credential (e.g. `key` instead of
`envKey`, no reason or howToObtain). Such a request renders degraded in the
board UI and cannot be completed, because provide-credential re-parses the
payload and would throw.

Validate the payload against requestCredentialSchema at creation time so a
malformed request is rejected up front with a clear validation error the
requesting agent can read and self-correct.
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 53 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3b917376-d24a-4404-8ca3-a43f37700bf1

📥 Commits

Reviewing files that changed from the base of the PR and between dbf60aa and cec825c.

📒 Files selected for processing (2)
  • server/src/__tests__/approval-routes-idempotency.test.ts
  • server/src/routes/approvals.ts
📝 Walkthrough

Walkthrough

The approval creation route gains a per-type validation step that parses the payload with requestCredentialSchema when type === "request_credential", rejecting malformed payloads before persistence. Two tests are added: one verifying HTTP 400 on a malformed payload (with no service call), and one verifying success on a valid payload.

Changes

request_credential Payload Validation

Layer / File(s) Summary
Route validation and tests
server/src/routes/approvals.ts, server/src/__tests__/approval-routes-idempotency.test.ts
Route parses payload with requestCredentialSchema for request_credential approvals and returns 400 on failure; tests cover both the rejection and acceptance paths.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐇 A credential request came knocking one day,
With fields all askew in a terrible way.
The schema said "No!" and returned a 400,
While valid ones sailed through without hesitation.
The rabbit approves — validation hooray! 🎉

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main change: adding validation for request_credential payloads during approval creation.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/credential-request-validation

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.

@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

🤖 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 `@server/src/__tests__/approval-routes-idempotency.test.ts`:
- Around line 434-435: The test assertion in approval-routes-idempotency should
be tightened to match the create contract: update the status check in the
approval route test so it expects only 201 instead of allowing 200 or 201. Use
the existing res.status assertion near mockApprovalService.create to verify the
successful creation response remains fixed at 201 and cannot regress to 200.

In `@server/src/routes/approvals.ts`:
- Around line 157-165: The `request_credential` payload is validated on create
but not on resubmit, so malformed data can still slip through `POST
/approvals/:id/resubmit`. Update the resubmit handler in `approvals` to re-parse
`approvalInput.payload` with `requestCredentialSchema` whenever `existing.type
=== "request_credential"`, mirroring the create-path check so both
`createApprovalSchema` and `resubmit` enforce the same contract.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8685f1a4-24a2-479a-8ddb-d30b22d93137

📥 Commits

Reviewing files that changed from the base of the PR and between b9860c8 and dbf60aa.

📒 Files selected for processing (2)
  • server/src/__tests__/approval-routes-idempotency.test.ts
  • server/src/routes/approvals.ts

Comment thread server/src/__tests__/approval-routes-idempotency.test.ts Outdated
Comment thread server/src/routes/approvals.ts
Address review: the resubmit path replaces the payload but never re-parsed it,
so a malformed request_credential could still be persisted through resubmit.
Validate it there too, and assert the creation test on 201 (the route's actual
success status) instead of 200 | 201.
@antoinekm antoinekm merged commit 70b92d7 into master Jun 30, 2026
16 checks passed
@antoinekm antoinekm deleted the fix/credential-request-validation branch June 30, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant