Repository navigation
Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference - #2917
Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference#2917nkaputnik wants to merge 30 commits into
Conversation
Port the extensibility customization guide from the Orders/bookshop sample to XTravels: model-only extension (x_priority + x_CostCenter), multi-repo workspace setup, local multitenancy, and tenant subscription. Regenerate all four screenshots against a running XTravels tenant: - base Travels list - extension project readme - Fiori preview with Priority and Cost Center columns - deployed tenant UI with Priority and Cost Center columns Remove the superseded Orders screenshots.
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
- Add Preferred Project Layout, Ship a Pre-Filled Base Model, and Make It Browsable subsections so a cloned template runs with npm install + cds watch. - Add Seed External & Federated Data (@capire/common, S4 customers, flights): explain the minified base model, trim sap.common-Currencies.csv to code;symbol;name;descr, and don't seed Languages/Regions (no target table). - Split reference wiring into its own section (Provide Reference Logic for Local Runs); renumber Extension Guides/Deploy accordingly. - Purge comments from JSON code blocks; use VitePress line-highlight instead. - Regenerate xtravels-deployed-ext and xtravels-ext-readme screenshots.
Extract the @sap/cds-oyster code-extension sandbox reference material into a dedicated Code Extension Reference page (code-extension.md), mirroring the multitenancy index.md/mtxs.md how+reference split. business-logic.md and business-logic-advanced.md keep their walkthroughs and best practices, with moved blocks replaced by short orientation stubs linking into the reference. Also applies a house-style pass across all three pages (pre-defined, -ize spelling, bare ## Introduction headings, no & in headings) and adds the new page to _menu.md.
…ox debugging business-logic.md: - Document the generated JSDoc handler stub and how it drives code completion - Note the mocked sandbox is debuggable in-process (cds watch --debug) business-logic-advanced.md: - Reframe before-CREATE around the verified declarative-vs-handler boundary: @mandatory/@assert.range/@assert.notNull/@readonly work in extensions only on added, defaulted fields; provider fields and @Assert:(case ...) constraints are rejected at push. Keep only the cross-record checks (customer lookup, budget). - Replace the hand-rolled TravelLog audit trio with a pointer to @cap-js/change-tracking and a single after-CREATE emit('TravelCreated') example - Swap TravelLog for CustomerPolicies + a TravelCreated event in the opened surface code-extension.md: - Add a Debugging in the mocked sandbox section and a troubleshooting row
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Control PanelHi, I'm an AI-powered Review Bot that helps you with summarizing and reviewing pull requests.
|
SummaryThe following content is AI-generated and provides a summary of the pull request: Document XTravels Extensibility and CDS-Oyster Code ExtensionsDocumentation📚 Migrates the SaaS customization walkthrough to the modular XTravels sample and introduces comprehensive guidance for sandboxed business logic extensions with Changes
Images and Links
PR Bot InformationVersion:
|
There was a problem hiding this comment.
I found a few substantive documentation issues that could mislead readers about CAP handler transaction timing and one template layout mismatch around db/data. The rest of the PR reads as a coherent port to XTravels with clear structure and useful examples.
PR Bot Information
Version: 1.31.64
- LLM:
gpt-5.5 - File Content Strategy: Full file content
- Event Trigger:
issue_comment.edited - Review Focus Files:
- Correlation ID:
f0a55c10-bcd9-11f1-8252-55e0b9ef2f35
…layout after handlers run inside the request transaction (pre-commit), not post-commit: a reject rolls back both the write and the handler's own changes. Verified via a purpose-built test in cds-oyster under both the mocked and wasm engines. Also show db/data in the template layout, which the walkthrough creates for the shipped code list.
There was a problem hiding this comment.
I posted a few targeted comments where the new docs could mislead readers about supported handler events or local test setup. The earlier transaction-boundary and template-layout comments appear to have been addressed, so I did not repeat them.
PR Bot Information
Version: 1.31.64
- LLM:
gpt-5.5 - Correlation ID:
288c5390-bcdf-11f1-92bb-b6b30f554ebc - Event Trigger:
issue_comment.edited - Review Focus Files:
- File Content Strategy: Full file content
Resolve hyperspace-bot and reviewer comments on the extensibility guide: - Correct the CRUD handler event scope: no before-READ; before covers Create/Update/Upsert/Delete, after covers all CRUD+Upsert. Fixed the prose in business-logic-advanced.md and the handler-file tree in code-extension.md (verified against cds-oyster registrationCheck.js). - Show the inactive stub filename with its leading # in business-logic.md. - Clarify local submitForReview wiring vs the reference-logic pattern. - Rework the Add Test Data / seeding section in customization.md: say explicitly to copy the base app's CSVs and from where, turn the federated-data paths into a table, note cds pull only writes .base/, and explain why flights data comes from @capire/xflights-data (the integration package) rather than the @capire/xflights microservice. - Tighten the modular-application warning.
- Reframe the allowlist note: extending reuse/federated entities is a deliberate allowlist scoping choice, not a framework limitation. Verified against the real base model with the mtxs push-time linter: extending a @federated entity (sap.capire.s4.Customers) is rejected only because it is not in the allowlist, and is accepted once added. Focus the note on why the reuse modules are deliberately left out. - Replace 'seed/seeding' with capire's established 'test data' / 'initial data' vocabulary; rename the subsection anchor accordingly.
| namespace x_orders.ext; // only applies to new entities defined below | ||
| using { OrdersService, sap.capire.orders.Orders } from '@capire/orders'; | ||
| namespace x_travels.ext; // only applies to new entities defined below | ||
| using { TravelService, sap.capire.travels.Travels } from '@capire/xtravels'; |
There was a problem hiding this comment.
Do we miss an as here? Or would we need to full namespace for the following extend statement?
| using { TravelService, sap.capire.travels.Travels } from '@capire/xtravels'; | |
| using { TravelService, sap.capire.travels.Travels as Travels} from '@capire/xtravels'; |
Validated customization + business-logic + business-logic-advanced against a
from-scratch XTravels run (clone → MT enable → subscribe → pull → push).
customization.md:
- app UI port 4004 → 4114 (XTravels pins 4114)
- create the extension project OUTSIDE the base-app npm workspace (cd ../..),
else @capire/xtravels resolves to the base-app sources and it won't compile;
made the rationale a note
- fix test-data cp paths to ../samples/{xtravels/db/data, common/db/data,
s4/srv/external/data, xflights/apis/data-service/data}
- cds add extension only scaffolds extends + .base/package.json (made the
bookshop placeholder an info note; dropped the false app/extension.cds claim)
- inline the sidecar/app cds watch start commands at Subscribe
- note to move @cap-js/sqlite to optionalDependencies
business-logic.md / code-extension.md:
- cds watch --wasm → cds watch --profile wasm (the --wasm flag is not recognized)
- show extension_points() being called from init()
- cds push → cds push --to <sidecar> -u bob:
- note: upgrade tenants subscribed before code extensibility was enabled
- note: verify with a user authorized for the action, not the ExtensionDeveloper
business-logic-advanced.md:
- keep element-prefix; prefix all extension fields AND entities AND the event
with x_ (x_customerStatus, x_CustomerBudgets, x_CustomerPolicies, x_TravelCreated)
- new fields extend the base entity (extend Travels), not the TravelService
projection
Document the cds-oyster security concept: WASM-enforced tenant isolation, a mocked CDS API, callback-only integration with the runtime (no shared memory, no breakout), and runtime-secured service-fence enforcement for queries. Preface the forbidden-constructs linter reference as a push-time hygiene layer on top of that model.
Document two governance practices for subscribers running code extensions: separate the handler author from the designated deployer (four-eyes review via the cds.ExtensionDeveloper role), and validate on a test tenant before promoting to production.
Add a Technical Roles reference section to the MTX guide covering cds.ExtensionDeveloper and cds.Subscriber (verified against @sap/cds-mtxs), the mtcallback and internal-user technical roles, and guidance on when each is needed. Link it from the extension-tenant setup step in the customization guide.
| | Role | Unlocks | Used for | | ||
| | ---- | ------- | -------- | | ||
| | `cds.ExtensionDeveloper` | [ExtensibilityService](#extensibilityservice) (`/-/cds/extensibility/**`) | Reading the base model and pushing, activating, and deleting a tenant's own extensions (both model and code extensions). This is the role that `cds pull` and `cds push` require. It is **tenant-scoped**: a holder may only manage extensions for the tenant they belong to. | | ||
| | `cds.Subscriber` | [DeploymentService](#deploymentservice) (`/-/cds/deployment/**`), [SaasProvisioningService](#saasprovisioningservice) (`/-/cds/saas-provisioning/**`) | Subscribing, upgrading, and unsubscribing tenants. A technical role for the provisioning client (the automation that onboards tenants), never for end users. | |
There was a problem hiding this comment.
I think this is never used productively, only for the local testing scenario. When deployed, only 'internal-user' is used.
There was a problem hiding this comment.
You mean the subcriber role?
There was a problem hiding this comment.
Good catch, thanks. You're right that cds.Subscriber isn't the productive path. I verified against @sap/cds-mtxs: it's declared on DeploymentService (['cds.Subscriber','internal-user']) and SaasProvisioningService (['cds.Subscriber','mtcallback','internal-user']), but in a deployed app those endpoints are reached as internal-user from the application zone, with SaaS onboarding/offboarding via mtcallback. I've reworded the table and the when-to-use guidance to frame cds.Subscriber as mostly a local-testing affordance that's rarely assigned productively (a941bd9). I kept mtcallback alongside internal-user as productive callers for SaaS provisioning, since the service model accepts it there.
| - `mtcallback`: the role the SAP BTP SaaS Provisioning service presents when it calls the [SaasProvisioningService](#saasprovisioningservice) callback during tenant onboarding and offboarding. | ||
| - `internal-user`: a pseudo-role for internal, technical communication inside the [application zone](../security/overview#application-zone), for example the main application calling its own MTX sidecar. It is established by platform trust (a shared XSUAA instance), not granted to users. | ||
|
|
||
| ::: warning Keep technical roles out of business roles |
Per review feedback: cds.Subscriber is declared on the Deployment and SaaS-provisioning services but is not the productive caller. In a deployed app those endpoints are reached as internal-user from the application zone, with SaaS onboarding/offboarding via mtcallback. Reword the role table and the when-to-use guidance accordingly.
Add an Extension Lifecycle and Schema Changes section covering additive model merges, activation, removing/shrinking extensions (local SQLite error vs HANA orphans), type changes, canonical column-name reuse, and the relevant config (auto_undeploy, undeploy.json, skipExtensionCheck, schema_evolution). Link it from the activation step in the customization guide.
|
|
||
| ::: | ||
|
|
||
| Activating an extension changes the tenant's database schema. Model extensions are **additive**: later pushes add fields and entities, but removing or retyping an activated element is constrained, and on SAP HANA removed columns are not dropped. See [Extension Lifecycle and Schema Changes](../multitenancy/mtxs#extension-lifecycle) before you rely on changing or rolling one back. |
There was a problem hiding this comment.
It is more complicated. Sqlite will throw an error. With HANA, fields are dropped (!). Entities are not dropped except undeploy.json contains a matching pattern or auto_undeploy is set.
…guide-to-xtravels' into port-extensibility-guide-to-xtravels
HDI's delta deployment works at the file level: deleted files are not undeployed by default, but modified files are redeployed with ALTER. That means removing a field from an extension drops the column and its data on HANA, while removing a whole entity leaves the table behind as an orphan (only cleared via undeploy.json or auto_undeploy).
…omer flow, oyster sidecar fix customization.md: add 'Set Up the Extension Project Locally' (sidecar :4005, host :4114, extension project standalone :4006) to the provider walkthrough; rewrite the SaaS Customer section BTP-first and renumber; de-noise Prerequisites and demote incidental links; refocus 'Provide Extension Guides' on app-specific content; fix BTP 'cds pull' syntax. business-logic.md: point Prerequisites at the provider walkthrough; move the local srv/server.js reference wiring into Test-Drive before the 409 check; declare @sap/cds-oyster in mtx/sidecar/package.json instead of 'npm --prefix' and warn against npm in the sidecar (dual-cds); add a re-subscribe-tenants-after-oyster warning. Remove em-dashes throughout both guides.




Port Extensibility Guides to XTravels
Documentation
📚 Updates the extensibility documentation to use the XTravels sample throughout and adds new code extensibility guides for sandboxed business logic extensions. The model customization walkthrough now focuses on extending
sap.capire.travels.Travelswithx_priorityandx_CostCenter, including local setup, tenant activation, test data guidance, and refreshed UI verification screenshots.Changes
guides/extensibility/customization.md: Reworked the customization guide from Orders/bookshop examples to XTravels, including multi-repo workspace setup, MTX sidecar subscription flow, extension template layout, local reference wiring, model-only extension examples, local vs shipped data guidance, and XTravels-specific UI annotations.guides/extensibility/business-logic.md: Added a new guide for pre-defined business logic extension points using@sap/cds-oyster, covering provider setup, tenant handler implementation, local/wasm testing, push flow, and best practices.guides/extensibility/business-logic-advanced.md: Added advanced guidance for opening regular services to controlled code extensions, including CRUD handlers, after-READ enrichment, cross-record validation, pagination, and safety recommendations.guides/extensibility/code-extension.md: Added a sandbox reference covering engines, configuration, handler file layout, sandbox API, event scope, query constraints, forbidden constructs, quarantine behavior, and troubleshooting.guides/extensibility/_menu.md: Added navigation entries for the new business logic and code extension documentation pages.guides/extensibility/assets/*: Replaced superseded Orders screenshots with new XTravels screenshots for the base Travels list, extension template README, Fiori preview, and deployed tenant UI.Images and Links
PR Bot Information
Version:
1.31.64264dc780-bcda-11f1-810b-d179ffdc6203issue_comment.edited