@jimhoyd/urlcode 0.4.0-alpha.3 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +20 -15
- package/ROADMAP.md +16 -11
- package/dist/BUILD-MANIFEST.json +16 -15
- package/dist/authoring.js +15 -1
- package/dist/capability-query.js +0 -1
- package/dist/catalog.js +0 -1
- package/dist/cli.js +23 -7
- package/dist/config.js +1 -1
- package/dist/explain.js +1 -1
- package/dist/http-response.js +1 -1
- package/dist/index.js +1 -0
- package/dist/init-with.js +36 -11
- package/dist/manifest.js +1 -1
- package/dist/mcp-authoring.js +2 -2
- package/dist/mcp.js +1 -1
- package/dist/policies/cache.js +2 -2
- package/dist/project-dependencies.js +305 -0
- package/dist/runtime.js +1 -1
- package/dist/trusted-functions.js +4 -5
- package/dist/types/authoring.d.ts +9 -1
- package/dist/types/capability-query.d.ts +0 -1
- package/dist/types/catalog.d.ts +0 -4
- package/dist/types/config.d.ts +1 -9
- package/dist/types/explain.d.ts +0 -1
- package/dist/types/http-response.d.ts +0 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/init-with.d.ts +7 -13
- package/dist/types/manifest.d.ts +0 -1
- package/dist/types/project-dependencies.d.ts +78 -0
- package/dist/types/trusted-functions.d.ts +1 -4
- package/docs/AI-AUTHORING.md +5 -1
- package/docs/AWS.md +9 -0
- package/docs/CI-FOLLOWUP-2026-09-19.md +1 -1
- package/docs/CODEBASE-AUDIT-2026-09-20.md +6 -0
- package/docs/COMPOSING-A-SITE.md +278 -0
- package/docs/DEVELOPMENT-PIPELINE.md +208 -119
- package/docs/EXTENSIONS.md +36 -6
- package/docs/FRAMEWORK.md +45 -30
- package/docs/INSTALL.md +13 -8
- package/docs/MIDDLEWARE.md +10 -4
- package/docs/OPEN-DECISIONS.md +46 -6
- package/docs/READINESS.md +4 -3
- package/docs/README.md +3 -4
- package/docs/RELEASE-0.4.1.md +73 -0
- package/docs/RELEASE-SECURITY.md +27 -12
- package/docs/SPECIFICATION.md +5 -1
- package/docs/SPIKE-CORE-LAYERING.md +1 -1
- package/docs/STARTERS.md +17 -5
- package/docs/TOOLING.md +6 -4
- package/docs/VERCEL.md +10 -2
- package/docs/VERSION-ALIGNMENT.md +42 -8
- package/docs/archive/2026-09-19/ROADMAP.md +1 -0
- package/docs/archive/2026-09-19/SPIKE-EXTENSION-MODEL.md +1 -0
- package/docs/{SPIKE-LAMBDA-COMPILE.md → archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md} +168 -12
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +2 -0
- package/docs/archive/README.md +1 -0
- package/docs/yaml/functions.md +10 -2
- package/docs/yaml/middleware.md +5 -3
- package/examples/cookbook/middleware/envelope.mjs +4 -2
- package/llms-full.txt +387 -44
- package/llms.txt +1 -0
- package/package.json +8 -5
- package/packaging/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/recipes/middleware/middleware/envelope.mjs +4 -2
|
@@ -1,19 +1,39 @@
|
|
|
1
|
+
# Historical record
|
|
2
|
+
|
|
3
|
+
Archived 2026-09-19, when the proposal was **declined**. This records an earlier
|
|
4
|
+
proposal, not current instructions. The decision it lost to is
|
|
5
|
+
[one Node deployment per project](../../OPEN-DECISIONS.md#accepted-one-node-deployment-per-project);
|
|
6
|
+
see also the [current roadmap](../../../ROADMAP.md) and
|
|
7
|
+
[current contract](../../SPECIFICATION.md). Remaining acceptance work is not
|
|
8
|
+
declared complete by archiving this record.
|
|
9
|
+
|
|
10
|
+
<!-- trust-model-prose: historical-file -->
|
|
11
|
+
<!-- guidance-claims: ignore-file -->
|
|
12
|
+
|
|
1
13
|
# Spike: compiling `function` routes into their own Lambdas
|
|
2
14
|
|
|
3
15
|
> Review update, 2026-09-19: Current baseline: trusted Node execution is the default, so fresh invocation
|
|
4
16
|
> state is a guarantee of `sandbox: true` only. AWS/Vercel still reject functions
|
|
5
17
|
> and middleware in `src/capabilities.ts`; changing the default did not implement
|
|
6
|
-
> a provider adapter for them.
|
|
7
|
-
>
|
|
8
|
-
> link APIs in the analysis below are historical.
|
|
18
|
+
> a provider adapter for them. The per-route lowering was weighed against a
|
|
19
|
+
> single trusted Node deployment per project, and **the Node deployment was
|
|
20
|
+
> chosen** (2026-09-19). Removed link APIs in the analysis below are historical.
|
|
9
21
|
|
|
10
22
|
|
|
11
|
-
Status:
|
|
12
|
-
|
|
23
|
+
Status: **declined 2026-09-19 — kept as the analysis behind that decision, not
|
|
24
|
+
as a plan.** Nothing here is implemented and nothing here is committed scope.
|
|
25
|
+
The maintainer chose the alternative this document weighs itself against: a
|
|
26
|
+
project that uses `function` or `middleware` deploys as **one trusted Node
|
|
27
|
+
process**, and AWS/Vercel keep refusing those routes at activation as a
|
|
28
|
+
deliberate position rather than a gap awaiting an adapter. See
|
|
29
|
+
[open decisions](../../OPEN-DECISIONS.md#accepted-one-node-deployment-per-project).
|
|
30
|
+
|
|
31
|
+
Read on for why, and for what a first attempt would look like if real demand for
|
|
32
|
+
`function` routes on AWS serverless ever appears and reopens the question.
|
|
13
33
|
|
|
14
34
|
AWS already deploys today. `createLambdaHandler` (`src/aws.ts`) runs a project
|
|
15
35
|
as **one** Lambda behind a Function URL or an API Gateway HTTP API, reading the
|
|
16
|
-
same `urlcode.yaml` that runs locally — see [AWS](AWS.md). What it cannot serve
|
|
36
|
+
same `urlcode.yaml` that runs locally — see [AWS](../../AWS.md). What it cannot serve
|
|
17
37
|
is `function`, `middleware` and `link`, which
|
|
18
38
|
`activateNativeOnly` (`src/adapters.ts`) refuses for the whole deployment at
|
|
19
39
|
activation rather than letting individual routes fail per request.
|
|
@@ -22,6 +42,120 @@ This spike asks one question: **is the refusal of `function` a fact about
|
|
|
22
42
|
Lambda, or a fact about the adapter?** It argues the second, sketches the
|
|
23
43
|
lowering that follows, and is deliberate about what that lowering costs.
|
|
24
44
|
|
|
45
|
+
Section 0 says all of that again without the jargon; sections 1 onward are the
|
|
46
|
+
argument in full.
|
|
47
|
+
|
|
48
|
+
## 0. In plain terms
|
|
49
|
+
|
|
50
|
+
This section is the whole spike in ordinary language. Everything after it is the
|
|
51
|
+
same argument stated precisely; if the two ever disagree, the precise version
|
|
52
|
+
wins.
|
|
53
|
+
|
|
54
|
+
### What a `function` route is
|
|
55
|
+
|
|
56
|
+
Most of a URLCode project is description, not code: "this URL redirects there",
|
|
57
|
+
"this URL returns that page", "this URL serves that file". You write those in
|
|
58
|
+
YAML and never write a program. A **`function` route** is the escape hatch for
|
|
59
|
+
the cases YAML cannot describe — you write a small piece of JavaScript, and the
|
|
60
|
+
runtime calls it when a request arrives. `middleware` is the same idea, except
|
|
61
|
+
it runs on the way *to* other routes rather than answering by itself.
|
|
62
|
+
|
|
63
|
+
### Where that code runs today
|
|
64
|
+
|
|
65
|
+
Two ways, and the project picks per route:
|
|
66
|
+
|
|
67
|
+
- **Trusted (the default).** The code runs directly in the same Node process as
|
|
68
|
+
everything else, at full speed, with the same access the process has. This is
|
|
69
|
+
the default because the person writing the route is usually the same person
|
|
70
|
+
deploying it. See [the decision](../../SPIKE-DEFAULT-TRUST-MODEL.md).
|
|
71
|
+
- **Sandboxed (`sandbox: true`, opt in per route).** The code runs inside a
|
|
72
|
+
small, separate JavaScript engine (QuickJS, compiled to WebAssembly) on a
|
|
73
|
+
worker thread. Inside there it has no filesystem, no network, no environment
|
|
74
|
+
variables and a completely fresh memory space on every single call. It can
|
|
75
|
+
only reach the outside world through *bindings* an operator granted by name.
|
|
76
|
+
See [function security](../../FUNCTION-SECURITY.md).
|
|
77
|
+
|
|
78
|
+
Think of the sandbox as a sealed room inside your own house. Nothing gets in or
|
|
79
|
+
out except through a hatch you deliberately opened, and the room is wiped clean
|
|
80
|
+
between visitors.
|
|
81
|
+
|
|
82
|
+
### What happens on AWS today
|
|
83
|
+
|
|
84
|
+
Nothing, for these routes. If a project contains any `function` or `middleware`
|
|
85
|
+
route, the AWS adapter refuses **the entire deployment at startup** and names
|
|
86
|
+
what it cannot serve. Everything else — redirects, pages, static files,
|
|
87
|
+
downloads — deploys fine as a single Lambda.
|
|
88
|
+
|
|
89
|
+
That refusal is not a bug or an oversight. It is the runtime declining to
|
|
90
|
+
pretend. The alternative would be accepting the deployment and then failing
|
|
91
|
+
individual requests in production, which is worse.
|
|
92
|
+
|
|
93
|
+
### Why it refuses
|
|
94
|
+
|
|
95
|
+
The sealed room is expensive to build. Every time AWS starts a fresh copy of
|
|
96
|
+
your Lambda (a "cold start"), that copy would have to spin up worker threads and
|
|
97
|
+
boot a WebAssembly engine *before* it could answer the first request. One
|
|
98
|
+
process trying to serve every route in a project, rebuilding all that machinery
|
|
99
|
+
on every cold start, is a bad trade.
|
|
100
|
+
|
|
101
|
+
The key observation of this spike: that reasoning is about **one process serving
|
|
102
|
+
every route**. It is not actually about AWS. Change the unit of deployment and
|
|
103
|
+
the objection evaporates.
|
|
104
|
+
|
|
105
|
+
### The idea
|
|
106
|
+
|
|
107
|
+
Stop shipping one Lambda for the whole project. Instead, at build time, emit
|
|
108
|
+
**one Lambda per `function` route** — plus the existing single Lambda for all
|
|
109
|
+
the ordinary declarative routes.
|
|
110
|
+
|
|
111
|
+
Then you do not need the sealed room at all, because each piece of code already
|
|
112
|
+
has an entire AWS process to itself. The process *is* the wall. This is the same
|
|
113
|
+
move URLCode already makes for Cloudflare: when a platform will not run what the
|
|
114
|
+
adapter needs, compile the project ahead of time instead of adapting at runtime.
|
|
115
|
+
|
|
116
|
+
### The catch — three of them
|
|
117
|
+
|
|
118
|
+
1. **It is a different kind of safety, not more of the same safety.** A Lambda
|
|
119
|
+
is a genuinely separate box, which is good. But out of the box that box has
|
|
120
|
+
working network access, a writable temp disk, ambient environment variables,
|
|
121
|
+
and an AWS identity (an "IAM role") that can reach real infrastructure. The
|
|
122
|
+
sealed room had none of that. So swapping one for the other is a **trade**,
|
|
123
|
+
not an upgrade — and the documentation would have to say exactly which
|
|
124
|
+
guarantee changed rather than announcing "functions work on AWS now". One
|
|
125
|
+
guarantee is simply lost: the sandbox promises fresh memory on every call,
|
|
126
|
+
and AWS reuses warm containers.
|
|
127
|
+
2. **URLCode would start generating security-critical infrastructure.** To keep
|
|
128
|
+
each route's permissions tight, the build would have to write out an IAM role
|
|
129
|
+
per route. A generated permissions file is not an implementation detail you
|
|
130
|
+
can wave away with "don't rely on this" — if it is too generous, it is a
|
|
131
|
+
security hole the project authored.
|
|
132
|
+
3. **It would be an unverified claim wearing a capability's clothes.** Right now
|
|
133
|
+
the project's position on AWS is honest: it reports `deployment: 'unverified'`
|
|
134
|
+
and tells you to deploy the example yourself. Shipping a compiler that emits
|
|
135
|
+
cloud infrastructure nobody on the project has ever actually deployed would
|
|
136
|
+
trade an honest refusal for a bigger unproven promise.
|
|
137
|
+
|
|
138
|
+
### The alternative already sitting on the table — and now chosen
|
|
139
|
+
|
|
140
|
+
Run the project as **one ordinary Node deployment** — a container or a VM. That
|
|
141
|
+
supports `function` and `middleware` today, with no compiler, no generated
|
|
142
|
+
infrastructure and no new security surface. It costs you the serverless
|
|
143
|
+
operating model: something is always running, and you scale it yourself.
|
|
144
|
+
|
|
145
|
+
So the real decision is not "can this be built" — it probably can. It is:
|
|
146
|
+
|
|
147
|
+
> Is there enough demand for running URLCode `function` routes specifically on
|
|
148
|
+
> AWS serverless to justify this project owning an infrastructure compiler and a
|
|
149
|
+
> second, weaker isolation story?
|
|
150
|
+
|
|
151
|
+
**That question was answered on 2026-09-19: no.** Nobody has produced the demand
|
|
152
|
+
evidence, and the plain Node deployment does the job today, so the Node
|
|
153
|
+
deployment is the supported model and the compiler is not being built. The
|
|
154
|
+
refusal on AWS and Vercel stays, and is now a position rather than a gap. See
|
|
155
|
+
[open decisions](../../OPEN-DECISIONS.md#accepted-one-node-deployment-per-project).
|
|
156
|
+
If that demand ever shows up, §6 below already scopes what a first attempt
|
|
157
|
+
would be.
|
|
158
|
+
|
|
25
159
|
## 1. Where the refusal actually comes from
|
|
26
160
|
|
|
27
161
|
`src/capabilities.ts` gives the reason:
|
|
@@ -32,7 +166,7 @@ capability === 'function' ? 'isolated functions need worker threads and the WASM
|
|
|
32
166
|
|
|
33
167
|
That is true of the runtime's *own* mechanism. Isolation for guest code is
|
|
34
168
|
QuickJS inside WebAssembly, driven from worker threads, with the boundaries
|
|
35
|
-
[function security](FUNCTION-SECURITY.md) lists: no `process`, no filesystem,
|
|
169
|
+
[function security](../../FUNCTION-SECURITY.md) lists: no `process`, no filesystem,
|
|
36
170
|
no sockets, no `fetch`, a fresh guest heap per invocation, and bindings denied
|
|
37
171
|
unless an operator granted them by exact name.
|
|
38
172
|
|
|
@@ -49,7 +183,7 @@ Cloudflare already establishes the pattern: where a platform forbids what the
|
|
|
49
183
|
adapter needs, URLCode **compiles ahead of time** instead of adapting at
|
|
50
184
|
runtime. `urlcode build --target cloudflare` (`src/build-cloudflare.ts`) emits
|
|
51
185
|
an artifact the Worker reads, and refuses at build time anything it cannot
|
|
52
|
-
serve, with the route named — see [Cloudflare](CLOUDFLARE.md).
|
|
186
|
+
serve, with the route named — see [Cloudflare](../../CLOUDFLARE.md).
|
|
53
187
|
|
|
54
188
|
The same move for AWS: a build step emits **one Lambda per `function` route**,
|
|
55
189
|
plus the existing native-handler Lambda for everything else.
|
|
@@ -75,6 +209,9 @@ This is not a smaller change than it looks. Three things follow from it.
|
|
|
75
209
|
|
|
76
210
|
This is the claim most likely to be made too early, so it goes first.
|
|
77
211
|
|
|
212
|
+
> **Plainly:** both are real walls, but they are different walls, and neither
|
|
213
|
+
> one is strictly stronger. Read the table as a trade, not a scorecard.
|
|
214
|
+
|
|
78
215
|
QuickJS-WASM and a Lambda are both real isolation. They are **not the same
|
|
79
216
|
isolation**, and neither strictly contains the other:
|
|
80
217
|
|
|
@@ -101,6 +238,12 @@ this project should not make.
|
|
|
101
238
|
|
|
102
239
|
### 3.2 `middleware` is the hard part, not `function`
|
|
103
240
|
|
|
241
|
+
> **Plainly:** a `function` is a dead end — it answers and the request stops
|
|
242
|
+
> there, so giving it its own Lambda is easy. Middleware is a queue of steps
|
|
243
|
+
> every request walks through on its way somewhere else, and a queue split
|
|
244
|
+
> across separate Lambdas has to be either copied into each one or wired up as
|
|
245
|
+
> a chain of calls. Both hurt, so this spike does not attempt middleware.
|
|
246
|
+
|
|
104
247
|
`function` lowers cleanly because it is a leaf. `middleware` is a per-request
|
|
105
248
|
chain, and there are only two ways to lower it, both with a real cost:
|
|
106
249
|
|
|
@@ -124,6 +267,11 @@ section describes was later removed from core; see
|
|
|
124
267
|
|
|
125
268
|
## 4. Emitting infrastructure is a new kind of output
|
|
126
269
|
|
|
270
|
+
> **Plainly:** up to now URLCode has only ever produced things that run *inside*
|
|
271
|
+
> a server it was given. Emitting a CloudFormation stack means it starts
|
|
272
|
+
> producing the cloud account's own configuration — including permissions — and
|
|
273
|
+
> becomes responsible for that being correct as AWS changes underneath it.
|
|
274
|
+
|
|
127
275
|
`examples/aws/template.yaml` is hand-written today. Generating a stack means
|
|
128
276
|
this project starts owning a surface it has never owned:
|
|
129
277
|
|
|
@@ -139,7 +287,7 @@ this project starts owning a surface it has never owned:
|
|
|
139
287
|
|
|
140
288
|
That last point is the one worth holding onto. The project's current position on
|
|
141
289
|
AWS is **honest**: the capability catalog reports `deployment: 'unverified'` for
|
|
142
|
-
every target that is not self-hosted, and [AWS](AWS.md) tells a reader to treat
|
|
290
|
+
every target that is not self-hosted, and [AWS](../../AWS.md) tells a reader to treat
|
|
143
291
|
the limits as unverified until they deploy the example themselves. A compiler
|
|
144
292
|
that emits infrastructure nobody has deployed would be a larger unverified claim
|
|
145
293
|
wearing the clothes of a capability.
|
|
@@ -161,7 +309,9 @@ lowering without anything else in the model changing, and `urlcode capabilities
|
|
|
161
309
|
|
|
162
310
|
## 6. Proposed scope for a first spike
|
|
163
311
|
|
|
164
|
-
Narrow, so that the isolation story stays clean and the win is real
|
|
312
|
+
Narrow, so that the isolation story stays clean and the win is real.
|
|
313
|
+
**Plainly: build the smallest version that proves the idea, and resist every
|
|
314
|
+
tempting extra.**
|
|
165
315
|
|
|
166
316
|
**In:** `function` routes, Function URL only, one Lambda per function route,
|
|
167
317
|
a generated role per route carrying exactly that route's granted bindings,
|
|
@@ -190,13 +340,19 @@ having run it on AWS, and the spike should say so rather than imply otherwise.
|
|
|
190
340
|
|
|
191
341
|
## 8. Open questions
|
|
192
342
|
|
|
343
|
+
These are the things a reviewer should press on. In plain terms: *is losing the
|
|
344
|
+
fresh-state guarantee acceptable at all; should URLCode write the permissions or
|
|
345
|
+
merely describe them; does splitting into many Lambdas quietly weaken the
|
|
346
|
+
policies a project already declares; and is one Lambda per route even the right
|
|
347
|
+
size of piece?*
|
|
348
|
+
|
|
193
349
|
- Is warm-container reuse acceptable at all, given the runtime currently
|
|
194
350
|
*guarantees* fresh per-invocation state? If not, this lowering is wrong for
|
|
195
351
|
any route that relies on that guarantee, and there is no build-time way to
|
|
196
352
|
tell which ones do.
|
|
197
353
|
- Does the generated IAM role belong in URLCode's output, or should the build
|
|
198
354
|
emit a *description* of the permissions each route needs and leave the role to
|
|
199
|
-
the operator — closer to how [function security](FUNCTION-SECURITY.md) already
|
|
355
|
+
the operator — closer to how [function security](../../FUNCTION-SECURITY.md) already
|
|
200
356
|
keeps grants operator-controlled and outside the checkout?
|
|
201
357
|
- Does a per-route Lambda change what `policies` can promise? `throttle` on AWS
|
|
202
358
|
is already `conditional` — "counters are per instance" — and more instances
|
|
@@ -204,6 +360,6 @@ having run it on AWS, and the spike should say so rather than imply otherwise.
|
|
|
204
360
|
- Is one Lambda per route the right granularity, or one per *project* with a
|
|
205
361
|
route parameter, which keeps deployment small but reintroduces a shared
|
|
206
362
|
process?
|
|
207
|
-
- What happens to the 6 MB Lambda response limit ([AWS](AWS.md)) for a function
|
|
363
|
+
- What happens to the 6 MB Lambda response limit ([AWS](../../AWS.md)) for a function
|
|
208
364
|
route that returns a large body — refuse at build time, as the Cloudflare
|
|
209
365
|
target refuses what it cannot serve?
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Spike: consolidating core, auth, admin and ui into one repo
|
|
2
2
|
|
|
3
|
+
<!-- local-links: historical-file -->
|
|
4
|
+
|
|
3
5
|
> **Closed 2026-09-19: the migration is done, and this document is history.**
|
|
4
6
|
>
|
|
5
7
|
> `urlcode-ui`, `urlcode-auth` and `urlcode-admin` are workspace packages under
|
package/docs/archive/README.md
CHANGED
|
@@ -19,6 +19,7 @@ Archived on 2026-09-19 after checking the current code:
|
|
|
19
19
|
| [Extension model review](2026-09-19/SPIKE-EXTENSION-MODEL.md) | Historical design rationale | Current extension contract |
|
|
20
20
|
| [Usability review](2026-09-19/USABILITY-REVIEW.md) | Predates trusted execution and retired packages | New benchmark observations |
|
|
21
21
|
| [Management security](2026-09-19/MANAGEMENT-SECURITY.md) | Describes the removed core link-management API | No current core replacement |
|
|
22
|
+
| [Lambda compile spike](2026-09-19/SPIKE-LAMBDA-COMPILE.md) | Proposal declined 2026-09-19 in favour of one Node deployment per project | Open decisions; AWS and Vercel guides |
|
|
22
23
|
|
|
23
24
|
Open proposals stay outside the archive with their status stated at the top.
|
|
24
25
|
The accepted trust-by-default decision remains directly linked from the current
|
package/docs/yaml/functions.md
CHANGED
|
@@ -53,8 +53,16 @@ short form: `middleware: [middleware/headers.mjs]` means
|
|
|
53
53
|
`middleware: [{source: middleware/headers.mjs}]`. The path must be
|
|
54
54
|
project-relative, end in `.mjs` or `.js` and contain no `..` segment.
|
|
55
55
|
Methods default to GET and HEAD. Function paths resolve from the project root,
|
|
56
|
-
not the YAML file's directory.
|
|
57
|
-
|
|
56
|
+
not the YAML file's directory. Modules are ES modules either way: `.mjs` always
|
|
57
|
+
works, while a trusted `.js` module is loaded by Node and therefore needs the
|
|
58
|
+
nearest `package.json` to say `"type": "module"` (a `sandbox: true` route reads
|
|
59
|
+
`.js` as ESM regardless). Serving never transpiles TypeScript; build it first
|
|
60
|
+
with [TypeScript authoring](../TYPESCRIPT-AUTHORING.md). The route above
|
|
61
|
+
declares no `sandbox`, so it runs trusted and in-process: Node APIs, npm
|
|
62
|
+
imports, network and filesystem access are all available to it, exactly as they
|
|
63
|
+
are to any other Node code in the host. Add `sandbox: true` to trade them away
|
|
64
|
+
for isolation -- inside the guest none of them exist. See
|
|
65
|
+
[trust model and sandbox opt-in](../FUNCTION-SECURITY.md).
|
|
58
66
|
|
|
59
67
|
## 4. Input types and constraints
|
|
60
68
|
|
package/docs/yaml/middleware.md
CHANGED
|
@@ -23,7 +23,9 @@ export async function decorate(request, context, next) {
|
|
|
23
23
|
|
|
24
24
|
Entries run in declared order before the handler and reverse order afterward.
|
|
25
25
|
Return a Response early to skip downstream code; call `next()` at most once.
|
|
26
|
-
Up to 16 middleware entries share one
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Up to 16 middleware entries share the route's execution mode, one deadline and
|
|
27
|
+
one set of approved route bindings; the mode is the route's `sandbox` field, not
|
|
28
|
+
a per-entry choice. On a `sandbox: true` route native bodies are opaque;
|
|
29
|
+
preserving them requires retaining original status/headers. Return a new
|
|
30
|
+
Response to replace native content or destination.
|
|
29
31
|
YAML response headers apply last. See [middleware](../MIDDLEWARE.md) for details.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
// Wrap successful JSON function responses in a stable envelope.
|
|
2
|
-
//
|
|
1
|
+
// Wrap successful JSON function responses in a stable envelope. Only a JSON body
|
|
2
|
+
// this chain can actually read is rewritten; everything else passes through
|
|
3
|
+
// untouched -- on a `sandbox: true` route that includes every native body, which
|
|
4
|
+
// the guest cannot read at all.
|
|
3
5
|
export default async function envelope(request, context, next) {
|
|
4
6
|
const response = await next();
|
|
5
7
|
if (!response.ok || !(response.headers.get('content-type') || '').startsWith('application/json')) return response;
|