Skip to content

fix: reject unsafe integers in proposal and reservation parsers - #11

Merged
EauDoon merged 1 commit into
mainfrom
devloop/cycle-05-safe-integer-bounds
Aug 30, 2026
Merged

fix: reject unsafe integers in proposal and reservation parsers#11
EauDoon merged 1 commit into
mainfrom
devloop/cycle-05-safe-integer-bounds

Conversation

@EauDoon

@EauDoon EauDoon commented Aug 30, 2026

Copy link
Copy Markdown
Owner

What

Proposal and reservation parsers now reject non-integral, non-finite, and unsafe integer values for duration and money fields. Evidence max_age_seconds and remedy_window_seconds must also convert exactly to milliseconds (value * 1000 remains a safe integer). Settlement-bundle validation uses the same duration bound.

Why

Number.isInteger admits Number.MAX_VALUE and 2 ** 53. Those values overflow when converted to milliseconds, so an evidence freshness window could become Infinity and never expire. Amount fields already used Number.isSafeInteger; duration and attempt fields did not.

How tested

  • node ./scripts/check.js
  • node --test
  • Added admission tests that unsafe max_age_seconds, max_attempts, remedy_window_seconds, and amount fields fail closed without consuming action capacity or calling the connector.
  • Added an HTTP propose case for max_age_seconds: 1e20 (422, no stored action).
  • Extended bundle schema-invalid mutations for overflow-scale duration fields.

Devin Review

Duration fields were admitted with Number.isInteger, so values such as
MAX_VALUE and 2^53 passed and overflowed millisecond conversion. Require
safe integers whose millisecond product stays exact, and fail closed
before action capacity or connector reservation is consumed.
@EauDoon
EauDoon merged commit 68dced5 into main Aug 30, 2026
6 of 7 checks passed
@EauDoon
EauDoon deleted the devloop/cycle-05-safe-integer-bounds branch August 30, 2026 00:10

@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 1 potential issue.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment thread src/rail.js
Comment on lines +1265 to +1272
assertSafeInteger(
input.evidence_plan.max_age_seconds,
"ActionProposal.evidence_plan.max_age_seconds",
{
min: 1,
max: MAX_DURATION_SECONDS,
message: "A positive evidence max age is required.",
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Published schemas accept rejected values

Oversized durations and attempt counts pass the published schemas, but assertSafeInteger rejects them. Schema-valid clients therefore receive unexpected validation errors.

Prompt for agents
Align every public contract with the new runtime numeric bounds. Add the duration maximum of 9007199254740 to max_age_seconds and remedy_window_seconds, and Number.MAX_SAFE_INTEGER-equivalent maxima to max_attempts and relevant money fields in spec/schemas/action-proposal.schema.json, spec/schemas/recourse-reservation.schema.json, spec/schemas/connector-recourse-commitment.schema.json, and api/openapi.json. Add repository checks or contract tests that prove the published schemas reject the same boundary values as ConsequenceRail and bundle validation.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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