Skip to content

fix: report list routes return all rows up to a uniform cap - #465

Merged
dmealing merged 4 commits into
mainfrom
fm/mo-reporting-next
Oct 26, 2026
Merged

dmealing merged 4 commits into
mainfrom
fm/mo-reporting-next

Conversation

@dmealing

@dmealing dmealing commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

What Changed

  • Report list routes in all five ports return every row when limit is omitted, up to a uniform cap of 10,000 (reportMaxRows generator option). Java, Kotlin and Python previously stopped at 50 rows with no error; TypeScript and C# had no cap. Rows above the cap, or an explicit limit above it, now answer 400 { "error": "report_too_large", "maxRows": N }, before any body is written.
  • A report page bound that is not usable (limit below 1, negative offset, non-integer) answers 400 pagination.invalid_value in every port. C# previously ignored limit<=0 on reports.
  • Shared runtime (runtime-ts parseReportPage/ReportTooLargeError, REPORT_MAX_ROWS) and the per-port route generators (TypeScript routesFile/routesFileHono, C# RoutesGenerator, Java SpringControllerGenerator, Kotlin KotlinSpringControllerGenerator, Python router_generator) implement the cap. Entity and projection lists keep their paging.
  • Adds api-contract report/ scenarios cap-all-rows, cap-refused and bad-page-bound with a ReadingLog report fixture; updates CHANGELOG.md [Unreleased] and the reporting and api-contract docs.
Validation

Risk Assessment

✅ Low: The report-cap code matches what the first run validated, all five ports apply the same cap and the same refusals, the three ejected TypeScript copies match the reference byte for byte, and the CHANGELOG conflict resolution keeps both sides with no conflict markers left.

Testing

Narrow validation only. Baseline ts-fast/ts-unit gate passed. runtime-ts report-cap mount test (44 cases, in-process Fastify inject against real libsql) and typecheck pass. No scenario driven against a standing server, so none marked live. Scenarios 1-4 are untested live; scenario 5 is a gate run, not a live product scenario. Full repository regression suite not rerun this turn.

  • Live validation: ⚠️ inconclusive - 0 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Report list with no limit returns every row up to the cap (60 rows past the old 50) ⏸️ untested no Prior payload recorded only in-process Fastify inject tests (mount-read-only.test.ts 'report row cap'), not a live running server. Live result not established.
Report list at exactly the cap is answered; one row more is refused with 400 report_too_large and maxRows ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Report limit above the cap is refused; limit within it pages ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Report limit=0, negative, or malformed returns 400 pagination.invalid_value with expected 'an integer from 1 to N' ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Configured ts-fast and ts-unit gate passes on HEAD ⏸️ untested no Gate run is not a live product scenario. Baseline gate passed per prior run, but it is not counted as a live result.
  • Outcome: ⚠️ 1 warning across 1 run (18m24s)

Pipeline

Updates from git push no-mistakes

✅ **Intent** - passed

✅ No issues found.

🔧 **Rebase** - 1 issue found → auto-fixed ✅
  • ⚠️ CHANGELOG.md - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

✅ **Review** - passed

✅ No issues found.

⚠️ **Test** - 1 warning
  • ⚠️ live validation verdict: inconclusive (0 of 5 scenarios were driven live against the product); untested: Report list with no limit returns every row up to the cap (60 rows past the old 50), Report list at exactly the cap is answered; one row more is refused with 400 report_too_large and maxRows, Report limit above the cap is refused; limit within it pages, Report limit=0, negative, or malformed returns 400 pagination.invalid_value with expected 'an integer from 1 to N', Configured ts-fast and ts-unit gate passes on HEAD
  • Live validation: ⚠️ inconclusive - 0 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Report list with no limit returns every row up to the cap (60 rows past the old 50) ⏸️ untested no Prior payload recorded only in-process Fastify inject tests (mount-read-only.test.ts 'report row cap'), not a live running server. Live result not established.
Report list at exactly the cap is answered; one row more is refused with 400 report_too_large and maxRows ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Report limit above the cap is refused; limit within it pages ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Report limit=0, negative, or malformed returns 400 pagination.invalid_value with expected 'an integer from 1 to N' ⏸️ untested no Prior payload recorded only in-process inject, not a standing server. Live result not established.
Configured ts-fast and ts-unit gate passes on HEAD ⏸️ untested no Gate run is not a live product scenario. Baseline gate passed per prior run, but it is not counted as a live result.
  • scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains
  • scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains (baseline, passed)
  • cd server/typescript/packages/runtime-ts && bun test test/drizzle-fastify/mount-read-only.test.ts (44 pass, 0 fail)
  • cd server/typescript/packages/runtime-ts && bun run typecheck (clean)
  • grep for conflict markers in CHANGELOG.md (none)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

…p, refuse bad bounds

Report list routes in all five ports now return every row up to a
generator-configurable cap (default 10000) instead of a silent 50-row page.
Above the cap, or with an explicit limit above it, the route answers
400 report_too_large with maxRows. limit<=0, negative offset and
non-integer bounds are refused with the existing 400 envelope (C# used to
ignore them). Pinned by new api-contract report scenarios.
…ANGELOG, api-contract.md and reporting.md already updated by the change and match code (cap 10,000, reportMaxRows option names, report_too_large and pagination.invalid_value envelopes, 30-scenario count). Fixed one formatting nit: missing blank line between Fixed entries in CHANGELOG [Unreleased]. docs/superpowers/plans/2026-10-04-fr-044-plan-3 still describes the old 50-row default, but it is a dated plan record, so left as is.
@dmealing
dmealing force-pushed the fm/mo-reporting-next branch from f5a2c7b to f0eb56d Compare October 26, 2026 06:34
@dmealing
dmealing merged commit c67a3de into main Oct 26, 2026
1 check passed
@dmealing
dmealing deleted the fm/mo-reporting-next branch October 26, 2026 06:36
dmealing added a commit that referenced this pull request Oct 26, 2026
All four registries publish 1.1.3 / 8.1.3: report list routes change served output in every
port (#465) and the C# generators change (#461). Maven stays one major ahead (npm major + 7).
Regenerates the site payload.
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