feat(#2247): re-land HCQL on 5 authenticated services (CAP 10.1.0) - #2257
Merged
Merged
Conversation
Phase A CAP ecosystem to latest-compatible-with-cds-10.1 (required), Phase B broader tree within-major only (majors deferred). Full suite + build gate each phase. Records maintainer decisions.
Major bump to 3.0.0 deferred to a separate PR per maintainer policy. 2.1.0 is the highest 2.x with peer @sap/cds >=8, compatible with 10.1.
Add { kind: 'hcql', path: '/hcql/admin' } to AdminService's @protocol
list in srv/admin-service-mcp.cds. HCQL mounts on its own path so OData
at /admin is never asked to parse CQN bodies (guards the #1004 regression).
Add test/unit/hcql-enablement.test.js: 5 tests confirm HCQL mounts, OData
path is clean, malformed CQN returns 400, and unauthenticated calls get 401.
Adds srv/hcql-enablement.cds with object-form @protocol lists that mount HCQL on /hcql/author, /hcql/analytics, /hcql/exports, /hcql/consolidation while preserving each service's existing OData @path verbatim. Also cleans the dead no-op assertion from the AdminService test block and extends the test suite with 12 new cases (3 per service × 4 services): mount presence, OData-path rejection, and unauthenticated rejection. All 17 hcql-enablement tests pass; cds build --production succeeds. consolidation mocked user was already present in .cdsrc.json.
Final-review finding: approuter v16 enables CSRF for non-GET by default, so the documented Bearer-token curl POSTs to /hcql/* would 403. Match the sibling programmatic-POST routes (/mcp/*, /a2a) which set csrfProtection:false. Auth is unaffected — XSUAA scope is still enforced per route. Also corrects hcql-support.md: there is no .deploy/xs-app.json (MTA builds from ../approuter).
# Conflicts: # package-lock.json # package.json
cds build --production stamps the cds-dk version into the csn snapshot; the CAP 10.1.0 runtime bump advances it from v10.0.3. Schema entities unchanged (HCQL enablement is annotation-only @protocol lists). Clears the CDS build staging check. Co-authored-by: Ordinary Tom <thomas.jung@sap.com>
srv-qa is a separate deployable CAP module; the CF buildpack installs it from srv-qa/package-lock.json. The root CAP 10.1.0 bump left srv-qa on cds ^10.0.3 / @cap-js/hana ^3.0.1, tripping check-srv-qa-dep-parity. Regenerated srv-qa/package-lock.json (now resolves cds 10.1.0). Co-authored-by: Ordinary Tom <thomas.jung@sap.com>
The check-csrf-clients static guard (post-#895) bans csrfProtection on any route except the allowlisted /mcp/* and /a2a JSON-RPC sources. The 5 /hcql/* routes set csrfProtection:false, tripping the guard. Per maintainer decision, remove the flag (approuter CSRF-on default) rather than allowlist HCQL — the secure default, and matches the security-bot MEDIUM finding. Consequence: clients must do the x-csrf-token: fetch two-step before each HCQL POST. Documented the handshake in hcql-support.md (curl intro + token fetch step + AdminService example + smoke-matrix note). Flipping back to the M2M csrfProtection:false pattern would require adding /hcql/* to CSRF_EXEMPT_SOURCES plus issue-tracker sign-off. Co-authored-by: Ordinary Tom <thomas.jung@sap.com>
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.
Summary
Re-lands the CAP 10 HCQL ("CQL over HTTP") beta protocol adapter — reverted in #1004 — scoped to the 5 authenticated services (
AdminService,AuthorService,AnalyticsService,ExportsService,ConsolidationService), on a CAP runtime bump to 10.1.0 plus a package.json-wide within-major dependency refresh.Closes the re-land tracked in #2247 (Option 1). Draft — do not merge until the maintainer runs the hybrid suite on a bound environment (see Validation).
What changed
@sap/cds10.0.3 → 10.1.0,@sap/cds-dk→ 10.1.1, and ~25 CAP/non-CAP deps advanced within their current major (maintainer decision: no cross-major jumps in this PR).package-lock.jsonregenerated. Notable conscious pins held:@cap-js/mcp1.3.0,@cap-js/ai~1.1.0,cds-caching2.1.0,sharp0.35.3 (rationale in the SDD ledger).@protocollists — each service mounts HCQL on a distinct/hcql/<svc>path, never co-mounted on the OData@path. This is the fix for the revert(#995): remove HCQL enablement — 218 unit tests failing on main #1004 root cause (HCQL greedily parsed OData bodies/URLs as CQN).srv/hcql-enablement.cds(4 services) +srv/admin-service-mcp.cds(AdminService's existing list extended in place). Every ODatapathverbatim-matches the service's current@path./hcql/*routes inapprouter/xs-app.json,authenticationType: xsuaa, scopes matching each service's@requires, JWT-forwarded totutorials-srv, placed before the catch-all. Nostatusprop (would crash approuter v16).test/unit/hcql-enablement.test.js: OData path unchanged, HCQL path works, malformed CQN → 400 + server survives, auth enforced before CQN parse.docs/developers/reference/hcql-support.mdrewritten (distinct paths, authenticated-only,cds >= 10.1.0, DoS-fixed-in-10.1.0); CLAUDE.md gotcha + VitePress sidebar; design specdocs/superpowers/specs/2026-09-11-2247-hcql-reland-design.md.Why it's safe (the #1004 regression)
#1004 broke 218 tests because plain
@hcqlco-mounted on each OData@pathand parsed OData traffic as CQN. Here HCQL rides its own/hcql/<svc>path via object-form@protocollists; the OData path rejects CQN bodies (405). The malformed-CQN process-exit DoS present in 10.0.3 is fixed in 10.1.0 (→ 400, server stays up). Auth is enforced before CQN parse. HCQL is documented read-only (writes are explicitly unsupported in the beta).CSRF on
/hcql/*routes — resolved to CSRF-onThe
check-csrf-clientsstatic guard (post-#895) banscsrfProtectionon any route except the allowlisted/mcp/*and/a2aJSON-RPC sources. The 5/hcql/*routes originally setcsrfProtection: false(matching the MCP M2M pattern); a background security scan flagged that MEDIUM (CSRF), and the guard failed CI.Decision (maintainer, this PR): flip
/hcql/*to the approuter CSRF-on default — the secure choice, no allowlist change, matches the security-bot finding. ThecsrfProtection: falseflag was removed from all 5 routes.Consequence for callers: HCQL POSTs now require the approuter
x-csrf-token: fetchtwo-step handshake — documented inhcql-support.md(curl intro, token-fetch step, AdminService example, smoke-matrix note). Reverting to the M2McsrfProtection: falsepattern later would require adding/hcql/*toCSRF_EXEMPT_SOURCESinscripts/check-csrf-clients.tsand issue-tracker sign-off — both intentionally gated.Validation
channel-atlasgraphology/sigma). No OData/CQN/HCQL/CAP-10 regression.cds build --productionclean.@cap-js/mcp1.3.0 + the transitive@hono/node-server1.x→2.x major (via@modelcontextprotocol/sdk). The MCP boot path is exercised, no crash.bind:setup-provisioned, socds bind --exechas no HANA/XSUAA/credstore bindings (139 binding-guard file-fails are environmental). Maintainer: please runnpm run test:hybridon a bound environment before merging, plus the post-deploy HCQL smoke matrix inhcql-support.md(5 response codes).Kill switch
Delete
srv/hcql-enablement.cds+ drop thehcqlentry fromAdminService's@protocollist insrv/admin-service-mcp.cds, thencds build --production+ redeploy. ~15 min.