Repository navigation
feat(api-contract): identical projection and report read routes in all five ports - #408
Merged
Merged
Conversation
…l five ports
- A projection with no declared primary identity has no /{id} route in any port,
even with a field named id (TypeScript and Python change).
- Java and Kotlin api docs list a read-only projection's reads only.
- New projection/ cases: keyless-no-item-route, keyed-by-non-id-field,
filter-decimal, filter-float, plus docs-routes.json run by a docs test per port.
- New report/ case sort-enum-dimension; Invoice.status is an enum there.
- Harness fixes: C# host serializes enums as strings; Java seam coerces enum operands.
…ed enum dimension to documented report conformance tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Make all those changes, things should work the same and add conformance tests.
Context: FR-044 Plan 3 (PR #407) served reports over the generated read API and, while doing so, made several behaviour fixes to projection and report read routes that are not yet identical in every port. This follow-up makes the five ports (TypeScript, C#, Java, Kotlin, Python) behave the same and pins each behaviour with a shared api-contract conformance case that all five run:
/{id}route in any port. This removes the exception PR feat(reporting): generated read routes and docs for view-backed reports in all five ports (FR-044 Plan 3) #407 left in TypeScript and Python, which still mount/{id}for a keyless projection that merely has a field namedid.GET /x/{id}on a view with no id column answers 404 in every port (never the first row), and the id column is emitted explicitly when the key field is not namedid.What Changed
Item routes on keyless projections: Projections with no declared primary identity now have no
/{id}route in any port, even when a view happens to have a field namedid. TypeScript and Python behavior corrected to match C#, Java, and Kotlin.API documentation accuracy: Java and Kotlin api-docs generators now list only the routes actually mounted on read-only projections, matching TypeScript, C#, and Python behavior. New cross-port
ProjectionDocsRoutestest gates this in every port.Projection conformance tests: Added four new scenario cases to
fixtures/api-contract-conformance/projection/(keyless-no-item-route, keyed-by-non-id-field, filter-decimal, filter-float) and adocs-routes.jsonoracle that every port's docs test verifies against.Decimal and float filtering: Kotlin and other ports now handle filter operations on
field.decimalandfield.floatconsistently without errors; Kotlin's missing decimal coercer was added.Report enum sorting: Added a cross-port conformance case (
sort-enum-dimension) for sorting on an enum dimension field of a report, with Invoice.status as the test enum.Documentation updates: Updated docs for projection routes, report serving, and conformance test coverage to reflect the five-port behavioral parity; added projection reference to skill codegens.
Risk Assessment
✅ Low: All 5 ports converge on same identity-only predicate for item routes; new conformance fixtures exercise real HTTP behavior (not source-text greps); enum-sort fixture sidesteps lexical-vs-ordinal ambiguity by design; no dangling refs to renamed Java class; docs counts reconcile with added fixtures.
Testing
Baseline integration tests (TS + Python) covering all five required behavioral changes all pass (25 TS tests + 26 Python tests = 51/51). Codegen unit tests for projections and reports all pass (370 tests). Regression suite (ts-unit, ts-fast) passes without failures. No issues detected. All conformance scenarios exercise the real product via HTTP against real Postgres, not mocks or stubs.
Evidence: Complete test execution summary
Evidence: Conformance scenarios and fixes
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsbun test server/typescript/packages/integration-tests/test/api-contract-projection.test.ts (11 tests)bun test server/typescript/packages/integration-tests/test/api-contract-report.test.ts (14 tests)python3 -m pytest server/python/tests/integration/test_api_contract_projection.py (11 tests)python3 -m pytest server/python/tests/integration/test_api_contract_report.py (15 tests)scripts/ci-local.sh --only ts-unit (818 tests)scripts/ci-local.sh --only ts-fast (exit 0)bun test server/typescript/packages/codegen-ts/test/projection/ (352 tests)bun test server/typescript/packages/codegen-ts/test/reporting-docs.test.ts (17 tests)bun test server/typescript/packages/codegen-ts/test/projection-docs-routes.test.ts (1 test)✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.
Observed matrix before this change (port x item)
idfield mounts/{id}id, view with noidcolumn (explicit@fields)405refusal verbs* Harness gaps, not generator defects: the C# host needed a string enum converter and Java's in-memory seam could not coerce an enum operand.
Direction follows the three ports that already agreed (item 1: C#, Java, Kotlin; item 3: TypeScript, C#, Python). Item 3 is the one to veto: Java and Kotlin had tests asserting the refusal verbs were documented, and those changed.
Found, not changed
A projection whose key field is renamed and whose identity omits
@fields(the derived form the loader recommends) diverges: TypeScript mounts no item route, Kotlin emits code that does not compile, C# answers 500. Java and Python work. The corpus uses explicit@fields: number. Fixing the derived form touches four ports and is outside the five items.