<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>DJ Adams</title>
  <subtitle>Reserving the right to be wrong</subtitle>
  <link href="https://qmacro.org/feed/feed.xml" rel="self" />
  <link href="https://qmacro.org/blog/" />
  <updated>2026-07-29T00:00:00Z</updated>
  <id>https://qmacro.org/blog/</id>
  <author>
    <name>DJ Adams</name>
  </author>
  <entry>
    <title>Knowledge and netiquette in today&#39;s AI era</title>
    <link href="https://qmacro.org/blog/posts/2026/07/29/knowledge-and-netiquette-in-todays-ai-era/" />
    <updated>2026-07-29T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/29/knowledge-and-netiquette-in-todays-ai-era/</id>
    <content type="html">&lt;p&gt;I&#39;m walking in the cool mornings at the moment, as the problem with my right
knee is preventing me from running right now, which is driving me bonkers.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/07/morning-from-the-stern.jpg&quot; alt=&quot;View from the narrowboat stern this morning just before I set off on the walk&quot;&gt;
&lt;em&gt;View from the narrowboat stern this morning just before I set off on the walk.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On the walk this morning, I listened to a couple of episodes from two great
podcasts I&#39;m subscribed to - &lt;a href=&quot;https://hanselminutes.com/&quot;&gt;Hanselminutes&lt;/a&gt; and
&lt;a href=&quot;https://softskills.audio/&quot;&gt;Soft Skills Engineering&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;knowledge-engineering-and-lifecycle-management&quot;&gt;Knowledge engineering and lifecycle management&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://hanselminutes.com/1051/stack-overflow-for-the-agent-era-with-vp-of-product-alex-lato&quot;&gt;Stack Overflow for the Agent Era - with VP of Product Alex
Lato&lt;/a&gt;,
Scott Hanselman talks to Alex Lato about how Stack Overflow is evolving, driven
by, and perhaps driven towards, the agent substrate. It&#39;s a fascinating
conversation between two experienced folks, and well worth a complete listen.
What I took from this conversation is that we may see a new knowledge-related
discipline emerging, or at least a stronger focus in that direction.&lt;/p&gt;
&lt;p&gt;Scott and Alex talked a lot about knowledge provenance, reliability,
attribution and ranking, which made me wonder about what knowledge engineering,
perhaps knowledge lifecycle management, might look like today and tomorrow.
This knowledge, and how agents source, relay, condense, combine and share it,
is originally from the hard work of folks on Stack Overflow and in other
communities sharing what they know, but how will that evolve when the layers of
reuse coalesce over time?&lt;/p&gt;
&lt;p&gt;One other fascinating aspect that Alex shared, and Scott picked up, is that in
Stack Overflow&#39;s new venture here, agents, and their activities, are ultimately
and strongly tied to human &amp;quot;owners&amp;quot;, with the provenance - but more importantly
reputation - that is part of that association.&lt;/p&gt;
&lt;h2 id=&quot;netiquette-and-how-our-connections-are-changing&quot;&gt;Netiquette and how our connections are changing&lt;/h2&gt;
&lt;p&gt;In Soft Skills Engineering&#39;s &lt;a href=&quot;https://softskills.audio/2026/07/06/episode-520-i-came-back-to-my-former-team-and-was-shocked-by-ai-and-my-team-does-not-care-at-all-about-the-code/&quot;&gt;Episode
520&lt;/a&gt;,
hosts Dave Smith and Jamison Dance are entertaining and fun to listen to as
usual, and the word &amp;quot;netiquette&amp;quot; is brought up in the context of what one
should and should not do in today&#39;s era of AI assisted work.&lt;/p&gt;
&lt;p&gt;Netiquette was originally an umbrella term for how to behave in the brave new
world of Internet-based communication - for example how and when to use the
To:, Cc: and Bcc: in email correspondence (on which &lt;a href=&quot;https://qmacro.org/blog/posts/2014/11/14/addressing-emails/&quot;&gt;I have
thoughts&lt;/a&gt; too), when to reply, and
how formal, or not, one should be, in various situations. That concept of &amp;quot;how
to behave&amp;quot; surfaces in this conversation again where Dave and Jamison talk
about their (and others&#39;) experiences with folks copy-pasting wads of
generative AI output to each other, sometimes without even reading it
themselves.&lt;/p&gt;
&lt;p&gt;Following that train of thought, they reach a conclusion that is not an
entirely pleasant one, that the LLM facilities we have at our fingertips today
is causing the death of the human connection, a connection that originally
evolved (in our tech workplaces) almost as a by-product of collaborating on
design and code, to get it right. When we have LLMs do a lot of that for us,
where&#39;s the context in which we maintain that loose but essential human
connection - the shared jokes, the gently snarky but well-meaning asides?&lt;/p&gt;
&lt;p&gt;If you&#39;re not subscribed to these podcasts, I recommend you remedy that today!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Timeless principles, agnostic design and the power of CAP&#39;s abstractions</title>
    <link href="https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/" />
    <updated>2026-07-24T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/</id>
    <content type="html">&lt;p&gt;I wrote recently about Hexagonal Architecture, alternatively known as Ports &amp;amp;
Adapters, in &lt;a href=&quot;https://qmacro.org/blog/posts/2026/06/04/book-overflow-and-two-architectural-patterns-in-cap/#ports-and-adapters&quot;&gt;Book Overflow and two architectural patterns in
CAP&lt;/a&gt;.
The core idea is based on having a deliberately agnostic approach to
mechanisms, resources and services beyond - located in the outer concentric
circles, as it were - a given core service.&lt;/p&gt;
&lt;p&gt;Think of this in a similar way to &amp;quot;late cut&amp;quot; integration, where the actual
location, shape of, and connection to a required service is left until the
last minute.&lt;/p&gt;
&lt;p&gt;The agnostic design approach is not new, and indeed as Daniel mentions in his
keynote, has in the past been referred to as &amp;quot;minimal assumptions&amp;quot;, which crops
up in various disciplines, including statistics &amp;amp; data analysis, where it
conveys the approach of &amp;quot;&lt;em&gt;deriving valid conclusions using the fewest possible
restrictive parameters&lt;/em&gt;&amp;quot;&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This approach brings many advantages, not least the ability for CAP developers
to enjoy a tight and rapid development loop, where
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;local-first&lt;/a&gt; is the
mantra, and mocking plus remote proxies are key enablers.&lt;/p&gt;
&lt;p&gt;Moreover it allows us to shift &lt;em&gt;left&lt;/em&gt; the important business of design,
including auth, consumption nuances and extended domain design, exactly because
we can shift &lt;em&gt;right&lt;/em&gt; the dirty work of connectivity and gnarly setups.&lt;/p&gt;
&lt;p&gt;But that&#39;s only one half of the story. The other half is that, right from the
get-go, we&#39;re ready to adapt and adopt new services, or different endpoint
locations, because we haven&#39;t tightly coupled our app or service design with a
specific technology or protocol.&lt;/p&gt;
&lt;h2 id=&quot;the-wonder-of-cds-service-bindings&quot;&gt;The wonder of cds.service.bindings&lt;/h2&gt;
&lt;p&gt;To illustrate this, I want to convey the wonder of one of Daniel&#39;s live demos
in the keynote. Indeed, this blog post was triggered by something very
specific, when Daniel accessed &lt;code&gt;cds.service.bindings&lt;/code&gt; in the cds REPL.&lt;/p&gt;
&lt;p&gt;I have talked about the local service binding registry (&lt;code&gt;~/.cds-services.json&lt;/code&gt;)
and explained its purpose, in many places, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-local-development-workshop&quot;&gt;CAP local
development&lt;/a&gt;
(workshop)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-service-integration-codejam&quot;&gt;Service integration with SAP Cloud Application Programming
Model&lt;/a&gt;
(CodeJam)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on&quot;&gt;A hands-on tour of CAP&lt;/a&gt;
(CodeJam)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s break down what we mean by &amp;quot;local service binding registry&amp;quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;local: it&#39;s local to my machine, both highlighted and constrained by the
location of this file, the developer user&#39;s home
directory&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; - you can&#39;t get much more &amp;quot;my machine&amp;quot;
specific than that!&lt;/li&gt;
&lt;li&gt;service: required services, that are likely going to be remote in a
production scenario&lt;/li&gt;
&lt;li&gt;binding: information that is needed to be able to connect and authenticate
with such services, such as URL &amp;amp; credentials, often collected into a
&lt;a href=&quot;https://help.sap.com/docs/excise-tax-management/administration/sap-btp-creating-and-configuring-destination&quot;&gt;destination&lt;/a&gt;
in production scenarios&lt;/li&gt;
&lt;li&gt;registry: a sort of table of contents, or list of what&#39;s currently available&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Such a local registry is at the heart of how agnostic design&#39;s innermost set
of concentric circles (the local machine) can function in CAP.&lt;/p&gt;
&lt;p&gt;Seeing Daniel retrieve this binding information directly in the cds REPL was a
magic moment for me. It both elevated the combined concepts I&#39;ve mentioned above,
plus made the registry content tangible and thus worthy of attention.&lt;/p&gt;
&lt;h2 id=&quot;exploring-the-first-two-circles&quot;&gt;Exploring the first two circles&lt;/h2&gt;
&lt;p&gt;Let&#39;s explore the two innermost circles&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, the ones
&lt;em&gt;within&lt;/em&gt; the local machine.&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt; +--------------------------+
 |     external process     |
 | ************************ |
 | * +------------------+ * |
 | * | separate process | * |
 | * |  +------------+  | * |
 | * |  | in-process |  | * |
 | * |  |            |  | * |
 | * |  +------------+  | *&lt;---- local machine
 | * +------------------+ * |
 | ************************ |
 +--------------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can run a single CAP server, that will serve one or more services, via one
or more protocols. That&#39;s denoted by the core &amp;quot;in-process&amp;quot; circle in this
diagram here. When we have a required service without
service bindings available, these are mocked also by the same CAP server.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At this point I often refer to the help text for the &lt;code&gt;--with-mocks&lt;/code&gt; option
for &lt;code&gt;cds serve&lt;/code&gt; which goes like this (emphasis mine):&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Use this in combination with the variants serving multiple services.
&lt;strong&gt;It starts in-process mock services for all required services configured
in &lt;code&gt;package.json#cds.requires&lt;/code&gt;, which don&#39;t have external bindings
in the current process environment.&lt;/strong&gt;
Note that by default, this feature is disabled in production and must be
enabled with configuration &lt;code&gt;features.mocked_bindings=true&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can run multiple CAP servers on the same machine, choosing different
ports&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;. From the perspective of the &amp;quot;in-process&amp;quot;
innermost circle, the next circle out, marked &amp;quot;separate process&amp;quot;, represents
these other CAP servers.&lt;/p&gt;
&lt;p&gt;This &amp;quot;local machine&amp;quot; universe, combined with CAP&#39;s local-first affordances,
is exactly what we need to experiment with agnostic design here.&lt;/p&gt;
&lt;p&gt;This demo follows roughly the same path as Daniel took in his keynote, with
some slight variations.&lt;/p&gt;
&lt;h3 id=&quot;start-monitoring-the-local-service-binding-registry&quot;&gt;Start monitoring the local service binding registry&lt;/h3&gt;
&lt;p&gt;It&#39;s helpful to see what happens as things progress, so let&#39;s use one terminal
window to keep an eye on the local service binding registry&#39;s contents. Here&#39;s
how I would do it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; ~/.cds-services.json &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-c&lt;/span&gt; jq &lt;span class=&quot;token parameter variable&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; ~/.cds-services.json&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;I use &lt;code&gt;touch&lt;/code&gt; first to make sure the file exists before trying to monitor it;
this command will create the file, empty, if it doesn&#39;t. If it has already
been populated with information from previously running CAP servers (that have
since been stopped) then it may already contain some empty registry structure
that looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;create-a-simple-cap-project-a&quot;&gt;Create a simple CAP project A&lt;/h3&gt;
&lt;p&gt;First, let&#39;s create a simple &lt;code&gt;tiny-sample&lt;/code&gt; facet based CAP project &amp;quot;A&amp;quot; then
immediately launch a cds REPL and have the CAP server start
up&lt;a href=&quot;https://qmacro.org/blog/posts/2026/07/24/timeless-principles-agnostic-design-and-the-power-of-caps-abstractions/#footnotes&quot;&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds init &lt;span class=&quot;token parameter variable&quot;&gt;--add&lt;/span&gt; tiny-sample proj-A &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cds repl &lt;span class=&quot;token parameter variable&quot;&gt;--run&lt;/span&gt; proj-A&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Log output like this will be emitted:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token property&quot;&gt;Adding facet:&lt;/span&gt; tiny&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;sample

Successfully initialized CAP project
&lt;span class=&quot;token property&quot;&gt;Continue with:&lt;/span&gt; code proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A

Welcome to cds repl &lt;span class=&quot;token number&quot;&gt;v10.0.3&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; loaded model from &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

  proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;cat&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cds

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; database&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from proj&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;A&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;db&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;CatalogService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Books&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using auth strategy &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; kind&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocked&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving CatalogService &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;proj-A/srv/cat-service.cds:1&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:33475&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server &lt;span class=&quot;token number&quot;&gt;v10.0.3&lt;/span&gt; launched in &lt;span class=&quot;token number&quot;&gt;209&lt;/span&gt; ms
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; terminate with &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt;C &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token separator comment&quot;&gt;------------------------------------------------------------------------&lt;/span&gt;
Following variables are made available in your repl&#39;s global context&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token property&quot;&gt;from cds.entities:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token property&quot;&gt;from cds.services:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  db&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  CatalogService&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;

Simply type e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; CatalogService in the prompt to use the respective objects&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So far, so (very) good. Notice that the CAP server is started on a random port,
which is the default behaviour when running in a REPL context (as it&#39;s
effectively more of a &amp;quot;throwaway&amp;quot; server that might be spun up to run some
tests against).&lt;/p&gt;
&lt;p&gt;Notice also that there&#39;s a service called &lt;code&gt;CatalogService&lt;/code&gt; that&#39;s available.&lt;/p&gt;
&lt;h3 id=&quot;check-the-local-service-binding-registry&quot;&gt;Check the local service binding registry&lt;/h3&gt;
&lt;p&gt;In the registry, we now see something like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;CatalogService&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;endpoints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;odata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/odata/v4/catalog&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;58557&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;58557&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file:///tmp/proj-A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:33475&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells us (and any CAP server running in the same binding context, i.e.
this local machine) that there&#39;s a service called &lt;code&gt;CatalogService&lt;/code&gt; that is
provided. There&#39;s information on what the endpoints are, and what protocols
these endpoints speak, and also the URL. In other words, this is the binding
context for the &lt;code&gt;CatalogService&lt;/code&gt; that is listed as being provided (note the
&lt;code&gt;cds.provides&lt;/code&gt; property that contains it)!&lt;/p&gt;
&lt;h3 id=&quot;connect-and-consume-catalogservice-locally&quot;&gt;Connect and consume CatalogService locally&lt;/h3&gt;
&lt;p&gt;Within the REPL, if we now have a quick look at the &lt;code&gt;CatalogService&lt;/code&gt;, we see
that it&#39;s an instance of the &lt;code&gt;ApplicationService&lt;/code&gt; class, effectively a locally
available service:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; CatalogService
ApplicationService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-service&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&#39;$linkProviders&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can consume that service directly, whereupon we&#39;ll get the result we
probably expect:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; CatalogService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can be explicit and &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/core-services#connecting-to-required-services--cdsconnect&quot;&gt;connect to&lt;/a&gt; the service, a &amp;quot;required&amp;quot; service, like this, too:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; catsrv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
ApplicationService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app-service&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string-property property&quot;&gt;&#39;$linkProviders&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We effectively get the same &lt;code&gt;ApplicationService&lt;/code&gt; instance, and can use it in
the same way:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; catsrv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;consume-the-provided-service-from-elsewhere&quot;&gt;Consume the provided service from elsewhere&lt;/h2&gt;
&lt;p&gt;We don&#39;t even need to set up a second project to require (consume) this
provided service, we can just start a second cds REPL session and do everything
there.&lt;/p&gt;
&lt;p&gt;While keeping the current cds REPL session open, let&#39;s start a second cds REPL
session in a new terminal window. This should represent a distinctly separate
CAP consumer context and so let&#39;s start this second cds REPL session
completely separate from the &lt;code&gt;proj-A/&lt;/code&gt; area to emphasise that point. Daniel used
his home directory for that, so let&#39;s do that too:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~ &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cds repl&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;fetch-the-service-bindings&quot;&gt;Fetch the service bindings&lt;/h4&gt;
&lt;p&gt;In the session that we get, which is announced like this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Welcome to cds repl v10.0.3
&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we can access the service bindings, like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bindings&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This fetches the service bindings from the registry and makes them available in
the current process:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
Bindings &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;provides:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;CatalogService:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; endpoints&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; odata&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/catalog&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; server&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;58557&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;servers:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;58557&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; root&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;file:///tmp/proj-A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:33475&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We even see that log line familiar to us from our &lt;code&gt;cds watch&lt;/code&gt; sessions, being
explicit about from where the bindings are being fetched:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;connect-to-the-service&quot;&gt;Connect to the service&lt;/h4&gt;
&lt;p&gt;Like we did in the other cds REPL session, let&#39;s now use &lt;code&gt;cds.connect.to&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; cs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
RemoteService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;EventHandlers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CatalogService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;odata&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;requestTimeout&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;60000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;csrf&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;csrfInBatch&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time, it&#39;s not an instance of the &lt;code&gt;ApplicationService&lt;/code&gt; class, it&#39;s an
instance of the &lt;code&gt;RemoteService&lt;/code&gt; class!&lt;/p&gt;
&lt;h4 id=&quot;send-a-query-to-the-service&quot;&gt;Send a query to the service&lt;/h4&gt;
&lt;p&gt;What&#39;s more, we can interact with that service ... as if it were local:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Books&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Wuthering Heights&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Emily Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Jane Eyre&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Charlotte Brontë&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;The Raven&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Eleonora&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Edgar Allen Poe&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Catweazle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Richard Carpenter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wham!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Going back to the concentric circles, this is a effectively an example of the
two that are within the confines of the local machine. One, the provided
service, exists as if it were remote (with a URL) in the eyes of the consuming
service (or REPL context here).&lt;/p&gt;
&lt;p&gt;CAP&#39;s adoption of minimal assumptions in service provision and consumption is
so complete that the lines become blurred between local and remote, thanks to
the power of remote proxies that do the heavy lifting of query transport across
the wire for us.&lt;/p&gt;
&lt;p&gt;This really is hard evidence of one of CAP&#39;s &amp;quot;magic made simple&amp;quot; moments, and
is explained further in the &lt;a href=&quot;https://cap.cloud.sap/docs/get-started/bookshop#cap-level-integration&quot;&gt;CAP-level
Integration&lt;/a&gt;
section of the Bookshop topic in Capire.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;See &lt;a href=&quot;https://www.tandfonline.com/doi/abs/10.1080/01621459.1962.10500545&quot;&gt;Non-Linear Regression with Minimal
Assumptions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The symbol for a user&#39;s home directory is the tilde (&lt;code&gt;~&lt;/code&gt;). I&#39;m guessing some
of you know why it&#39;s this symbol, but for those of you who don&#39;t, have a
look at the keyboard of the &lt;a href=&quot;https://en.wikipedia.org/wiki/ADM-3A&quot;&gt;ADM-3A&lt;/a&gt;
terminal, specifically in the top right. &lt;a href=&quot;https://en.wikipedia.org/wiki/ADM-3A&quot;&gt;Bill
Joy&lt;/a&gt;, erstwhile employee of Sun and
perhaps more importantly creator of both &lt;code&gt;vi&lt;/code&gt; and the C Shell (&lt;code&gt;csh&lt;/code&gt;), used
an ADM-3A and it was in the C Shell where the tilde came to represent a
user&#39;s home directory.&lt;/p&gt;
&lt;p&gt;Also on that same key is the caret (&lt;code&gt;^&lt;/code&gt;), which also represents &amp;quot;home&amp;quot;
(beginning of a line) in regular expression dialects. Coincidence? I think
not! :-)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/07/adm-3a-home-key.png&quot; alt=&quot;ADM-3A home key&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;OK, it may not have escaped your notice that these are not circles. Just
pretend they are.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&#39;s the concept of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_socket&quot;&gt;socket&lt;/a&gt;
that we must bear in mind, which is the combination of protocol, address
(hostname / IP) and port. But that&#39;s a story for another time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can actually just specify the project location as a single argument and
the same thing will happen: &lt;code&gt;cds repl proj-A&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>reCAP 2026 talk resources</title>
    <link href="https://qmacro.org/blog/posts/2026/07/15/recap-2026-talk-resources/" />
    <updated>2026-07-15T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/15/recap-2026-talk-resources/</id>
    <content type="html">&lt;p&gt;At &lt;a href=&quot;https://recap-conf.dev/&quot;&gt;reCAP&lt;/a&gt; this year, I was honoured to share a talk
slot with &lt;a href=&quot;https://www.linkedin.com/in/patrice-bender-64a816118/&quot;&gt;Patrice
Bender&lt;/a&gt;, a good friend
and adjacent colleague from the CAP Compiler team, and cohost / copresenter on
the &lt;a href=&quot;https://qmacro.org/blog/posts/2025/12/09/a-new-hands-on-sap-dev-mini-series-on-the-core-expression-language-in-cds/&quot;&gt;Hands-on SAP Dev mini-series on the core expression language in
CDS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://recap-conf.dev/program.html&quot;&gt;talk&lt;/a&gt; was titled &lt;strong&gt;Expressions
and Abstractions - Two Developer Superpowers in CAP&lt;/strong&gt;, with the following
overview:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Today we need to be more efficient and concise than ever, stop writing
code we don&#39;t need to, and avoid tasks that slow down our development
loops, letting the framework do the heavy lifting for us. In this
session we&#39;ll demonstrate two different affordances that enable that.
First, we&#39;ll show the power of expressions, what they are, how and
where they can be used, and why you should know about them. Then we&#39;ll
show how mocking abstracts us from the tedium and ceremony, allowing us
to iterate fast on data, auth, messaging and remote services during
development.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Whether you watched the talk at reCAP in person, or remotely, please consider
filling in the short &lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSc88GKiyicSBTOmM8Hgl5wPoVC8Tvc9WbiaHfa3sg9itPRiFg/viewform?pli=1&quot;&gt;feedback
form&lt;/a&gt;.
Thanks!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here are some resources relating to the two parts.&lt;/p&gt;
&lt;h2 id=&quot;expressions&quot;&gt;Expressions&lt;/h2&gt;
&lt;p&gt;The demo resources used in this part of the talk are available in the repo
&lt;a href=&quot;https://github.com/patricebender/cxl-bookshop&quot;&gt;cxl-bookshop&lt;/a&gt; that is an
extended bookshop you can clone, open in &lt;code&gt;cds repl&lt;/code&gt;, and use to try everything
shown live.&lt;/p&gt;
&lt;p&gt;The talk is based on the 7-part Hands-on SAP Dev mini-series &lt;a href=&quot;https://youtube.com/playlist?list=PL6RpkC85SLQCEU8XcyqnA5wYEZGxMPm6B&quot;&gt;Under the hood:
CDS Expressions in
CAP&lt;/a&gt;,
with our written notes accompanying it, starting with &lt;a href=&quot;https://qmacro.org/blog/posts/2026/03/05/cds-expressions-in-cap-notes-on-part-1/&quot;&gt;Part
1&lt;/a&gt;.
For the reference, including syntax diagrams that show what an expression can
contain, see &lt;a href=&quot;https://cap.cloud.sap/docs/cds/cxl#expressions-expr&quot;&gt;the CXL topic in
Capire&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;abstractions&quot;&gt;Abstractions&lt;/h2&gt;
&lt;p&gt;The demo resources used in this part of the talk are available in the repo
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development&quot;&gt;cap-nodejs-local-first-development&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;Local-first dev with CAP
Node.js&lt;/a&gt; series
of blog posts covers mocking of
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js-mocking-data/&quot;&gt;data&lt;/a&gt;,
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/&quot;&gt;auth&lt;/a&gt;,
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/&quot;&gt;remote
services&lt;/a&gt;
and
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/15/local-first-dev-with-cap-node-js-mocking-messaging/&quot;&gt;messaging&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the content for the CodeJam &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on&quot;&gt;A hands-on tour of
CAP&lt;/a&gt; there are deep and
detailed dive exercises on &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on/blob/main/exercises/01/README.md&quot;&gt;mocking
auth&lt;/a&gt;
and &lt;a href=&quot;https://github.com/SAP-samples/cap-tour-hands-on/blob/main/exercises/02/README.md&quot;&gt;mocking
messaging&lt;/a&gt;.
At the end of each of these exercises are plenty of links to further
information including resources in &lt;a href=&quot;https://cap.cloud.sap/docs/&quot;&gt;Capire&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Computing memories</title>
    <link href="https://qmacro.org/blog/posts/2026/07/08/computing-memories/" />
    <updated>2026-07-08T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/08/computing-memories/</id>
    <content type="html">&lt;p&gt;My good friend and colleague &lt;a href=&quot;https://ajmaradiaga.com/&quot;&gt;Antonio&lt;/a&gt; shared
&lt;a href=&quot;https://www.linkedin.com/posts/ajmaradiaga_today-i-bumped-into-this-blog-post-the-share-7480610580723183616-je3k/&quot;&gt;some
thoughts&lt;/a&gt;
today (also, see update below) about a post he&#39;d just read: &lt;a href=&quot;https://unix.foo/posts/last-people-who-know-how-it-works/&quot;&gt;The Last People
Who Know How It
Works&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was composing a reply to Antonio&#39;s thoughts on LinkedIn, but then thought
better of it, and in the proper spirit of &amp;quot;owning (and being in control of)
one&#39;s own content&amp;quot;, harking back to the good old days of communication and
community on the Web, I thought I&#39;d write my reply here and then point to it
via a URL. So here goes.&lt;/p&gt;
&lt;p&gt;The post is a lovely read, and makes a great point that resonates with me, a
point about the potential (or imminent) loss of knowing how things work,
through having to &lt;em&gt;make&lt;/em&gt; things work. I have many memories of building things
from scratch, making computers do things (where in their default state they
would do nothing).&lt;/p&gt;
&lt;p&gt;For our SAP community readers, I also remember (in the early to mid 1990&#39;s)
calculating which actual magnetic tracks across which cylinders (physical
partitions on the
&lt;a href=&quot;https://en.wikipedia.org/wiki/History_of_IBM_magnetic_disk_drives&quot;&gt;DASD&lt;/a&gt;) to
place different parts of the SAP R/2 document database and indices (ABEZ, ABIB,
etc) for optimal head movement across the spinning platters. Most commonly we&#39;d
use IDCAMS to define &lt;a href=&quot;https://www.ibm.com/docs/en/zos/3.1.0?topic=organizations-vsam-data-sets&quot;&gt;VSAM Data
Sets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;m sure that many of you dear readers have equivalent and equally fond memories.&lt;/p&gt;
&lt;p&gt;One thing that stood out in the post was this wonderful image:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I went looking the other night for a recording of a modem connecting. People
keep them around like pressed flowers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Such sounds are indeed, at least in my mind, delicate artifacts, and worth
preserving. And preserving with care.&lt;/p&gt;
&lt;p&gt;One statement the post makes is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A machine that cannot challenge you is a thing you cannot know. You can only
use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I agree strongly with this. It summarises much of how I feel about
using computers, and reminds me of the TEDx talk I gave back in 2012 titled
&lt;a href=&quot;https://www.youtube.com/watch?v=-gvOCaExeK0&quot;&gt;Our Computational Future&lt;/a&gt;, on how
we should not be raising generations of &lt;em&gt;users&lt;/em&gt;, but generations of &lt;em&gt;creators
and builders&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s something else from the post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The knowledge is not in danger, in fact, it has never been safer. The AI
models have read every manual that no human reads.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now this I cannot agree with, in fact strongly disagree (based on the way I
read it, which may be incorrect). We have been down those roads of information
being lost to time, either due to deterioration of physical media, or due to
proprietary formats where there&#39;s no way of reincarnating a reader program. If
we&#39;re relying on AI to remember stuff for us, that&#39;s very short sighted. Who
owns the models, the systems, the processes? What format is that stored in, and
how accessible is that to everyone and anyone who wants it?&lt;/p&gt;
&lt;p&gt;That road is a road to pain and regret.&lt;/p&gt;
&lt;p&gt;Anyway, I don&#39;t want this last thought to take anything away from the post -
&lt;a href=&quot;https://unix.foo/posts/last-people-who-know-how-it-works/&quot;&gt;it&#39;s still a lovely
read&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Update: Antonio has put his thoughts on his own post now too, kudos: &lt;a href=&quot;https://ajmaradiaga.com/how-it-works/&quot;&gt;A simple reflection on how things work, curiosity and friction&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Blogging in en-GB</title>
    <link href="https://qmacro.org/blog/posts/2026/07/04/blogging-in-en-gb/" />
    <updated>2026-07-04T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/07/04/blogging-in-en-gb/</id>
    <content type="html">&lt;p&gt;Terence Eden recently published a post titled &lt;a href=&quot;https://shkspr.mobi/blog/2026/07/this-blog-is-written-in-en-gb/&quot;&gt;This blog is written in
en-GB&lt;/a&gt;. Before
I even read the post, I knew what it was going to be about, and that I had to
&lt;a href=&quot;https://github.com/qmacro/qmacro.github.io/commit/0119c30b9494671a064718a634bf1ee3f89d9666&quot;&gt;make that
change&lt;/a&gt;
myself too, for the same reasons as I&#39;d guessed he was going to explain.&lt;/p&gt;
&lt;p&gt;Terence expresses those reasons very well, so I won&#39;t try to reproduce them
here. I&#39;m in strong agreement with him and those reasons resonate with me. This
is my blog, I string all the words together, in my own style, on the topics I
choose, with or without bias, depending on what I think. That is called a
&lt;em&gt;voice&lt;/em&gt;. Everyone has one, this is mine.&lt;/p&gt;
&lt;p&gt;To ask someone to change that (as a commenter did, to Terence), is not only
poor judgement, it is also self-centred. It reminds me of how I sometimes feel
about people who get &amp;quot;offended&amp;quot;. Offence is taken, not given. Indeed, as Ricky
Gervais famously said &amp;quot;just because someone is offended, it doesn&#39;t mean
they&#39;re right&amp;quot;.&lt;/p&gt;
&lt;p&gt;I attribute much of my learning by coming across references or ideas that I
didn&#39;t quite understand, and &lt;em&gt;looking them up&lt;/em&gt;. Today, that&#39;s easier than ever.
To ask someone to make their cultural references more &amp;quot;accessible&amp;quot; is asking to
be spoon fed slop.&lt;/p&gt;
&lt;p&gt;Talking of slop, one thing that gives me hope in today&#39;s world of generated
content, is that the human experience as expressed by individuals is what will
keep us sane. If you want more on that, I recommend the post &lt;a href=&quot;https://jayacunzo.com/blog/your-move-chief&quot;&gt;The best response
to AI slop, infinite advice, and online noise is from Robin
Williams&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In turn, that post reminded me of the classic quote:&lt;/p&gt;
&lt;p&gt;&amp;quot;The computer can&#39;t tell you the emotional story. It can give you the
exact mathematical design, but what&#39;s missing is the eyebrows.&amp;quot;&lt;/p&gt;
&lt;p&gt;If you don&#39;t know who uttered that ... go and find out.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>CAP service authentication at design time and in production</title>
    <link href="https://qmacro.org/blog/posts/2026/06/19/cap-service-authentication-at-design-time-and-in-production/" />
    <updated>2026-06-19T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/06/19/cap-service-authentication-at-design-time-and-in-production/</id>
    <content type="html">&lt;p&gt;Recently I wrote about &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/&quot;&gt;mocking
auth&lt;/a&gt; in
CAP for a rapid local-first development loop that allows you to embrace auth
design rather than defer it to later.&lt;/p&gt;
&lt;p&gt;In development mode, unless otherwise stated (i.e. unless you add appropriate
annotations such as &lt;code&gt;@readonly&lt;/code&gt;, &lt;code&gt;@requires&lt;/code&gt; or &lt;code&gt;@restrict&lt;/code&gt;), all resources are
accessible to everyone, even without authenticating. This is appropriate and
fitting, helping to facilitate the tight feedback loop that folks love
when developing with CAP.&lt;/p&gt;
&lt;p&gt;What about production? Is it the same there, i.e. do we have to ensure we lock
down access before moving to production? Of course not. Here&#39;s how things work.&lt;/p&gt;
&lt;h2 id=&quot;default-auth-settings-for-development&quot;&gt;Default auth settings for development&lt;/h2&gt;
&lt;p&gt;In development mode, the default auth strategy is &amp;quot;mocked&amp;quot;, as we can see:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; cds env requires&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;restrict_all_services&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocked&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;alice&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;t1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;admin&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;bob&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;t1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;cds.ExtensionDeveloper&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;carol&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;tenant&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;t1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;admin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;cds.ExtensionDeveloper&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;yves&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;roles&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;internal-user&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&#39;*&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;tenants&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;t1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;isbn&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;t2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;*&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice also the &lt;code&gt;restrict_all_services&lt;/code&gt; property, which is set to &lt;code&gt;false&lt;/code&gt;
by default in development mode too.&lt;/p&gt;
&lt;p&gt;This property is at the core of the &amp;quot;failsafe&amp;quot; production auth mechanism that
means that even if you do nothing with regards to auth for your services, they
will be protected in production and only available to users who provide
appropriate authentication.&lt;/p&gt;
&lt;h2 id=&quot;default-auth-settings-for-production&quot;&gt;Default auth settings for production&lt;/h2&gt;
&lt;p&gt;In the &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/authentication#authentication-in-production&quot;&gt;Authentication in
Production&lt;/a&gt;
section in Capire, we read, in the &amp;quot;Enforced by Default&amp;quot; subsection:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In a productive scenario with an authentication strategy configured, for
example the default &lt;code&gt;jwt&lt;/code&gt;, all CAP service endpoints are authenticated by
default, regardless of the authorization model. That is, all services without
&lt;code&gt;@restrict&lt;/code&gt; or &lt;code&gt;@requires&lt;/code&gt; implicitly get &lt;code&gt;@requires: &#39;authenticated-user&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This can be disabled via feature flag
&lt;code&gt;cds.requires.auth.restrict_all_services: false&lt;/code&gt;, or by using &lt;code&gt;mocked&lt;/code&gt;
authentication explicitly in production&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can check that the default auth strategy is &lt;code&gt;jwt&lt;/code&gt; in production, like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;production cds env requires&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;jwt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;vcap&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;xsuaa&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice also here that &lt;code&gt;restrict_all_services&lt;/code&gt; is not there, and will thus have
an undefined value:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;production cds env requires&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;restrict_all_services
&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;understanding-the-mechanism&quot;&gt;Understanding the mechanism&lt;/h2&gt;
&lt;p&gt;Now we understand the background, let&#39;s dig in to see how this works, to
understand things better.&lt;/p&gt;
&lt;p&gt;In the runtime, there&#39;s &lt;code&gt;@sap/cds/lib/srv/protocols/https.js&lt;/code&gt;, which contains:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;../../index&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; decodeURI &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;utils
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PROD&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NODE_ENV&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;production&#39;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; restrict_all &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;requires&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;restrict_all_services &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; authenticated &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PROD&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; restrict_all &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;authenticated-user&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpAdapter&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;/**
   * Returns a handler to check required roles, or null if no check required.
   * @returns {express.RequestHandler|null}
   */&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; d &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;definition&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;d&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;@requires&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; d&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;@restrict&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; roles &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;rr&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; authenticated &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; rr &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;rr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;requires &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; roles &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;user
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;roles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;has&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;role&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//&gt; ok&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_is_anonymous&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//&gt; request login&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;403&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;User &#39;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; is lacking required roles: [&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;roles&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; HttpAdapter&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;This is from a &lt;code&gt;@sap/cds&lt;/code&gt; runtime version 9.9.1 at the time of writing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If we &lt;a href=&quot;https://qmacro.org/blog/posts/2017/02/19/the-beauty-of-recursion-and-list-machinery/#initial-recognition&quot;&gt;stare
at&lt;/a&gt;
this for a moment, we see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;authenticated&lt;/code&gt; is set to the value &lt;code&gt;[&#39;authenticated-user&#39;]&lt;/code&gt; if we&#39;re in
production and the &lt;code&gt;restrict_all_services&lt;/code&gt; value is NOT explicitly set to
&lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;then, in the handler that gathers and checks for the specific roles required
when a resource is requested, if there are no roles explicitly set as
required for the service, then this &lt;code&gt;authenticated-user&lt;/code&gt; role is used
(remember, &lt;code&gt;authenticated-user&lt;/code&gt; is a
&lt;a href=&quot;https://cap.cloud.sap/docs/guides/security/cap-users#pseudo-roles&quot;&gt;pseudo-role&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, if you haven&#39;t set a value explicitly for
&lt;code&gt;restrict_all_services&lt;/code&gt; then this will &amp;quot;fail safely&amp;quot; in production.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;So there you have it. I mean, it&#39;s sort of obvious when you think about it, but
I think it&#39;s always nice to &amp;quot;understand by reading&amp;quot; and spend a bit of time to
dwell on the mechanism.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Book Overflow and two architectural patterns in CAP</title>
    <link href="https://qmacro.org/blog/posts/2026/06/04/book-overflow-and-two-architectural-patterns-in-cap/" />
    <updated>2026-06-04T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/06/04/book-overflow-and-two-architectural-patterns-in-cap/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://bookoverflow.io/&quot;&gt;Book Overflow&lt;/a&gt; is &amp;quot;a long-form discussion podcast
for software engineers&amp;quot; and one of the shows to which I&#39;m subscribed.&lt;/p&gt;
&lt;p&gt;The recent episode 118 is one in &lt;a href=&quot;https://bookoverflow.io/episodes/ep_at1583mmii2kreerjovku7ed&quot;&gt;the series where Carter and Nathan
discuss&lt;/a&gt; the book
&lt;a href=&quot;https://www.oreilly.com/library/view/learning-domain-driven-design/9781098100124/&quot;&gt;Learning Domain-Driven Design: Aligning Software Architecture and Business
Strategy&lt;/a&gt;
by Vlad Khononov.&lt;/p&gt;
&lt;p&gt;I listened to this episode today and found that, as usual, the two go into great
depth and draw on their thoughtfulness and experience to tease out details and
connect the dots for us listeners.&lt;/p&gt;
&lt;p&gt;Covered in their discussions were a couple of patterns that resonated with me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ports And Adapters&lt;/li&gt;
&lt;li&gt;Transactional Outbox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both these patterns live and breathe strongly within CAP, from a philosophical
standpoint but also from a place that drives the fundamental design of the
framework and how it manifests for us developers. So I thought it would be
worth both highlighting this episode, series, and podcast, while also
connecting the patterns and where they are in CAP.&lt;/p&gt;
&lt;h2 id=&quot;ports-and-adapters&quot;&gt;Ports and adapters&lt;/h2&gt;
&lt;p&gt;The Ports And Adapters pattern is another name for &lt;a href=&quot;https://alistair.cockburn.us/hexagonal-architecture/&quot;&gt;Hexagonal
Architecture&lt;/a&gt;, brought
into this world and popularised by Alistair Cockburn. It&#39;s the ultimate
approach to making agnosticism and abstraction first class players in system
design.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/06/hexagonal-architecture-diagram.png&quot; alt=&quot;Alastair&#39;s Hexagonal Architecture diagram from his original
article&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Nathan playfully observed that the hexagon isn&#39;t really used to the max, with
only four sides used in the illustration. I may be misremembering, but I think
Alistair might have picked the hexagon as it was different from other boxy
shapes available in a classic software diagramming template he had to hand,
plus the &amp;quot;extra&amp;quot; sides lend themselves to further expansion by folks using the
diagram to express their own usage of the pattern.)&lt;/p&gt;
&lt;p&gt;Of course, we know that Hexagonal Architecture is &lt;a href=&quot;https://cap.cloud.sap/docs/get-started/concepts#hexagonal-architecture&quot;&gt;a core concept in
CAP&lt;/a&gt;,
one that supports CAP&#39;s agnostic-by-design approach to pretty much everything.
It also is a fundamental enabler of the CAP developer experience - &lt;a href=&quot;https://cap.cloud.sap/docs/get-started/features#jumpstart-grow-as-you-go&quot;&gt;grow as
you
go&lt;/a&gt;
for rapid prototyping with
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;mocks&lt;/a&gt;
followed by a seamless transition to production grade services when
appropriate.&lt;/p&gt;
&lt;h2 id=&quot;transactional-outbox&quot;&gt;Transactional outbox&lt;/h2&gt;
&lt;p&gt;The Transactional Outbox pattern is one that we see reminders of while
developing, with the built-in &lt;code&gt;outbox&lt;/code&gt; table. This pattern allows the
coordination of a typical enterprise scenario where data needs to be updated
and an event needs to be sent to a remote system.&lt;/p&gt;
&lt;p&gt;The requirement to have both (synchronous and asynchronous) parts as a
transactional unit presents challenges, but by deferring the actual delivery of
the event to a separate service, the two parts can coalesce and indeed be
treated as a unit that collectively either works or doesn&#39;t.&lt;/p&gt;
&lt;p&gt;Facilitating this is an &amp;quot;outbox&amp;quot; for events, which is at the heart of this
pattern, and which &lt;a href=&quot;https://cap.cloud.sap/docs/guides/events/event-queues&quot;&gt;CAP has had for a few years
now&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://microservices.io/index.html&quot;&gt;Microservices Architecture&lt;/a&gt; website
is a great resource and has a page on the &lt;a href=&quot;https://microservices.io/patterns/data/transactional-outbox.html&quot;&gt;Transactional
Outbox&lt;/a&gt;
pattern. For an overview of Ports And Adapters, Alistair&#39;s &lt;a href=&quot;https://alistair.cockburn.us/hexagonal-architecture&quot;&gt;original
article&lt;/a&gt; is still well
worth the read.&lt;/p&gt;
&lt;p&gt;For more on CAP design and philosophy, see the blog posts (and videos) in &lt;a href=&quot;https://qmacro.org/blog/posts/2024/12/06/the-art-and-science-of-cap/&quot;&gt;The
Art and Science of
CAP&lt;/a&gt; series with Daniel
Hutzel himself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Local-first dev with CAP Node.js - mocking messaging</title>
    <link href="https://qmacro.org/blog/posts/2026/05/15/local-first-dev-with-cap-node-js-mocking-messaging/" />
    <updated>2026-05-15T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/05/15/local-first-dev-with-cap-node-js-mocking-messaging/</id>
    <content type="html">&lt;p&gt;This post is one of &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;a series on local-first development with CAP
Node.js&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;everything-is-an-event&quot;&gt;Everything is an event&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://qmacro.org/blog/posts/2024/11/07/five-reasons-to-use-cap/&quot;&gt;Five reasons to use CAP&lt;/a&gt;,
we see that &lt;a href=&quot;https://qmacro.org/blog/posts/2024/11/07/five-reasons-to-use-cap/#:~:text=%22Everything%20is%20an%20event%22&quot;&gt;everything is an
event&lt;/a&gt;.
Whether synchronous, such as via HTTP requests and responses for OData
operations, or asynchronous, where messages are emitted and received for
decoupled service-to-service communications.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/messaging&quot;&gt;Messaging&lt;/a&gt; topic in Capire
has a great overview and an explanation of all the different message brokers
that can be used. And there&#39;s one that is well suited for local-first
development: &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/messaging#file-based&quot;&gt;File
based&lt;/a&gt; messaging.&lt;/p&gt;
&lt;h2 id=&quot;working-through-an-example&quot;&gt;Working through an example&lt;/h2&gt;
&lt;p&gt;In this post, we&#39;ll work through an example of mocking messaging using the
file-based facility, with content in the
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development/tree/main/messaging&quot;&gt;messaging/&lt;/a&gt;
directory of the repo set up for the related
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/#talk&quot;&gt;talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The setup is a little different to the other mock examples in this series.
First, there are two CAP services that will be in play. Second, neither of them
have any entity definitions; in fact, only one has a CDS model at all, and that
only has a service definition with an action and an event defined within it.&lt;/p&gt;
&lt;h3 id=&quot;the-containing-project-definition&quot;&gt;The containing project definition&lt;/h3&gt;
&lt;p&gt;Usually in an asynchronous event scenario there is an emitter and a receiver,
and that&#39;s what we have here. They&#39;re both found within the &lt;code&gt;messaging/&lt;/code&gt;
directory, which is the containing project for this example, and has been set
up to use the Node.js
&lt;a href=&quot;https://docs.npmjs.com/cli/v11/using-npm/workspaces&quot;&gt;workspaces&lt;/a&gt; concept, with
this as the definition in &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@qmacro/messaging&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;workspaces&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;examining-the-emitter&quot;&gt;Examining the emitter&lt;/h3&gt;
&lt;p&gt;Within the &lt;code&gt;emitter/&lt;/code&gt; subdirectory we have a CAP project which has been put
together in the form of a package (like a
&lt;a href=&quot;https://qmacro.org/blog/posts/2024/12/30/cap-node-js-plugins/&quot;&gt;plugin&lt;/a&gt; would be). The name
declared in &lt;code&gt;emitter/package.json&lt;/code&gt; is &lt;code&gt;@qmacro/emitter&lt;/code&gt; and as well as the content in
&lt;code&gt;srv/&lt;/code&gt; there&#39;s also a project root level &lt;code&gt;emitter/index.js&lt;/code&gt; which acts as the package
entry point and contains:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;using &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./srv/main&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;the-emitter-service-definition&quot;&gt;The emitter service definition&lt;/h4&gt;
&lt;p&gt;This emitter is where the service definition is found, which looks like this,
in &lt;code&gt;emitter/srv/main.cds&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; org.qmacro.emitter;

&lt;span class=&quot;token annotation important&quot;&gt;@rest&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; EmitterService {
  &lt;span class=&quot;token keyword&quot;&gt;action&lt;/span&gt; greet(greeting: &lt;span class=&quot;token type builtin&quot;&gt;String&lt;/span&gt;) &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;token type builtin&quot;&gt;String&lt;/span&gt;;

  &lt;span class=&quot;token keyword&quot;&gt;event&lt;/span&gt; Greeting.Received {
    info : &lt;span class=&quot;token type builtin&quot;&gt;String&lt;/span&gt;;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The service defines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an action endpoint &lt;code&gt;greet&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;an event &lt;code&gt;Greeting.Received&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that while the term &amp;quot;action&amp;quot; has loaded meaning in the context of OData,
it also serves to define a POST based &amp;quot;RPC&amp;quot; style target that is valid even
in the context of the &amp;quot;REST&amp;quot; protocol, as declared here. The design of the
event and also the signature of the action endpoint is deliberately as simple
as possible for this example.&lt;/p&gt;
&lt;p&gt;As we&#39;ll see shortly, to have an event be emitted in this example scenario, we
need to make an HTTP POST request to the &lt;code&gt;/greet&lt;/code&gt; endpoint, with a payload body
containing the greeting data.&lt;/p&gt;
&lt;h4 id=&quot;the-emitter-service-implementation&quot;&gt;The emitter service implementation&lt;/h4&gt;
&lt;p&gt;Every action definition needs an implementation, and this is what we have in
&lt;code&gt;emitter/srv/main.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;@sap/cds&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; log &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;emitter&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;greet&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; emitter &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;org.qmacro.emitter.EmitterService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;emitting Greeting.Received (&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;greeting&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; emitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Greeting.Received&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;greeting &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;OK&#39;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that&#39;s pretty much it!&lt;/p&gt;
&lt;h3 id=&quot;messaging-configuration&quot;&gt;Messaging configuration&lt;/h3&gt;
&lt;p&gt;But upon what messaging mechanism are we relying here? Well, that&#39;s defined as
a requirement in the emitter&#39;s &lt;code&gt;emitter/package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@qmacro/emitter&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;requires&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      ...
      &lt;span class=&quot;token property&quot;&gt;&quot;messaging&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file-based-messaging&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value &lt;code&gt;file-based-messaging&lt;/code&gt; is what we want here, as described in &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/messaging#file-based&quot;&gt;the
corresponding Capire
section&lt;/a&gt; where it
tells us that a file is used as the message broker; that is, the emitter writes
messages to the file, and the receiver reads (and then removes) messages from
that file.&lt;/p&gt;
&lt;p&gt;By default the file is &lt;code&gt;~/.cds-msg-box&lt;/code&gt;. This fits with the general approach of
using hidden files in the developer&#39;s home directory (&lt;code&gt;~/.cds-services.json&lt;/code&gt; is
another example), emphasising the point that this is design-time only, i.e.
only for used in a local development context.&lt;/p&gt;
&lt;h3 id=&quot;examining-the-receiver&quot;&gt;Examining the receiver&lt;/h3&gt;
&lt;p&gt;The receiver in this setup is even simpler. It relies upon the emitter package,
and defines it as a required service, in &lt;code&gt;receiver/package.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@qmacro/receiver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;@qmacro/emitter&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;*&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;requires&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      ...
      &lt;span class=&quot;token property&quot;&gt;&quot;EmitterService&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;service&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;org.qmacro.emitter.EmitterService&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@qmacro/emitter&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;messaging&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;kind&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file-based-messaging&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like the emitter, it also defines a requirement on &lt;code&gt;file-based-messaging&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;the-receiver-implementation&quot;&gt;The receiver implementation&lt;/h4&gt;
&lt;p&gt;There&#39;s no CDS model in this simple receiver setup, just an implementation that
is in the form of a &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/cds-server#override-cds-server&quot;&gt;custom
server&lt;/a&gt; in
&lt;code&gt;receiver/server.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;@sap/cds&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; log &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;receiver&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eventID &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Greeting.Received&#39;&lt;/span&gt;

cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;served&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Setting up listener for &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;eventID&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; EmitterService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;EmitterService&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  EmitterService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;eventID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;received:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the CAP server has started up, a connection to the emitter service is made
and a handler is registered for the &lt;code&gt;Greeting.Received&lt;/code&gt; event.&lt;/p&gt;
&lt;p&gt;And that&#39;s all we need!&lt;/p&gt;
&lt;h3 id=&quot;trying-it-out&quot;&gt;Trying it out&lt;/h3&gt;
&lt;p&gt;We can try the entire construct out step by step to see what&#39;s going on. All
the following invocations are based on being in the &lt;code&gt;messaging/&lt;/code&gt; project root
directory.&lt;/p&gt;
&lt;p&gt;Before we start, we&#39;ll install the dependencies from the project root with:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;starting-up-the-emitter&quot;&gt;Starting up the emitter&lt;/h4&gt;
&lt;p&gt;Now, let&#39;s start the emitter up, and we&#39;ll specify &lt;code&gt;DEBUG&lt;/code&gt; level for the
&lt;code&gt;queue&lt;/code&gt; component(s) for a more detailed insight as to what happens:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;queue cds &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt; emitter&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We should see some familiar log output (some lines have been omitted for
brevity):&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Using non&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;scheduling&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;based event queue processing
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to messaging &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;based&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;messaging
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;qmacro&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;emitter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EmitterService &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/rest/emitter&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;emitter/srv/main.cds:4&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;impl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;emitter/srv/main.js&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:4006&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;file-based-messaging&lt;/code&gt; mechanism is brought into play, just before our
emitter service is served.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Port 4006 is selected by means of the value in &lt;code&gt;emitter/.env&lt;/code&gt;; it has no
special significance, except that it&#39;s one of a few ports (4004-4006 and
9229) that I publish in my dev container in which I do all my work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The service is registered in the local development binding registry
&lt;code&gt;~/.cds-services.json&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;org.qmacro.emitter.EmitterService&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;endpoints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;rest&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/rest/emitter&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35678&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;35678&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        ...
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we&#39;ve seen in another blog post in this series, on &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/&quot;&gt;mocking remote
services&lt;/a&gt;,
this registry serves to provide information on services provided and required.&lt;/p&gt;
&lt;h4 id=&quot;invoking-the-greet-action&quot;&gt;Invoking the greet action&lt;/h4&gt;
&lt;p&gt;Normally at this point it would make sense to start up the receiver, to have
the fully coordinated asynchronous setup. But we want to see things happen step
by step, and if we were to start the receiver now, any message generated and
emitted would be immediately consumed and we wouldn&#39;t see it &amp;quot;in transit&amp;quot;.&lt;/p&gt;
&lt;p&gt;So at this point we&#39;ll invoke the &lt;code&gt;greet&lt;/code&gt; action that the emitter exposes, to
have a message emitted.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;localhost:4006/rest/emitter/greet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--data&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;{&quot;greeting&quot;:&quot;Understanding is everything!&quot;}&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From this, we get a simple &lt;code&gt;OK&lt;/code&gt;, as we&#39;d expect from the &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/15/local-first-dev-with-cap-node-js-mocking-messaging/#the-emitter-service-implementation&quot;&gt;emitter service
implementation&lt;/a&gt;. More interesting is what
we see in the server log:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;rest&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; POST &lt;span class=&quot;token file-path string&quot;&gt;/rest/emitter/greet&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;emitter&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; emitting Greeting&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Received &lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;Understanding is everything&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;persistent&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Write message to queue
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;persistent&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Fetch messages
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;persistent&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Process &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; message
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;persistent&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Messages modified &lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;persistent&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Done&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While the &lt;code&gt;[rest]&lt;/code&gt; log record is just recording the incoming POST request, and
the &lt;code&gt;[emitter]&lt;/code&gt; log record was written by the emitter implementation (see
above), most notably we see the core messaging mechanism in action, handling the
queuing of the message. After all, queueing is a core part of everything that
is asynchronous.&lt;/p&gt;
&lt;h4 id=&quot;looking-at-the-message-queue&quot;&gt;Looking at the message queue&lt;/h4&gt;
&lt;p&gt;As we know, the &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/messaging#file-based&quot;&gt;file based messaging&lt;/a&gt; uses &lt;code&gt;~/.cds-msg-box&lt;/code&gt; by default as the queue. And if we look at that right now:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; ~/.cds-msg-box&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we see the message, &amp;quot;in transit&amp;quot;, as it were (formatted here for easier reading):&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;org.qmacro.emitter.EmitterService.Greeting.Received {
  &quot;data&quot;: {
    &quot;info&quot;: &quot;Understanding is everything!&quot;
  },
  &quot;headers&quot;: {
    &quot;x-correlation-id&quot;: &quot;80f83122-ecb7-49aa-8cdd-c465e2588374&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Half-way there!&lt;/p&gt;
&lt;h4 id=&quot;starting-up-the-receiver&quot;&gt;Starting up the receiver&lt;/h4&gt;
&lt;p&gt;Now we&#39;ve had a chance to examine the queue, we can start up the receiver:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt; receiver&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; bootstrapping from &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;receiver/server.js&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Using non&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;scheduling&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;based event queue processing
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to messaging &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;based&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;messaging
&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;receiver&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Setting up listener for Greeting&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Received
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:4005&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And directly following this, we see:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;receiver&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; received&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Greeting&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Received &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; info&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Understanding is everything!&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not only that, but the queued message in &lt;code&gt;~/.cds-msg-box&lt;/code&gt; is now gone. Consumed!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Asynchronous messaging is yet another fundamentally important aspect of real
life service design, delivery and orchestration, and we have no reason to put
off designing and building that in our projects, as we can incorporate local
mocking from the very start.&lt;/p&gt;
&lt;p&gt;By the way, for automated tests, you might even want to look at &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/messaging#local-messaging&quot;&gt;local
messaging&lt;/a&gt; which
takes place in-process, a little bit like in-process remote-service mocking,
and is very useful for automated testing.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Local-first dev with CAP Node.js - mocking remote services</title>
    <link href="https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/" />
    <updated>2026-05-13T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/</id>
    <content type="html">&lt;p&gt;This post is one of &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;a series on local-first development with CAP
Node.js&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;calesi-and-mocking-remote-services&quot;&gt;Calesi and mocking remote services&lt;/h2&gt;
&lt;p&gt;In the context of &lt;a href=&quot;https://cap.cloud.sap/docs/guides/integration/calesi&quot;&gt;CAP-Level Service
Integration&lt;/a&gt; (aka
&amp;quot;Calesi&amp;quot;) we can mash up remote and local services, and in the full spirit of
CAP generally, run everything &lt;a href=&quot;https://cap.cloud.sap/docs/guides/integration/calesi#mocked-out-of-the-box&quot;&gt;in airplane
mode&lt;/a&gt;,
i.e. fully locally.&lt;/p&gt;
&lt;h2 id=&quot;working-through-an-example&quot;&gt;Working through an example&lt;/h2&gt;
&lt;p&gt;In this post, we&#39;ll work through an example of mocking a remote service, based
on content in the
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development/tree/main/remoteservice&quot;&gt;remoteservice/&lt;/a&gt;
directory of the repo set up for the related
&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/#talk&quot;&gt;talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We start with an almost empty project directory, save for a basic
&lt;code&gt;package.json&lt;/code&gt; file which we only really have at this point so we can check the
changes in it that are introduced when we import a remote service API
definition. All operations are done in the context of this project directory.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The other files in this directory in the repo are related to performing and
resetting the demo during the talk version of this post.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;examining-and-importing-the-candidate-remote-service&quot;&gt;Examining and importing the candidate remote service&lt;/h2&gt;
&lt;p&gt;At &lt;a href=&quot;https://odd.cfapps.eu10.hana.ondemand.com/&quot;&gt;https://odd.cfapps.eu10.hana.ondemand.com/&lt;/a&gt; there&#39;s the
&lt;a href=&quot;https://odd.cfapps.eu10.hana.ondemand.com/northbreeze&quot;&gt;northbreeze&lt;/a&gt; OData V4
service with Products, Categories and Suppliers&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. The
service&#39;s API is available as the &lt;a href=&quot;https://odd.cfapps.eu10.hana.ondemand.com/northbreeze/$metadata&quot;&gt;metadata
document&lt;/a&gt; so
let&#39;s grab that:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://odd.cfapps.eu10.hana.ondemand.com/northbreeze/$metadata&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; northbreeze.edmx&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and use &lt;a href=&quot;https://cap.cloud.sap/docs/guides/services/consuming-services#import-api-definition&quot;&gt;cds
import&lt;/a&gt;
to import it to our project:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; northbreeze.edmx&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This emits:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; updated &lt;span class=&quot;token file-path string&quot;&gt;./package.json&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; imported API to srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; use it in your CDS models through the likes of&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

using &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; northbreeze as external &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt; from &lt;span class=&quot;token string&quot;&gt;&#39;./external/northbreeze&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and the EDMX API definition, along with the CAP-focused CSN equivalent that was
created at import, are moved into an &lt;code&gt;external/&lt;/code&gt; directory within a standard
&lt;code&gt;srv/&lt;/code&gt; directory (which itself is
&lt;a href=&quot;https://en.wikipedia.org/wiki/Autovivification&quot;&gt;autovivified&lt;/a&gt; at this point):&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;
├── &lt;span class=&quot;token domain constant&quot;&gt;package.json&lt;/span&gt;
└── srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;
    └── external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;
        ├── &lt;span class=&quot;token domain constant&quot;&gt;northbreeze.csn&lt;/span&gt;
        └── &lt;span class=&quot;token domain constant&quot;&gt;northbreeze.edmx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;mocking-is-automatically-and-immediately-initiated&quot;&gt;Mocking is automatically and immediately initiated&lt;/h3&gt;
&lt;p&gt;At this point too, the CAP server restarts and shows:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; loaded model from &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

  srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csn

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; mocking northbreeze &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/northbreeze&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/external/northbreeze.csn:170&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:4004&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is because &lt;code&gt;cds watch&lt;/code&gt; is actually shorthand for:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds serve all --with-mocks --in-memory?&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and if we read the help for &lt;code&gt;--with-mocks&lt;/code&gt; we see this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Use this in combination with the variants serving multiple services.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;It starts in-process mock services for all required services configured in
package.json#cds.requires, which don&#39;t have external bindings in the current
process environment.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that by default, this feature is disabled in production and must be
enabled with configuration &#39;features.mocked_bindings=true&#39;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That&#39;s right - mocking is already being done for our imported remote service!
It&#39;s in-process, i.e. within the same CAP server process that we started with
&lt;code&gt;cds watch&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-package-json-file-is-extended&quot;&gt;The package.json file is extended&lt;/h3&gt;
&lt;p&gt;As part of the import process, &lt;code&gt;package.json&lt;/code&gt; was modified in two key areas:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token coord&quot;&gt;--- a/remoteservice/package.json&lt;/span&gt;
&lt;span class=&quot;token coord&quot;&gt;+++ b/remoteservice/package.json&lt;/span&gt;
&lt;span class=&quot;token coord&quot;&gt;@@ -4,7 +4,10 @@&lt;/span&gt;
&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &quot;description&quot;: &quot;Demonstrating local-first support for remote services&quot;,
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &quot;dependencies&quot;: {
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &quot;@sap/cds&quot;: &quot;^9&quot;,
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;    &quot;express&quot;: &quot;^4&quot;
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &quot;express&quot;: &quot;^4&quot;,
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &quot;@sap-cloud-sdk/connectivity&quot;: &quot;^4&quot;,
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &quot;@sap-cloud-sdk/http-client&quot;: &quot;^4&quot;,
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &quot;@sap-cloud-sdk/resilience&quot;: &quot;^4&quot;
&lt;/span&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  },
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &quot;devDependencies&quot;: {
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &quot;@cap-js/sqlite&quot;: &quot;^2&quot;
&lt;/span&gt;&lt;span class=&quot;token coord&quot;&gt;@@ -12,5 +15,13 @@&lt;/span&gt;
&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  &quot;scripts&quot;: {
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;    &quot;start&quot;: &quot;cds-serve&quot;
&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;  },
&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;  &quot;private&quot;: true
&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;}
&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &quot;private&quot;: true,
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  &quot;cds&quot;: {
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    &quot;requires&quot;: {
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;      &quot;northbreeze&quot;: {
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &quot;kind&quot;: &quot;odata&quot;,
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;        &quot;model&quot;: &quot;srv/external/northbreeze&quot;
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;      }
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;    }
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;  }
&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;the SAP Cloud SDK libraries were added - for marshalling of, connection to and
communication with remote destinations&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the remote service is added as &amp;quot;required&amp;quot;, with the name &lt;code&gt;northbreeze&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;reviewing-the-situation&quot;&gt;Reviewing the situation&lt;/h2&gt;
&lt;p&gt;This in-process mocking of the required remote service &amp;quot;northbreeze&amp;quot; means that
in the CAP server context that exists for our project, we have that remote
service as an endpoint available to us at &lt;a href=&quot;http://localhost:4004&quot;&gt;http://localhost:4004&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://qmacro.org/images/2026/05/northbreeze-available.png&quot; alt=&quot;northbreeze remote service available&quot;&gt;&lt;/p&gt;
&lt;p&gt;But while the mocked remote service is already fully formed, even in this
&amp;quot;in-process&amp;quot; mode, there&#39;s no data. Let&#39;s add some so we can better explore the
service.&lt;/p&gt;
&lt;h2 id=&quot;add-data-for-the-mocked-remote-service&quot;&gt;Add data for the mocked remote service&lt;/h2&gt;
&lt;p&gt;Using CAP&#39;s mock data facilities, we can easily come up
with some mock data. Because of CAP&#39;s &lt;a href=&quot;https://github.com/qmacro/capref/blob/main/axioms/AXI003.md&quot;&gt;convention over
configuration&lt;/a&gt;
axiom, this works even for mocked remote services. As an erstwhile Perl
programmer, I appreciate this
&lt;a href=&quot;https://perldoc.perl.org/perlsyn#DESCRIPTION:~:text=This%20is%20known%20as%20Do%20What%20I%20Mean%2C%20abbreviated%20DWIM.&quot;&gt;DWIM&lt;/a&gt;-style approach.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To dig in more to the mock data facilities in CAP, see the &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/blog/posts/2026/05/11/local-first-dev-with-cap-node-js-mocking-data/&quot;&gt;mocking
data&lt;/a&gt;
blog post in this series.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;have-some-data-generated&quot;&gt;Have some data generated&lt;/h3&gt;
&lt;p&gt;Let&#39;s first have CAP generate some data for us:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; data &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--filter&lt;/span&gt; Categories &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--records&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a CSV file with an appropriate name and in the expected place for
initial data:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;./
├── db/
│   └── data/
│       └── northbreeze.Categories.csv
├── package.json
└── srv/
    └── external/
        ├── northbreeze.csn
        └── northbreeze.edmx&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;retrieve-data-and-use-that-too&quot;&gt;Retrieve data and use that too&lt;/h3&gt;
&lt;p&gt;Given this is about gathering some data to exercise the mocked remote service,
it&#39;s likely that the actual remote service has data that we can perhaps use
too.&lt;/p&gt;
&lt;p&gt;Being an OData V4 service, the data available, in the form of, say, an
entityset, is going to be in JSON format by default. But that&#39;s fine, the CAP
server&#39;s data mechanism can deal with this too. So let&#39;s grab the Products data
from the actual remote service and place it alongside the Categories data we
have:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--silent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://odd.cfapps.eu10.hana.ondemand.com/northbreeze/Products&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; jq .value &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; db/data/northbreeze.Products.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can mix CSV and JSON data with ease:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;./
├── db/
│   └── data/
│       └── northbreeze.Categories.csv
:       └── northbreeze.Products.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it&#39;s picked up as we would hope:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from db&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Products&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from db&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Categories&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;move-the-data-closer-to-the-service&quot;&gt;Move the data closer to the service&lt;/h3&gt;
&lt;p&gt;While the data for this mocked external required service is perfectly fine in
&lt;code&gt;db/data/&lt;/code&gt; and is picked up as we&#39;d expect, perhaps it makes more sense to keep
it closer to the service definition, as a &amp;quot;bundle&amp;quot;, as it were. That will work
too, with respect to the automatic data loading mechanism, so let&#39;s do that:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; db/data/ srv/external/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the external service is more self-contained:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;./
├── db/
├── package.json
└── srv/
    └── external/
        ├── data/
        │   ├── northbreeze.Categories.csv
        │   └── northbreeze.Products.json
        ├── northbreeze.csn
        └── northbreeze.edmx&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;switching-to-a-more-realistic-scenario&quot;&gt;Switching to a more realistic scenario&lt;/h2&gt;
&lt;p&gt;There are a couple of aspects we should look at now, based on the very simple
setup we have so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the required remote service has been mocked in-process; ideally we want a
local development scenario that is closer to the eventual production
situation&lt;/li&gt;
&lt;li&gt;it is also entirely independent, unrelated to any local service definitions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Regarding the first aspect, we can also have a service mocked in a separate
process, instead of being mocked in-process. One effect of this is that real
wire API calls are made between your local service and the separately mocked
(but still locally running) remote service.&lt;/p&gt;
&lt;p&gt;Regarding the second aspect, we&#39;ll set up a local to remote proxy definition in
our CDS model, for an entity. We&#39;ll do that first staying with in-process
mocking, and then switch to separate process based mocking.&lt;/p&gt;
&lt;h3 id=&quot;set-up-a-local-to-remote-proxy-definition&quot;&gt;Set up a local to remote proxy definition&lt;/h3&gt;
&lt;p&gt;One of the simplest forms of service mashup is surfacing a remote entity as a
local one. This may not be entirely useful, but it demonstrates the atomic
structure of more involved scenarios, and is nice and simple so as not to get
in the way of understanding here.&lt;/p&gt;
&lt;p&gt;First, add the following service definition in &lt;code&gt;srv/main.cds&lt;/code&gt;, remembering that
the &lt;code&gt;using&lt;/code&gt; directive here brings in the &lt;code&gt;northbreeze&lt;/code&gt; scope from the imported
remote service definition that was created with the &lt;code&gt;cds import&lt;/code&gt; earlier:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; {northbreeze} &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;./external/northbreeze&#39;;

&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; Main {
  &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Products &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; northbreeze.Products;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the following sections, we&#39;ll see the difference between in-process and
external process mocking.&lt;/p&gt;
&lt;h3 id=&quot;examine-the-cap-server-logs-now&quot;&gt;Examine the CAP server logs now&lt;/h3&gt;
&lt;p&gt;Once the CAP server restarts, take a look at the log output:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; loaded model from &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; file&lt;span class=&quot;token operator&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token operator&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

  srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cds
  srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csn

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Products&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Categories&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving Main &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/main&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/main.cds:3&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; mocking northbreeze &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/northbreeze&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/external/northbreeze.csn:170&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we see is very useful and helps augment our understanding:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the overall CDS model is built from the local definition we&#39;ve just created,
plus the definitions from the remote service&lt;/li&gt;
&lt;li&gt;initial data is being loaded from the CSV and JSON files&lt;/li&gt;
&lt;li&gt;the local &lt;em&gt;provided&lt;/em&gt; service &lt;code&gt;Main&lt;/code&gt; is served&lt;/li&gt;
&lt;li&gt;the remote &lt;em&gt;required&lt;/em&gt; service &lt;code&gt;northbreeze&lt;/code&gt; is also served, mocked in-process&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Moreover, when we request a &lt;code&gt;Products&lt;/code&gt; resource from the local &lt;code&gt;Main&lt;/code&gt; service
at &lt;code&gt;/odata/v4/main&lt;/code&gt;, which as we know from our service definition is a
projection onto the corresponding entity in the remote service definition:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/odata/v4/main/Products?$top=1&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;we get a successful result:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;@odata.context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;$metadata#Products&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ProductID&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ProductName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chai&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;QuantityPerUnit&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10 boxes x 20 bags&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;UnitPrice&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Category_CategoryID&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Supplier_SupplierID&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;UnitsInStock&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;39&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;UnitsOnOrder&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;ReorderLevel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;Discontinued&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is due to the in-process based connectivity available in the single CAP
server process.&lt;/p&gt;
&lt;p&gt;Let&#39;s stop the CAP server at this point.&lt;/p&gt;
&lt;h3 id=&quot;mock-the-remote-service-in-a-separate-process&quot;&gt;Mock the remote service in a separate process&lt;/h3&gt;
&lt;p&gt;In a second terminal window, let&#39;s now start the standalone mocking of the
required &lt;code&gt;northbreeze&lt;/code&gt; service with the &lt;code&gt;cds mock&lt;/code&gt;
command&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/#footnotes&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;, like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds mock northbreeze&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We should see output like this:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; database&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Products&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json
  &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; init from srv&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;external&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;data&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Categories&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;csv
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; mocking northbreeze &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/northbreeze&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/external/northbreeze.csn:170&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:42623&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The initial data is loaded as before, the &lt;code&gt;northbreeze&lt;/code&gt; service is served, but
crucially:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the provided &lt;code&gt;Main&lt;/code&gt; service is not served (as we haven&#39;t asked it to be)&lt;/li&gt;
&lt;li&gt;the required &lt;code&gt;northbreeze&lt;/code&gt; service is available on a non-standard (in fact
random) port 42623&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can successfully request resources in this mocked remote service at
&lt;code&gt;http://localhost:42623/odata/v4/northbreeze&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;start-a-normal-cap-server-process-to-have-the-local-service-served&quot;&gt;Start a normal CAP server process to have the local service served&lt;/h3&gt;
&lt;p&gt;Now in the first terminal window, let&#39;s restart the CAP server with &lt;code&gt;cds watch&lt;/code&gt;, and we should now see:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to db &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; sqlite &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;:memory:&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; successfully deployed to in&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;memory database&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving Main &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/odata/v4/main&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/main.cds:3&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; server listening on &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:4004&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, there&#39;s no initial data loaded, because that belongs to the required
remote &lt;code&gt;northbreeze&lt;/code&gt; service and thus not relevant here, because only the
&lt;code&gt;Main&lt;/code&gt; service is being served.&lt;/p&gt;
&lt;p&gt;Why is only the provided &lt;code&gt;Main&lt;/code&gt; service being served, and not the required
remote &lt;code&gt;northbreeze&lt;/code&gt; service, like before?&lt;/p&gt;
&lt;h3 id=&quot;get-to-know-the-binding-registry&quot;&gt;Get to know the binding registry&lt;/h3&gt;
&lt;p&gt;To answer that question, we need to recall that highlighted part of the help
for the mocking option to &lt;code&gt;cds serve&lt;/code&gt; earlier:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It starts in-process mock services for all required services configured in
package.json#cds.requires, &lt;strong&gt;which don&#39;t have external bindings in the current
process environment&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here, in our local-first development context, our &amp;quot;current process environment&amp;quot;
is effectively any (and all) CAP server process(es) running locally.&lt;/p&gt;
&lt;p&gt;You might have noticed this line appearing in previous CAP server output
samples in this post:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using bindings from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; registry&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;~/.cds-services.json&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As they start up and shut down, local CAP server processes read and write to
this registry file &lt;code&gt;~/.cds-services.json&lt;/code&gt;. They read it to see what services
are available (that they might be requiring), and write to it to record the
services they&#39;re providing (for other locally running CAP server processes).&lt;/p&gt;
&lt;p&gt;When we started the separate CAP server to mock the &lt;code&gt;northbreeze&lt;/code&gt; remote
service with &lt;code&gt;cds mock northbreeze&lt;/code&gt;, information was written to this file,
recording the fact that this &lt;code&gt;northbreeze&lt;/code&gt; service is &amp;quot;provided&amp;quot;:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;provides&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;northbreeze&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;endpoints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;odata&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/odata/v4/northbreeze&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;17250&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;servers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;17250&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;file:///work/gh/github.com/qmacro/cap-nodejs-local-first-development/remoteservice&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://localhost:42623&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, it also records where the provision is, in this case at
&lt;code&gt;http://localhost:42623&lt;/code&gt;, which is at the port that the mock server is
listening on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is why a random port is not such a problem here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;retry-the-local-to-remote-proxy-part-1&quot;&gt;Retry the local to remote proxy - part 1&lt;/h3&gt;
&lt;p&gt;Now that we have two CAP server processes running, one mocking the required
remote service &lt;code&gt;northbreeze&lt;/code&gt;, and the other serving the local service &lt;code&gt;Main&lt;/code&gt;,
let&#39;s retry that same request (to get the product data from the mocked remote
service, proxied through the local service definition):&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/odata/v4/main/Products?$top=1&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh dear:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Entity &#92;&quot;Main.Products&#92;&quot; is annotated with &#92;&quot;@cds.persistence.skip&#92;&quot; and cannot be served generically.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;501&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;@Common.numericSeverity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The in-process connectivity available (provided for convenience) cannot be used
here, and we have to implement some basic query and connectivity logic which is
exactly what we will have to do in a productive scenario anyway.&lt;/p&gt;
&lt;p&gt;So let&#39;s do that, using the simplest thing that could possibly work - adding
this to a corresponding &lt;code&gt;srv/main.js&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cds &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;@sap/cds&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;service&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;impl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; northbreeze &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; cds&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;connect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;northbreeze&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;READ&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Products&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; northbreeze&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;req&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a query arrives to read &lt;code&gt;Products&lt;/code&gt; data, send it across to &lt;code&gt;northbreeze&lt;/code&gt;
and pass back whatever is returned.&lt;/p&gt;
&lt;p&gt;Once the CAP server in the first terminal window restarts because of this
change, note that there&#39;s a new log line in the output:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; connect to northbreeze &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; odata &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; url&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;http://localhost:42623/odata/v4/northbreeze&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a direct result of the &lt;code&gt;await cds.connect.to(&#39;northbreeze&#39;)&lt;/code&gt; line
above.&lt;/p&gt;
&lt;h3 id=&quot;retry-the-local-to-remote-proxy-part-2&quot;&gt;Retry the local to remote proxy - part 2&lt;/h3&gt;
&lt;p&gt;With this simple implementation in place, retrying that same request again will
result in some very satisfying log output in both CAP server processes.&lt;/p&gt;
&lt;p&gt;Before we do, stop the CAP server in the first terminal window and restart it
specifying &lt;code&gt;DEBUG=remote&lt;/code&gt; like this, to get more log output detail for remote
related activities:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;remote cds &lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, after retrying the request for a final time, we see this log output in the
first (&lt;code&gt;Main&lt;/code&gt;) CAP server log output:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;remote&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; GET &lt;span class=&quot;token url&quot;&gt;http://localhost:42623/odata/v4/northbreeze/Products?$select=ProductID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;ProductName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;QuantityPerUnit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;UnitPrice&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Category_CategoryID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Supplier_SupplierID&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;UnitsInStock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;UnitsOnOrder&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;ReorderLevel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;Discontinued&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;top&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;headers:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;accept:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;application/json,text/plain&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;x-correlation-id&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ff4da315-ec6e-4e89-97d4-85f96b270ed6&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&#39;x-correlationid&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ff4da315-ec6e-4e89-97d4-85f96b270ed6&#39;&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;remote&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; Executing via native fetch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that there&#39;s an HTTP request, specifically an OData QUERY operation,
that&#39;s been constructed and sent to the URL where the remote service is being
provided&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/13/local-first-dev-with-cap-node-js-mocking-remote-services/#footnotes&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And in the CAP server process in the second terminal window, where we&#39;re
separately mocking the &lt;code&gt;northbreeze&lt;/code&gt; remote service on 42623, we see that OData
QUERY operation arrive:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;odata&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; GET &lt;span class=&quot;token file-path string&quot;&gt;/odata/v4/northbreeze/Products&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&#39;$select&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ProductID,ProductName,QuantityPerUnit,UnitPrice,Category_CategoryID,Supplier_SupplierID,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&#39;$top&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;1&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A true inter-process remote service call. All running locally, and orchestrated
in the simplest way possible.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;This post has just scratched the surface of what&#39;s possible when it comes to
working in local-first development mode, with remote services. For more
information and stuff that you can practise yourself, we have the &lt;a href=&quot;https://github.com/SAP-samples/cap-service-integration-codejam/&quot;&gt;CAP Service
Integration
CodeJam&lt;/a&gt;
exercises publicly available for you. Happy learning!&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&amp;quot;odd&amp;quot; is short for OData Deep Dive, and the service is used in the
corresponding SAP Tutorial Navigator mission that I&#39;m rewriting currently -
see &lt;a href=&quot;https://qmacro.org/blog/posts/2026/02/02/odata-deep-dive-rewrite-in-the-open/&quot;&gt;OData Deep Dive rewrite in the
open&lt;/a&gt; for
details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Note that &lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/apr26#n-o-cloud-sdk&quot;&gt;since the CAP Apr 2026
release&lt;/a&gt;, the
SAP Cloud SDK is no longer mandatory for remote communication in
development scenarios.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;cds mock servicename&lt;/code&gt; is actually just shorthand for&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;cds serve &lt;span class=&quot;token parameter variable&quot;&gt;--mocked&lt;/span&gt; servicename --in-memory? &lt;span class=&quot;token parameter variable&quot;&gt;--port&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can also see, via the &amp;quot;Executing via native fetch&amp;quot; line, that the
&lt;a href=&quot;https://cap.cloud.sap/docs/releases/2026/apr26#node-native-fetch-api&quot;&gt;Node-native Fetch API is in use here now, since Apr
2026&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>Local-first dev with CAP Node.js - mocking auth</title>
    <link href="https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/" />
    <updated>2026-05-12T00:00:00Z</updated>
    <id>https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/</id>
    <content type="html">&lt;p&gt;This post is one of &lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/11/local-first-dev-with-cap-node-js/&quot;&gt;a series on local-first development with CAP
Node.js&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-mocked-authentication-strategy&quot;&gt;The mocked authentication strategy&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://cap.cloud.sap/docs/node.js/authentication#strategies&quot;&gt;Authentication
Strategies&lt;/a&gt;
section of the Node.js Security topic in Capire explains the different
strategies available, and the &amp;quot;mocked&amp;quot; strategy comes with pre-defined users
that can be used, with their various levels of authorisations, to explore,
define and test security-related constructs. This mock user configuration can
be modified and extended too, but what comes out of the box is definitely
enough to get started.&lt;/p&gt;
&lt;h2 id=&quot;working-through-an-example&quot;&gt;Working through an example&lt;/h2&gt;
&lt;p&gt;In this post, we&#39;ll work through an example of mocking auth, based
on content in the
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development/tree/main/auth&quot;&gt;auth/&lt;/a&gt;
directory of the talk repository.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that what&#39;s absent here is any form of auth implementation - all
declarations available are automatically enforced by CAP&#39;s generic service
providers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-service-definition&quot;&gt;The service definition&lt;/h3&gt;
&lt;p&gt;In
&lt;a href=&quot;https://github.com/qmacro/cap-nodejs-local-first-development/blob/main/auth/srv/main.cds&quot;&gt;srv/main.cds&lt;/a&gt;
there&#39;s a single service defined, with a couple of entities that are simple
projections on to the entities in the data model:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; northwind &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;../db/schema&#39;;

&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; Main {

  &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Products   &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; northwind.Products;
  &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Categories &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; northwind.Categories;

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Starting a CAP server in local development mode with &lt;code&gt;cds watch&lt;/code&gt; shows us that
the mocked authentication strategy is in play by default:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; using auth strategy &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt; kind&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mocked&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cds&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; serving Main &lt;span class=&quot;token operator&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;at:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/main&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;decl:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;srv/main.cds:4&#39;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we haven&#39;t yet addressed any auth requirements in our CDS model, access is
currently open to all, as we can see&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/#footnotes&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--include&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/main/Products?$top=1&#39;&lt;/span&gt;
HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
OData-Version: &lt;span class=&quot;token number&quot;&gt;4.0&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Content-Length: &lt;span class=&quot;token number&quot;&gt;105&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;@odata.context&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$metadata&lt;/span&gt;#BasicProducts&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chai&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;supplier&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Exotic Liquids&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;examine-the-pre-defined-users-and-their-authorisations&quot;&gt;Examine the pre-defined users and their authorisations&lt;/h3&gt;
&lt;p&gt;We can take a look at the pre-defined user data that is defined for the mocked
authentication strategy, with:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;cds &lt;span class=&quot;token function&quot;&gt;env&lt;/span&gt; requires.auth.users&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will emit something like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  alice&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t1&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;admin&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  bob&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t1&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;cds.ExtensionDeveloper&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  carol&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t1&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;admin&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &#39;cds.ExtensionDeveloper&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  dave&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t1&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;admin&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; features&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  erin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t2&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;admin&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &#39;cds.ExtensionDeveloper&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  fred&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t2&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; features&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;isbn&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  me&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tenant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;t1&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; features&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;*&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  yves&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; roles&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &#39;internal-user&#39; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &#39;*&#39;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;restrict-the-service&quot;&gt;Restrict the service&lt;/h3&gt;
&lt;p&gt;Let&#39;s annotate the service with some basic role based access control (RBAC)
requirements - that of needing to authenticate, via the pseudo-role
&lt;code&gt;authenticated-user&lt;/code&gt;. We can use the
&lt;a href=&quot;https://cap.cloud.sap/docs/guides/security/authorization#requires&quot;&gt;@requires&lt;/a&gt;
annotation:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; northwind &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;../db/schema&#39;;

&lt;span class=&quot;token annotation important&quot;&gt;@requires:&lt;/span&gt; &#39;authenticated-user&#39;
&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; Main {

  ...

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same &lt;code&gt;curl&lt;/code&gt; request as before now fails with an appropriate HTTP 401 status
code:&lt;/p&gt;
&lt;pre class=&quot;language-log&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-log&quot;&gt;HTTP&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;401&lt;/span&gt; Unauthorized
&lt;span class=&quot;token property&quot;&gt;WWW-Authenticate:&lt;/span&gt; Basic realm&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Users&quot;&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;Content-Type:&lt;/span&gt; text&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;plain&lt;span class=&quot;token operator&quot;&gt;;&lt;/span&gt; charset&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;token property&quot;&gt;Content-Length:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;

Unauthorized&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;authenticate-with-a-pre-defined-user&quot;&gt;Authenticate with a pre-defined user&lt;/h3&gt;
&lt;p&gt;We can re-try the request with one of the pre-defined
users&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/#footnotes&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;; because the requirement is just for the
pseudo-role &lt;code&gt;authenticated-user&lt;/code&gt;, we don&#39;t need any particular actual role
allocated to the user, we just need to be successfully authenticated (and so
identified) in this case:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--user&lt;/span&gt; alice: &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--include&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/main/Products?$top=1&#39;&lt;/span&gt;
HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
OData-Version: &lt;span class=&quot;token number&quot;&gt;4.0&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Content-Length: &lt;span class=&quot;token number&quot;&gt;105&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;@odata.context&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$metadata&lt;/span&gt;#BasicProducts&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;ID&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Chai&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;supplier&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Exotic Liquids&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;try-some-finer-grained-access-restrictions&quot;&gt;Try some finer-grained access restrictions&lt;/h3&gt;
&lt;p&gt;With the
&lt;a href=&quot;https://cap.cloud.sap/docs/guides/security/authorization#restrict-annotation&quot;&gt;@restrict&lt;/a&gt;
we can define finer grained access requirements&lt;a href=&quot;https://qmacro.org/blog/posts/2026/05/12/local-first-dev-with-cap-node-js-mocking-auth/#footnotes&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; in
privilege building blocks of this form:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; grant&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&amp;lt;events&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&amp;lt;roles&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; where&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&amp;lt;filter-condition&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&#39;s now add privilege requirements for the &lt;code&gt;Categories&lt;/code&gt; entity, like this:&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token using keyword&quot;&gt;using&lt;/span&gt; northwind &lt;span class=&quot;token from keyword&quot;&gt;from&lt;/span&gt; &#39;../db/schema&#39;;

&lt;span class=&quot;token annotation important&quot;&gt;@requires:&lt;/span&gt; &#39;authenticated-user&#39;
&lt;span class=&quot;token keyword&quot;&gt;service&lt;/span&gt; Main {

  &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Products   &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; northwind.Products;

  &lt;span class=&quot;token annotation important&quot;&gt;@restrict:&lt;/span&gt; [
    {
      grant: &#39;WRITE&#39;,
      to   : &#39;buyer&#39;
    },
    {
      grant: &#39;READ&#39;,
      to   : &#39;any&#39;
    }
  ]
  &lt;span class=&quot;token keyword&quot;&gt;entity&lt;/span&gt; Categories &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token cdl-keyword keyword&quot;&gt;projection&lt;/span&gt; &lt;span class=&quot;token cqlkeywords keyword&quot;&gt;on&lt;/span&gt; northwind.Categories;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This says that any (authenticated) user can read the categories, but only a
user with the &lt;code&gt;buyer&lt;/code&gt; role can perform &amp;quot;write&amp;quot;-semantic operations.&lt;/p&gt;
&lt;h3 id=&quot;confirm-read-operations-are-permitted&quot;&gt;Confirm read operations are permitted&lt;/h3&gt;
&lt;p&gt;Let&#39;s check that &amp;quot;read&amp;quot;-semantic operations are allowed for authenticated users
(remember that the entity access is also governed by the &lt;code&gt;authenticated-user&lt;/code&gt;
pseudo-role restriction on the service that contains it):&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--user&lt;/span&gt; alice: &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--include&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/main/Categories?$top=1&#39;&lt;/span&gt;
HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt; OK
OData-Version: &lt;span class=&quot;token number&quot;&gt;4.0&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Content-Length: &lt;span class=&quot;token number&quot;&gt;155&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;@odata.context&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$metadata&lt;/span&gt;#Categories&quot;&lt;/span&gt;,
  &lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;CategoryID&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;CategoryName&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Beverages&quot;&lt;/span&gt;,
      &lt;span class=&quot;token string&quot;&gt;&quot;Description&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Soft drinks, coffees, teas, beers, and ales&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks OK.&lt;/p&gt;
&lt;h3 id=&quot;try-a-write-operation&quot;&gt;Try a write operation&lt;/h3&gt;
&lt;p&gt;Now for a &amp;quot;write&amp;quot;-semantic operation. Let&#39;s go big and try DELETE:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--user&lt;/span&gt; alice: &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--include&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--request&lt;/span&gt; DELETE &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/main/Categories/1&#39;&lt;/span&gt;
HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;403&lt;/span&gt; Forbidden
OData-Version: &lt;span class=&quot;token number&quot;&gt;4.0&lt;/span&gt;
Content-Type: application/json&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;utf-8
Content-Length: &lt;span class=&quot;token number&quot;&gt;74&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;error&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Forbidden&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;code&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;403&quot;&lt;/span&gt;,
    &lt;span class=&quot;token string&quot;&gt;&quot;@Common.numericSeverity&quot;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alice, with the &lt;code&gt;admin&lt;/code&gt; role, is denied.&lt;/p&gt;
&lt;h3 id=&quot;give-the-user-more-access-in-the-mocked-strategy&quot;&gt;Give the user more access in the mocked strategy&lt;/h3&gt;
&lt;p&gt;We can also modify and add to the pre-defined user definitions for the mocked
authentication strategy. Let&#39;s do that, adding a couple of extra roles for
Alice in a separate &lt;code&gt;.cdsrc.json&lt;/code&gt; file in the project:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;cds&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;requires&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;auth&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;users&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token property&quot;&gt;&quot;alice&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token property&quot;&gt;&quot;roles&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
              &lt;span class=&quot;token string&quot;&gt;&quot;admin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token string&quot;&gt;&quot;buyer&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;token string&quot;&gt;&quot;head-office&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the roles is &lt;code&gt;buyer&lt;/code&gt;, so let&#39;s now retry the previous request:&lt;/p&gt;
&lt;pre class=&quot;language-shell&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--user&lt;/span&gt; alice: &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--include&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--request&lt;/span&gt; DELETE &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
  &lt;span class=&quot;token parameter variable&quot;&gt;--url&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;localhost:4004/main/Categories/1&#39;&lt;/span&gt;
HTTP/1.1 &lt;span class=&quot;token number&quot;&gt;204&lt;/span&gt; No Content
OData-Version: &lt;span class=&quot;token number&quot;&gt;4.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success!&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;With the mocked authentication strategy, we can embrace and work on the
important aspect of securing our app or service right from the very start. CAP
makes it easy to do the right things here.&lt;/p&gt;
&lt;p&gt;For more information, see the
&lt;a href=&quot;https://cap.cloud.sap/docs/node.js/authentication&quot;&gt;Authentication&lt;/a&gt; topic in
Capire.&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The JSON output in these examples has been pretty-printed for readability here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;--user&lt;/code&gt; option for &lt;code&gt;curl&lt;/code&gt; allows us to specify a username and password
separated by a colon, so &lt;code&gt;alice:&lt;/code&gt; here is just the username combined with an
empty password (there are no passwords for these users). If we&#39;d just
specified &lt;code&gt;--user alice&lt;/code&gt; without a colon, then &lt;code&gt;curl&lt;/code&gt; would have prompted
us for a password - we could have then just pressed Enter but this is one
step we can avoid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In fact, &lt;code&gt;@requires&lt;/code&gt; is just a convenience shortcut for &lt;code&gt;@restrict&lt;/code&gt;. The annotation&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token annotation important&quot;&gt;@requires:&lt;/span&gt; &#39;authenticated-user&#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;that we used earlier is equivalent to&lt;/p&gt;
&lt;pre class=&quot;language-cds&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-cds&quot;&gt;&lt;span class=&quot;token annotation important&quot;&gt;@restrict:&lt;/span&gt; [ { grant: &#39;*&#39;, to: &#39;authenticated-user&#39; } ]&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
</feed>