@jimhoyd/urlcode 0.4.0-alpha.2 → 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/skills/urlcode-authoring/SKILL.md +17 -19
- package/.claude/skills/urlcode-operations/SKILL.md +9 -9
- package/.claude-plugin/marketplace.json +1 -1
- package/CONTRIBUTING.md +20 -16
- package/README.md +59 -64
- package/ROADMAP.md +66 -376
- package/dist/BUILD-MANIFEST.json +26 -25
- package/dist/agents-guide.js +6 -6
- package/dist/authoring.js +15 -1
- package/dist/build-static.js +2 -0
- package/dist/capability-query.js +0 -1
- package/dist/catalog.js +0 -1
- package/dist/cli.js +25 -9
- package/dist/config.js +1 -1
- package/dist/explain-cli.js +4 -2
- package/dist/explain.js +8 -2
- package/dist/extensions.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 +8 -2
- package/dist/mcp-authoring.js +4 -4
- package/dist/mcp.js +1 -1
- package/dist/policies/cache.js +2 -2
- package/dist/policies.js +3 -1
- package/dist/prerender.js +4 -0
- package/dist/project-dependencies.js +305 -0
- package/dist/readiness.js +3 -0
- package/dist/route-diff.js +12 -5
- 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 +6 -1
- package/dist/types/extensions.d.ts +1 -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 +5 -2
- package/dist/types/project-dependencies.d.ts +78 -0
- package/dist/types/readiness.d.ts +2 -0
- package/dist/types/trusted-functions.d.ts +1 -4
- package/dist/types/types.d.ts +8 -1
- package/dist/types.js +8 -1
- package/dist/typescript-authoring.js +18 -7
- package/docs/AI-AUTHORING.md +15 -7
- package/docs/ASSETS.md +2 -1
- package/docs/AUTH-BACKUP.md +32 -0
- package/docs/AWS.md +9 -0
- package/docs/BEST-PRACTICES.md +17 -9
- package/docs/CAPABILITIES.md +1 -1
- package/docs/CI-FOLLOWUP-2026-09-19.md +97 -0
- package/docs/CI-RELEASE-AUDIT-2026-09-19.md +322 -0
- package/docs/CI.md +8 -3
- package/docs/CODEBASE-AUDIT-2026-09-20.md +284 -0
- package/docs/COMPOSING-A-SITE.md +278 -0
- package/docs/DEVELOPMENT-PIPELINE.md +270 -0
- package/docs/EXTENSIONS.md +51 -11
- package/docs/FRAMEWORK.md +67 -48
- package/docs/FUNCTION-SECURITY.md +44 -0
- package/docs/INSTALL.md +13 -8
- package/docs/LOCAL-DEVELOPMENT.md +3 -0
- package/docs/MIDDLEWARE.md +10 -4
- package/docs/OPEN-DECISIONS.md +224 -212
- package/docs/OPERATIONAL-PROOF.md +3 -3
- package/docs/OPERATIONS.md +3 -3
- package/docs/POLICIES.md +13 -5
- package/docs/PRERENDER.md +23 -11
- package/docs/PROJECT-DIRECTION.md +3 -3
- package/docs/READINESS.md +10 -5
- package/docs/README.md +20 -44
- package/docs/RELEASE-0.4.0-alpha.3.md +50 -0
- package/docs/RELEASE-0.4.1.md +73 -0
- package/docs/RELEASE-READINESS.md +6 -6
- package/docs/RELEASE-SECURITY.md +96 -181
- package/docs/RESILIENCE.md +3 -3
- package/docs/ROUTING.md +3 -4
- package/docs/SECURITY-AUDIT.md +2 -2
- package/docs/SPECIFICATION.md +12 -6
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +6 -5
- package/docs/SPIKE-BUSINESS-SUITE.md +14 -6
- package/docs/SPIKE-CORE-LAYERING.md +49 -18
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +7 -5
- package/docs/STARTERS.md +17 -5
- package/docs/STATIC.md +14 -3
- package/docs/TOOLING.md +10 -7
- package/docs/TYPESCRIPT-AUTHORING.md +6 -1
- package/docs/VERCEL.md +10 -2
- package/docs/VERSION-ALIGNMENT.md +76 -201
- package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +68 -0
- package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +102 -0
- package/docs/{NEXT-PHASE-PLAN.md → archive/2026-09-19/NEXT-PHASE-PLAN.md} +15 -5
- package/docs/{NEXT-STEPS.md → archive/2026-09-19/NEXT-STEPS.md} +15 -3
- package/docs/archive/2026-09-19/OPEN-DECISIONS.md +277 -0
- package/docs/archive/2026-09-19/RELEASE-SECURITY.md +186 -0
- package/docs/archive/2026-09-19/ROADMAP.md +387 -0
- package/docs/{SPIKE-EXTENSION-MODEL.md → archive/2026-09-19/SPIKE-EXTENSION-MODEL.md} +11 -0
- package/docs/{SPIKE-EXTENSIONS.md → archive/2026-09-19/SPIKE-EXTENSIONS.md} +25 -14
- package/docs/archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md +365 -0
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +778 -0
- package/docs/{USABILITY-REVIEW.md → archive/2026-09-19/USABILITY-REVIEW.md} +12 -2
- package/docs/archive/README.md +28 -0
- package/docs/policies/agents.md +1 -1
- package/docs/policies/compression.md +3 -2
- package/docs/policies/security.md +3 -2
- package/docs/yaml/functions.md +10 -2
- package/docs/yaml/middleware.md +5 -3
- package/examples/assets/example.yaml +1 -1
- package/examples/cookbook/middleware/envelope.mjs +4 -2
- package/examples/cookbook/route-index.json +1 -1
- package/examples/cookbook/routes/middleware.yaml +1 -1
- package/examples/prerender/README.md +14 -6
- package/examples/prerender/functions/page.mjs +4 -2
- package/examples/prerender/middleware/template.mjs +1 -1
- package/examples/prerender/prerender.mjs +1 -1
- package/examples/prerender/urlcode.yaml +8 -4
- package/llms-full.txt +503 -88
- package/llms.txt +6 -4
- package/package.json +27 -4
- package/packaging/claude-plugin/.claude-plugin/plugin.json +2 -2
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +17 -19
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +9 -9
- package/recipes/authenticated-json-api/README.md +4 -3
- package/recipes/authenticated-json-api/functions/profile.mjs +2 -1
- package/recipes/authenticated-json-api/recipe.yaml +1 -1
- package/recipes/contact-form/functions/contact.mjs +2 -1
- package/recipes/contact-form/recipe.yaml +2 -2
- package/recipes/cors-api/README.md +2 -2
- package/recipes/cors-api/recipe.yaml +1 -1
- package/recipes/health-page/README.md +1 -1
- package/recipes/json-api/README.md +1 -1
- package/recipes/json-api/recipe.yaml +3 -3
- package/recipes/middleware/README.md +8 -4
- package/recipes/middleware/middleware/envelope.mjs +4 -2
- package/recipes/protected-download/README.md +1 -1
- package/recipes/protected-download/recipe.yaml +1 -1
- package/recipes/static-plus-api/README.md +2 -2
- package/recipes/static-plus-api/public/index.html +1 -1
- package/recipes/static-plus-api/recipe.yaml +1 -1
- package/recipes/static-plus-api/urlcode.yaml +1 -1
- package/recipes/typescript/recipe.yaml +4 -4
- package/skills/urlcode/SKILL.md +6 -6
- package/starters/default/AGENTS.md +6 -6
- package/docs/SPIKE-LAMBDA-COMPILE.md +0 -201
- package/docs/SPIKE-MONOREPO.md +0 -322
package/docs/FRAMEWORK.md
CHANGED
|
@@ -7,26 +7,26 @@ claim here is implemented in the linked repository; nothing is roadmap.
|
|
|
7
7
|
|
|
8
8
|
## Four packages, one project shape
|
|
9
9
|
|
|
10
|
-
| Package |
|
|
10
|
+
| Package | Source | What it adds | How a project declares it |
|
|
11
11
|
|---|---|---|---|
|
|
12
|
-
| `@jimhoyd/urlcode` |
|
|
13
|
-
| `@jimhoyd/urlcode-ui` | [
|
|
14
|
-
| `@jimhoyd/urlcode-auth` | [
|
|
15
|
-
| `@jimhoyd/urlcode-admin` | [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
endorsement: the source is complete, but independent review, deployment
|
|
22
|
-
evidence and an accessibility assessment are still pending
|
|
12
|
+
| `@jimhoyd/urlcode` | this repository | The runtime: YAML routes, functions and middleware (trusted by default, `sandbox: true` opt-in), pages and assets, policies, site conventions, CLI, provider adapters, the extension contract | `urlcode.yaml` with `version: "1"` |
|
|
13
|
+
| `@jimhoyd/urlcode-ui` | [`packages/ui`](../packages/ui) | Shared presentation: escaped templates, shadcn/ui partials, one stylesheet with light and dark, themes, translations, the `ui` extension that serves the kit's assets | `extensions.ui` plus an asset mount route |
|
|
14
|
+
| `@jimhoyd/urlcode-auth` | [`packages/auth`](../packages/auth) | Accounts: password, passkeys, OpenID Connect, email codes, TOTP, recovery, sessions, roles, registration modes, account page, operator CLI | `extensions.auth` plus an `/account/*` mount and `policies.extensions.auth` on protected routes |
|
|
15
|
+
| `@jimhoyd/urlcode-admin` | [`packages/admin`](../packages/admin) | Administration: users, sessions, roles, audit, registration approval, two-person cases, support impersonation, health | `extensions.admin` plus an `/admin/*` mount |
|
|
16
|
+
|
|
17
|
+
All four are Apache-2.0. The `0.4.1` release line aligns their stable versions;
|
|
18
|
+
check `npm run release:status` for publication progress. A stable npm channel is
|
|
19
|
+
not an independent assessment: review, deployment evidence and an accessibility
|
|
20
|
+
assessment are still pending
|
|
23
21
|
([issue 58](https://github.com/jimhoyd-com/urlcode/issues/58)). Their status
|
|
24
|
-
files say exactly what is built: [auth](
|
|
25
|
-
[admin](
|
|
26
|
-
[ui](
|
|
27
|
-
|
|
28
|
-
in
|
|
29
|
-
|
|
22
|
+
files say exactly what is built: [auth](../packages/auth/IMPLEMENTATION-STATUS.md),
|
|
23
|
+
[admin](../packages/admin/IMPLEMENTATION-STATUS.md),
|
|
24
|
+
[ui](../packages/ui/IMPLEMENTATION-STATUS.md).
|
|
25
|
+
The current version of each package is its own manifest, and the peer ranges it
|
|
26
|
+
declares are in that manifest too; do not read a version number out of this
|
|
27
|
+
page. How versions, channels and release tags line up is recorded in
|
|
28
|
+
[package and channel alignment](VERSION-ALIGNMENT.md), and `npm run
|
|
29
|
+
release:status` reports the live registry and tag state.
|
|
30
30
|
|
|
31
31
|
## The ladder
|
|
32
32
|
|
|
@@ -43,8 +43,10 @@ Each rung's YAML is valid on every rung above it.
|
|
|
43
43
|
3. **Functions and middleware.** `function` routes and ordered `middleware`
|
|
44
44
|
in JavaScript, trusted and in-process by default; a route declaring
|
|
45
45
|
`sandbox: true` runs isolated instead (QuickJS inside WebAssembly, fresh
|
|
46
|
-
heap per call, no Node, filesystem or network).
|
|
47
|
-
only
|
|
46
|
+
heap per call, no Node, filesystem or network). The `env`/`secrets` the
|
|
47
|
+
runtime injects into a function come only from an operator grant pinned to
|
|
48
|
+
the project revision; the grant governs that injected context, not the
|
|
49
|
+
ambient Node environment trusted in-process code can reach on its own.
|
|
48
50
|
4. **Accounts.** The `auth` extension: sign-in, registration, MFA, account
|
|
49
51
|
page and protected routes. The operator installs it in a host file outside
|
|
50
52
|
the project; YAML only declares the mount and configuration.
|
|
@@ -56,27 +58,29 @@ Each rung's YAML is valid on every rung above it.
|
|
|
56
58
|
project copy, template and stylesheet overrides for kit-rendered pages.
|
|
57
59
|
|
|
58
60
|
Stored short links previously sat here as a native `link` route; that handler
|
|
59
|
-
was removed from core. A
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
was removed from core. A `urlcode-dynamic-link` package owned them the same way
|
|
62
|
+
`auth`/`admin` own their mounts, but it has been retired and unpublished; no
|
|
63
|
+
package occupies this rung today.
|
|
62
64
|
|
|
63
65
|
Rungs 1 to 3 need only the core package. Rungs 4 to 6 need the extension
|
|
64
|
-
packages
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
packages installed from npm and a Node host with a
|
|
67
|
+
patched SQLite build; see each package's README ([auth](../packages/auth/README.md),
|
|
68
|
+
[admin](../packages/admin/README.md), [ui](../packages/ui/README.md)) for the
|
|
69
|
+
exact requirement.
|
|
67
70
|
|
|
68
71
|
## The composition contract
|
|
69
72
|
|
|
70
|
-
|
|
73
|
+
After the aligned `0.4.1` packages are published, an extended project starts
|
|
74
|
+
with the packages and one command:
|
|
71
75
|
|
|
72
76
|
```sh
|
|
73
|
-
npm install @jimhoyd/urlcode @jimhoyd/urlcode-ui @jimhoyd/urlcode-auth @jimhoyd/urlcode-admin
|
|
74
|
-
urlcode init my-site --with auth,admin
|
|
77
|
+
npm install --save-exact @jimhoyd/urlcode@0.4.1 @jimhoyd/urlcode-ui@0.4.1 @jimhoyd/urlcode-auth@0.4.1 @jimhoyd/urlcode-admin@0.4.1
|
|
78
|
+
urlcode init my-site --with ui,auth,admin
|
|
75
79
|
```
|
|
76
80
|
|
|
77
|
-
Installing from npm is the normal path;
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
Installing from npm is the normal path; `scripts/pack-sources.mjs` still builds
|
|
82
|
+
local tarballs from a reviewed checkout for operators who install only source
|
|
83
|
+
they have read — one revision now covers core and every extension. Three files make an extended
|
|
80
84
|
project. Nothing else is discovered by convention.
|
|
81
85
|
|
|
82
86
|
```
|
|
@@ -108,7 +112,8 @@ routes:
|
|
|
108
112
|
auth: {}
|
|
109
113
|
```
|
|
110
114
|
|
|
111
|
-
The operator host
|
|
115
|
+
The operator host explicitly registers the packages. Registration is an
|
|
116
|
+
activation boundary; it does not isolate trusted application code from the host:
|
|
112
117
|
|
|
113
118
|
```js
|
|
114
119
|
import { createUiExtension } from '@jimhoyd/urlcode-ui/host';
|
|
@@ -128,18 +133,18 @@ export default {
|
|
|
128
133
|
};
|
|
129
134
|
```
|
|
130
135
|
|
|
131
|
-
Auth and admin
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
Auth and admin already render their screens through `ui.kit` when the host
|
|
137
|
+
supplies the UI extension; their package-owned templates and catalogues must be
|
|
138
|
+
registered with that kit. Without it, both retain shared primitive rendering
|
|
139
|
+
through `presentation`. The example above uses that primitive fallback. The UI
|
|
140
|
+
block is optional, and a migration to the kit is not unfinished framework work.
|
|
141
|
+
See each package README for its complete kit registration example.
|
|
137
142
|
|
|
138
143
|
```sh
|
|
139
144
|
urlcode serve --project /absolute/site --host-file /absolute/operator/host.mjs --origin https://site.example
|
|
140
145
|
```
|
|
141
146
|
|
|
142
|
-
`urlcode init <dir> --with auth,admin` writes this layout in one step: it
|
|
147
|
+
`urlcode init <dir> --with ui,auth,admin` writes this layout in one step: it
|
|
143
148
|
resolves each installed `@jimhoyd/urlcode-<name>` from the current directory,
|
|
144
149
|
calls its `scaffold` export and merges the fragments into `app/urlcode.yaml`,
|
|
145
150
|
one `host.mjs` and one `README.md`, refusing before writing anything when a
|
|
@@ -150,12 +155,24 @@ administrator from JSON on stdin. `inspectExtensionRevision(project)` prints
|
|
|
150
155
|
the SHA-256 that `projectSha256` must carry; changing extension YAML, policies
|
|
151
156
|
or mounts changes the revision and needs an explicit operator reapproval.
|
|
152
157
|
|
|
158
|
+
The presentation tooling composes the same way, by naming packages rather than
|
|
159
|
+
depending on them. `urlcode-ui` is the kit alone until
|
|
160
|
+
`--extensions @jimhoyd/urlcode-auth,@jimhoyd/urlcode-admin` names the packages
|
|
161
|
+
that ship the other namespaces: each is resolved from `--project` with Node
|
|
162
|
+
package resolution and imported for the namespace it exports, so `list`,
|
|
163
|
+
`doctor`, `eject`, `preview` and `copy --missing` cover the `auth/*` and
|
|
164
|
+
`admin/*` templates and copy the host registers, and a project override of an
|
|
165
|
+
extension template is checked against the shipped view model. A package that is
|
|
166
|
+
not installed is skipped. `urlcode init --with` writes the commands with the
|
|
167
|
+
flag already set; `@jimhoyd/urlcode-ui` still depends on neither peer.
|
|
168
|
+
|
|
153
169
|
## Rules an agent must follow
|
|
154
170
|
|
|
155
171
|
These are the facts that keep generated projects valid. The full matrix is in
|
|
156
172
|
[AI authoring](AI-AUTHORING.md); this is the short list.
|
|
157
173
|
|
|
158
|
-
- **YAML
|
|
174
|
+
- **Extension YAML names logical extensions, not host packages or credentials.**
|
|
175
|
+
Function and middleware `source` fields do name project modules. Extensions are
|
|
159
176
|
logical names; the host file chooses the implementation. There is no
|
|
160
177
|
`--extension` flag, no `import` in YAML, no interpolation.
|
|
161
178
|
- **One handler per route.** `redirect`, `respond`, `page`, `static`, `download`,
|
|
@@ -166,13 +183,15 @@ These are the facts that keep generated projects valid. The full matrix is in
|
|
|
166
183
|
It runs in-process with full Node access unless the route declares
|
|
167
184
|
`sandbox: true`, which isolates it to a text/JSON `Request`/`Response`
|
|
168
185
|
subset, validated `args` and granted `env`, with no `fetch`, Node,
|
|
169
|
-
filesystem or timers. Either way, `args`/`env`/`secrets` are exactly what
|
|
186
|
+
filesystem or general network access; bounded timers are available. Either way, `args`/`env`/`secrets` are exactly what
|
|
170
187
|
the route declares and an operator grants — trust changes where code runs,
|
|
171
188
|
not what it is handed. See docs/SPIKE-DEFAULT-TRUST-MODEL.md and
|
|
172
189
|
docs/FUNCTION-SECURITY.md.
|
|
173
190
|
- **Authentication is host processing.** Do not build login forms, session
|
|
174
|
-
cookies or password checks in functions.
|
|
175
|
-
|
|
191
|
+
cookies or password checks in functions. With the auth extension declared,
|
|
192
|
+
prefer `auth: true` or `auth: {role: admin}`; these expand to
|
|
193
|
+
`policies.extensions.auth`. The runtime filters credential headers passed to
|
|
194
|
+
application handlers. This is not a security boundary against trusted Node code.
|
|
176
195
|
- **Everything is validated before it runs.** `urlcode validate --local`,
|
|
177
196
|
`urlcode test`, `urlcode audit --expect-routes N`. Unsupported features fail
|
|
178
197
|
with the route named; nothing degrades silently.
|
|
@@ -191,8 +210,8 @@ These are the facts that keep generated projects valid. The full matrix is in
|
|
|
191
210
|
| Need | Read |
|
|
192
211
|
|---|---|
|
|
193
212
|
| Write or change routes | [YAML guide](YAML-GUIDE.md), [field reference](YAML-REFERENCE.md), [cookbook](../examples/cookbook/README.md) |
|
|
194
|
-
| Add accounts | [auth README](
|
|
195
|
-
| Add administration | [admin README](
|
|
196
|
-
| Restyle every page | [ui README](
|
|
197
|
-
| Write an extension | [extensions](EXTENSIONS.md), [extension model review](SPIKE-EXTENSION-MODEL.md) |
|
|
213
|
+
| Add accounts | [auth README](../packages/auth/README.md), [auth security](../packages/auth/SECURITY.md) |
|
|
214
|
+
| Add administration | [admin README](../packages/admin/README.md) |
|
|
215
|
+
| Restyle every page | [ui README](../packages/ui/README.md), [ui contract](../packages/ui/CONTRACT.md) |
|
|
216
|
+
| Write an extension | [extensions](EXTENSIONS.md), [extension model review](archive/2026-09-19/SPIKE-EXTENSION-MODEL.md) |
|
|
198
217
|
| Run it | [operations](OPERATIONS.md), [install](INSTALL.md), [deployment checks](DEPLOYMENT-CHECKS.md) |
|
|
@@ -40,6 +40,35 @@ API is all it has, so its binding grant *is* effectively its whole reach into
|
|
|
40
40
|
the environment. Trusted code's reach is not bounded that way; treat the
|
|
41
41
|
grant as scoping `context`, not as scoping the process.
|
|
42
42
|
|
|
43
|
+
## Migrating to the trusted default
|
|
44
|
+
|
|
45
|
+
If you are upgrading a project from a release before this change shipped:
|
|
46
|
+
**every existing `function` and `middleware` route silently changes execution
|
|
47
|
+
mode**, from sandboxed to trusted, unless it already has (or you add)
|
|
48
|
+
`sandbox: true`. This is a real behavior change on upgrade, not a
|
|
49
|
+
documentation update — a route that used to run with no filesystem or network
|
|
50
|
+
access will, after the upgrade, run with full Node access unless you opt it
|
|
51
|
+
back into the sandbox.
|
|
52
|
+
|
|
53
|
+
Before upgrading:
|
|
54
|
+
|
|
55
|
+
- List every `function` and `middleware` route in the project.
|
|
56
|
+
- For each one, decide whether you fully trust that code to run in-process
|
|
57
|
+
with full Node/filesystem/network access — the same trust you would extend
|
|
58
|
+
to any other code you deploy to that server.
|
|
59
|
+
- Add `sandbox: true` explicitly to any route whose code you do not fully
|
|
60
|
+
trust, that processes input from a source you don't control, or that handles
|
|
61
|
+
a secret binding you want isolated — before you upgrade, not after.
|
|
62
|
+
- Routes you do want running trusted need no change; that is now the default.
|
|
63
|
+
|
|
64
|
+
The change moves the sandbox from an unconditional guarantee to an explicit,
|
|
65
|
+
per-route choice, mainly for performance: the previous blanket sandbox capped
|
|
66
|
+
concurrency at two workers with no queue shared across every function route on
|
|
67
|
+
the server, which does not scale to real concurrent traffic. It also brings
|
|
68
|
+
first-party code in line with how the rest of the Node ecosystem treats
|
|
69
|
+
deployed application code. The sandbox itself is unchanged for routes that opt
|
|
70
|
+
into it; only the default for routes that declare neither option has changed.
|
|
71
|
+
|
|
43
72
|
## What "sandboxed" (`sandbox: true`) still guarantees
|
|
44
73
|
|
|
45
74
|
- Function sources are parsed/snapshotted without importing them into Node.
|
|
@@ -116,6 +145,21 @@ it is handed *through `context`*. It does not change what the code can go get
|
|
|
116
145
|
on its own once it is running; see "binding grants are unaffected" above for
|
|
117
146
|
that distinction.
|
|
118
147
|
|
|
148
|
+
## Trusted code, not trusted requests
|
|
149
|
+
|
|
150
|
+
"Trusted" describes the code's authorship — first-party project code you
|
|
151
|
+
reviewed and deployed — not the requests it handles. Every request, in either
|
|
152
|
+
mode, still carries client-controlled path, query, header and body data that is
|
|
153
|
+
exactly as adversarial as it always was. Running trusted means that code
|
|
154
|
+
executes with full Node access if it mishandles that input; it does not mean
|
|
155
|
+
the input itself became safe to trust. Declare `parameters` and `request.body`
|
|
156
|
+
validation in YAML, check `args` and any other request data again inside
|
|
157
|
+
function/middleware code, and implement your own authentication and
|
|
158
|
+
authorization — no route, sandboxed or trusted, adds automatic auth.
|
|
159
|
+
`sandbox: true` narrows what a bug or an unreviewed dependency in the *code*
|
|
160
|
+
can do with that same request data; it is not a substitute for validating or
|
|
161
|
+
authenticating the request itself.
|
|
162
|
+
|
|
119
163
|
## Granting selected bindings
|
|
120
164
|
|
|
121
165
|
An application may request a named binding in YAML, but only an operator can
|
package/docs/INSTALL.md
CHANGED
|
@@ -8,8 +8,13 @@ so the installed `urlcode` command runs `dist/cli.js` and needs no build tool.
|
|
|
8
8
|
|
|
9
9
|
## npm
|
|
10
10
|
|
|
11
|
+
The stable release target is `0.4.1`. Use these commands after publication;
|
|
12
|
+
`npm run release:status` in a checkout reports live registry availability. An
|
|
13
|
+
unversioned npm install selects the current `latest` channel, while `@alpha`
|
|
14
|
+
explicitly selects the separate prerelease channel.
|
|
15
|
+
|
|
11
16
|
```sh
|
|
12
|
-
npm install --global @jimhoyd/urlcode
|
|
17
|
+
npm install --global @jimhoyd/urlcode@0.4.1
|
|
13
18
|
urlcode --help
|
|
14
19
|
```
|
|
15
20
|
|
|
@@ -19,12 +24,12 @@ Which dependency list it belongs in depends on how the project uses URLCode:
|
|
|
19
24
|
```sh
|
|
20
25
|
# Using URLCode as a tool: validate, test and build in CI, never imported by
|
|
21
26
|
# the code that serves requests.
|
|
22
|
-
npm install --save-dev @jimhoyd/urlcode
|
|
27
|
+
npm install --save-dev --save-exact @jimhoyd/urlcode@0.4.1
|
|
23
28
|
npx urlcode validate
|
|
24
29
|
|
|
25
30
|
# Embedding the runtime (see TYPESCRIPT.md): the application imports
|
|
26
31
|
# @jimhoyd/urlcode at startup, so it must survive `npm ci --omit=dev`.
|
|
27
|
-
npm install --save @jimhoyd/urlcode
|
|
32
|
+
npm install --save --save-exact @jimhoyd/urlcode@0.4.1
|
|
28
33
|
```
|
|
29
34
|
|
|
30
35
|
A devDependency is absent from a production install, so an application that
|
|
@@ -65,7 +70,7 @@ It downloads the release tarball, verifies its SHA-256 against the release's
|
|
|
65
70
|
`SHA256SUMS`, and installs with npm. Options:
|
|
66
71
|
|
|
67
72
|
```sh
|
|
68
|
-
curl -fsSL .../install.sh | sh -s -- --version 0.
|
|
73
|
+
curl -fsSL .../install.sh | sh -s -- --version 0.4.1 --prefix "$HOME/.local"
|
|
69
74
|
```
|
|
70
75
|
|
|
71
76
|
`--prefix` avoids needing privileges for a global npm directory; add
|
|
@@ -76,12 +81,12 @@ for that moment: to inspect first, download it, read it, then run it.
|
|
|
76
81
|
|
|
77
82
|
No image is published yet: the release job's GHCR step is gated behind the
|
|
78
83
|
`PUBLISH_CONTAINER` repository variable and has not run, so there is nothing at
|
|
79
|
-
`ghcr.io/jimhoyd-com/urlcode` to pull.
|
|
84
|
+
`ghcr.io/jimhoyd-com/urlcode` to pull. After the release tag exists, build it from that checkout:
|
|
80
85
|
|
|
81
86
|
```sh
|
|
82
|
-
git clone --branch v0.
|
|
83
|
-
docker build -t urlcode:0.
|
|
84
|
-
docker run --rm -p 127.0.0.1:3000:3000 -v "$PWD:/project:ro" urlcode:0.
|
|
87
|
+
git clone --branch v0.4.1 https://github.com/jimhoyd-com/urlcode.git
|
|
88
|
+
docker build -t urlcode:0.4.1 urlcode
|
|
89
|
+
docker run --rm -p 127.0.0.1:3000:3000 -v "$PWD:/project:ro" urlcode:0.4.1 \
|
|
85
90
|
serve --project /project --host 0.0.0.0
|
|
86
91
|
```
|
|
87
92
|
|
|
@@ -10,6 +10,9 @@ ship, together with the declarations; `dist` is never committed. Make is an opti
|
|
|
10
10
|
shortcut layer; npm and the CLI work on Windows, macOS and Linux. No global
|
|
11
11
|
package install, hosting account, database or Docker is needed for the local loop.
|
|
12
12
|
|
|
13
|
+
For the repository's prose-only checks, CI selection and release helper commands,
|
|
14
|
+
see [the development pipeline](DEVELOPMENT-PIPELINE.md).
|
|
15
|
+
|
|
13
16
|
## Try the runtime
|
|
14
17
|
|
|
15
18
|
From the runtime checkout, `make dev` installs locked dependencies if needed and
|
package/docs/MIDDLEWARE.md
CHANGED
|
@@ -48,12 +48,18 @@ Every middleware and the function share the same request and context. Validated
|
|
|
48
48
|
with a fresh `context.state` object for this chain. State never survives the
|
|
49
49
|
request. Header edits are visible downstream; editing the request does not
|
|
50
50
|
reroute it or change already validated inputs. Request bodies are single-use:
|
|
51
|
-
reading one consumes it for downstream code.
|
|
52
|
-
API
|
|
51
|
+
reading one consumes it for downstream code. On a `sandbox: true` route there is
|
|
52
|
+
no `clone()` or streaming API at all, so pass parsed data through
|
|
53
|
+
`context.state`; a trusted route receives Node's own `Request`/`Response` and so
|
|
54
|
+
does have `clone()`, but passing parsed data through `context.state` keeps the
|
|
55
|
+
chain portable between the two modes.
|
|
53
56
|
|
|
54
57
|
Function responses support the existing text/JSON guest API. To transform their
|
|
55
|
-
body, read it and return a new `Response`.
|
|
56
|
-
download bodies are opaque and cannot be read
|
|
58
|
+
body, read it and return a new `Response`. On a `sandbox: true` route, native
|
|
59
|
+
redirect/respond/page/static/download bodies are opaque and cannot be read
|
|
60
|
+
through `text()` or `json()`; a trusted chain receives them as an ordinary
|
|
61
|
+
`Response` and can read them, so wrapping `respond: {text: hello}` and returning
|
|
62
|
+
`HELLO` works there and fails in the guest.
|
|
57
63
|
Returning the same native response preserves original bytes, including binary
|
|
58
64
|
files, ranges and HEAD lengths. You may add headers, but cannot change its
|
|
59
65
|
original status or existing native headers while preserving that body. To replace
|