Skip to content

Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference - #2917

Draft
nkaputnik wants to merge 30 commits into
mainfrom
port-extensibility-guide-to-xtravels
Draft

nkaputnik wants to merge 30 commits into
mainfrom
port-extensibility-guide-to-xtravels

Conversation

@nkaputnik

@nkaputnik nkaputnik commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

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.Travels with x_priority and x_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

XTravels Travels List
XTravels Extension README
XTravels Fiori Preview Extension
XTravels Deployed Extension

  • 🔄 Regenerate and Update Summary
PR Bot Information

Version: 1.31.64

  • Correlation ID: 264dc780-bcda-11f1-810b-d179ffdc6203
  • Event Trigger: issue_comment.edited

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.

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(deleted)

nkaputnik and others added 10 commits September 23, 2026 15:55
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>

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(deleted)

nkaputnik and others added 3 commits September 30, 2026 16:10
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>

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(deleted)

Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
@hyperspace-pr-bot

hyperspace-pr-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Control Panel

Hi, I'm an AI-powered Review Bot that helps you with summarizing and reviewing pull requests.
To interact with me, just use the following actions:

  • 📝 Summarize PR
  • 🔍 Review
  • 🗑️ Delete all bot comments and reviews

@hyperspace-pr-bot

hyperspace-pr-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The following content is AI-generated and provides a summary of the pull request:


Document XTravels Extensibility and CDS-Oyster Code Extensions

Documentation

📚 Migrates the SaaS customization walkthrough to the modular XTravels sample and introduces comprehensive guidance for sandboxed business logic extensions with @sap/cds-oyster. The update covers provider and subscriber workflows, secure extension surfaces, local and tenant testing, deployment governance, and refreshed UI examples.

Changes

  • guides/extensibility/customization.md: Reworks model extensibility around XTravels, including workspace setup, extension templates, tenant activation, reference logic, federated test data, x_priority and x_CostCenter examples, and safe handling of local versus shipped data.
  • guides/extensibility/business-logic.md: Adds an end-to-end guide for defining, implementing, testing, and pushing pre-defined sandboxed extension points.
  • guides/extensibility/business-logic-advanced.md: Documents controlled code extensions for regular services, including CRUD handlers, after-READ enrichment, cross-record validation, events, pagination, and extension allow-lists.
  • guides/extensibility/code-extension.md: Adds the CDS-Oyster reference for sandbox engines, configuration, handler layout, APIs, event scope, query restrictions, security, forbidden constructs, quarantine, and troubleshooting.
  • guides/extensibility/_menu.md: Adds navigation for the new business logic and code extension pages.
  • guides/multitenancy/mtxs.md: Documents MTX technical roles, their permitted operations, and governance recommendations.
  • guides/extensibility/assets/*: Replaces outdated Orders screenshots with XTravels extension workflow screenshots.

Images and Links

XTravels Travels List
XTravels Extension README
XTravels Fiori Preview
XTravels Deployed Extension


  • 🔄 Regenerate and Update Summary
  • ✏️ Insert as PR Description (deletes this comment)
  • 🗑️ Delete comment
PR Bot Information

Version: 1.32.18

  • Output Template: Default Template
  • LLM: gpt-5.6-sol
  • Summary Prompt: Default Prompt
  • Event Trigger: issue_comment.edited
  • Correlation ID: ab6fff80-c6ff-11f1-9a92-c1d5b12464b2
  • File Content Strategy: Full file content

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/customization.md
…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.

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/code-extension.md Outdated
Comment thread guides/extensibility/business-logic.md Outdated
Comment thread guides/extensibility/business-logic.md Outdated
@nkaputnik nkaputnik changed the title Port extensibility customization guide to XTravels Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference Oct 1, 2026
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
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.
@nkaputnik
nkaputnik requested a review from smahati October 8, 2026 13:40
@nkaputnik
nkaputnik requested a review from danjoa October 8, 2026 13:40
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
- 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.
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md Outdated
Comment thread guides/extensibility/customization.md
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';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we miss an as here? Or would we need to full namespace for the following extend statement?

Suggested change
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.
Comment thread guides/multitenancy/mtxs.md Outdated
| 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. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is never used productively, only for the local testing scenario. When deployed, only 'internal-user' is used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You mean the subcriber role?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good to mention this!

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.
Comment thread guides/extensibility/customization.md Outdated

:::

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

vmikhailenko and others added 4 commits October 14, 2026 17:36
…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.

This branch has not been deployed

No deployments
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.

4 participants