Skip to content

fix(server): reject unsupported monitor-scheduling fields on PATCH /issues/:id (RBR-1101) - #26

Merged
PraeSynBH merged 1 commit into
masterfrom
fix/rbr-1101-monitor-patch-fork-retarget
Aug 9, 2026
Merged

fix(server): reject unsupported monitor-scheduling fields on PATCH /issues/:id (RBR-1101)#26
PraeSynBH merged 1 commit into
masterfrom
fix/rbr-1101-monitor-patch-fork-retarget

Conversation

@PraeSynBH

Copy link
Copy Markdown
Owner

Summary

RBR-1094 diagnosed (3x independent repro) that PATCH /issues/:id silently accepts and drops
monitorNextCheckAt / monitorNotes / monitorScheduledBy (flat) and executionState.monitor.*
(nested) — HTTP 200, no error, zero persistence. updateIssueSchema has no shape entries for these
fields and is never .strict()'d, so Zod's default non-strict .parse() silently strips unknown
keys before the route handler ever sees them.

Per CEO-approved product decision on RBR-1094: ship the narrow, low-blast-radius fix now rather than
flipping updateIssueSchema to global .strict() (untested blast radius across every other PATCH
caller company-wide; needs a separate audit).

Fix

Adds rejectUnsupportedIssuePatchMonitorSchedulingFields(), a z.preprocess() wrapper applied to
the route-level PATCH schema (updateIssueRouteSchema in server/src/routes/issues.ts) that
inspects the raw request body before Zod strips anything, and raises a 4xx naming the unsupported
field(s) instead of the silent 200 no-op. Matches the RBR-807/RBR-826 unsupported-field-rejection
pattern already used elsewhere in this codebase.

Tests

5 new cases in server/src/__tests__/issue-recovery-actions.test.ts — one per unsupported field
asserting a 4xx naming it, plus one proving a legitimate PATCH without these fields is unaffected.

Full suite run (this branch, fork/master base): issue-recovery-actions.test.ts 27/27 passing.
packages/shared vitest project: 170/170 passing.

Notes

Retargeted onto fork/master per the RBR-974/RBR-1081 repo-governance policy — paperclipai/paperclip
is upstream (no push access); PraeSynBH/paperclip is the repo we actually control and deploy from.
This branch was rebased off fork/master (not origin/master) to keep it mergeable/deployable.

Closes RBR-1101. AC-d follow-up (comment back on parent RBR-1094 + confirm on RBR-954) to be done
after this merges.

…ssues/:id (RBR-1101)

RBR-1094 diagnosed (3x independent repro) that PATCH /issues/:id silently
accepts and drops monitorNextCheckAt / monitorNotes / monitorScheduledBy
(flat) and executionState.monitor.* (nested) -- HTTP 200, no error, zero
persistence. updateIssueSchema (packages/shared/src/validators/issue.ts)
has no shape entries for these fields and is never .strict()'d, so Zod's
default non-strict .parse() silently strips unknown keys before the route
handler ever sees them.

Per CEO-approved product decision on RBR-1094: ship the narrow,
low-blast-radius fix now rather than flipping updateIssueSchema to global
.strict() (which would newly reject other currently-tolerated extra keys
across every PATCH caller company-wide and needs a separate audit).

Fix: add rejectUnsupportedIssuePatchMonitorSchedulingFields(), a
z.preprocess() wrapper applied to the route-level PATCH schema
(updateIssueRouteSchema in server/src/routes/issues.ts) that inspects the
raw request body before Zod strips anything, and raises a 4xx naming the
unsupported field(s) -- monitorNextCheckAt, monitorNotes,
monitorScheduledBy, or executionState.monitor -- instead of the silent
200 no-op. Matches the RBR-807/RBR-826 unsupported-field-rejection
pattern already used elsewhere in this codebase.

Tests (server/src/__tests__/issue-recovery-actions.test.ts): 5 new cases
-- one per unsupported field asserting a 4xx naming it, plus one proving
a legitimate PATCH without these fields is unaffected. Full
issue-recovery-actions.test.ts suite: 49/49 passing.

AC-a/AC-b/AC-c of RBR-1101 satisfied. AC-d (comment back on parent +
RBR-954 confirmation) to follow once this lands.
@PraeSynBH
PraeSynBH merged commit e01fcce into master Aug 9, 2026
9 of 16 checks passed
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.

2 participants