@jimhoyd/urlcode 0.4.0-alpha.1 → 0.4.0-alpha.2
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 +24 -8
- package/.claude/skills/urlcode-operations/SKILL.md +10 -16
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +75 -62
- package/ROADMAP.md +61 -16
- package/SECURITY.md +23 -8
- package/dist/BUILD-MANIFEST.json +38 -43
- package/dist/agents-guide.js +18 -18
- package/dist/build-static.js +134 -0
- package/dist/capabilities.js +85 -31
- package/dist/capability-query.js +0 -1
- package/dist/cli.js +23 -31
- package/dist/compliance-rules/baseline.js +2 -10
- package/dist/compliance-rules/privacy.js +5 -16
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance.js +6 -8
- package/dist/config.js +15 -8
- package/dist/context.js +9 -10
- package/dist/examples.js +2 -2
- package/dist/explain-cli.js +3 -3
- package/dist/explain.js +5 -6
- package/dist/extensions.js +61 -2
- package/dist/function-sources.js +34 -2
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +3 -6
- package/dist/manifest.js +5 -7
- package/dist/mcp.js +1 -1
- package/dist/observability.js +1 -21
- package/dist/policies/cache.js +8 -3
- package/dist/policy.js +28 -9
- package/dist/project-tests.js +3 -3
- package/dist/readiness.js +32 -9
- package/dist/router.js +5 -7
- package/dist/runtime.js +77 -58
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/tooling.js +1 -1
- package/dist/trusted-functions.js +210 -0
- package/dist/types/build-static.d.ts +43 -0
- package/dist/types/capabilities.d.ts +14 -5
- package/dist/types/compliance-rules/shared.d.ts +0 -2
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/config.d.ts +2 -1
- package/dist/types/context.d.ts +2 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/extensions.d.ts +55 -0
- package/dist/types/function-sources.d.ts +4 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +3 -6
- package/dist/types/manifest.d.ts +1 -3
- package/dist/types/observability.d.ts +1 -14
- package/dist/types/project-tests.d.ts +1 -2
- package/dist/types/readiness.d.ts +10 -3
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +0 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/server.d.ts +1 -4
- package/dist/types/tooling.d.ts +3 -3
- package/dist/types/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +14 -7
- package/dist/types/verify-deployment.d.ts +2 -2
- package/dist/types.js +17 -4
- package/dist/typescript-authoring.js +55 -17
- package/dist/verify-deployment.js +3 -3
- package/docs/AI-AUTHORING.md +104 -9
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +3 -2
- package/docs/CAPABILITIES.md +29 -16
- package/docs/CAPACITY.md +128 -31
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/COMPLIANCE.md +6 -9
- package/docs/DEPLOYMENT-CHECKS.md +1 -1
- package/docs/EXTENSIONS.md +183 -11
- package/docs/FRAMEWORK.md +35 -19
- package/docs/FUNCTION-SECURITY.md +129 -32
- package/docs/INSTALL.md +0 -5
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/MIDDLEWARE.md +27 -16
- package/docs/MONITORING.md +2 -19
- package/docs/NEXT-PHASE-PLAN.md +12 -4
- package/docs/NEXT-STEPS.md +259 -40
- package/docs/OBSERVABILITY.md +7 -16
- package/docs/OPEN-DECISIONS.md +212 -0
- package/docs/OPERATIONAL-PROOF.md +26 -30
- package/docs/OPERATIONS.md +23 -32
- package/docs/POLICIES.md +15 -4
- package/docs/PRERENDER.md +2 -2
- package/docs/PROJECT-DIRECTION.md +34 -9
- package/docs/README.md +13 -11
- package/docs/RELEASE-READINESS.md +49 -29
- package/docs/RELEASE-SECURITY.md +89 -3
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +8 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +40 -0
- package/docs/SPECIFICATION.md +60 -26
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +8 -0
- package/docs/SPIKE-CORE-LAYERING.md +337 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +2 -2
- package/docs/SPIKE-EXTENSIONS.md +5 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +4 -2
- package/docs/SPIKE-MONOREPO.md +322 -0
- package/docs/STARTERS.md +1 -1
- package/docs/STATIC.md +94 -0
- package/docs/TOOLING.md +13 -9
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +27 -12
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/USABILITY-REVIEW.md +7 -1
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +205 -0
- package/docs/YAML-GUIDE.md +0 -3
- package/docs/YAML-REFERENCE.md +16 -6
- package/docs/policies/cache.md +13 -0
- package/examples/assets/example.yaml +1 -1
- package/examples/aws/example.yaml +1 -1
- package/examples/cloudflare/example.yaml +1 -1
- package/examples/conditions/example.yaml +1 -1
- package/examples/cookbook/example.yaml +1 -1
- package/examples/cookbook/middleware/bucket.mjs +12 -2
- package/examples/cookbook/middleware/locale.mjs +7 -3
- package/examples/egress/example.yaml +1 -1
- package/examples/extensions/example.yaml +1 -1
- package/examples/prerender/README.md +2 -2
- package/examples/prerender/example.yaml +1 -1
- package/examples/provider-conformance/example.yaml +1 -1
- package/examples/vercel/example.yaml +1 -1
- package/llms-full.txt +594 -219
- package/llms.txt +23 -12
- package/package.json +10 -3
- package/packaging/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +24 -8
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +10 -16
- package/recipes/authenticated-json-api/recipe.yaml +1 -1
- package/recipes/contact-form/recipe.yaml +1 -1
- package/recipes/cors-api/recipe.yaml +1 -1
- package/recipes/health-page/recipe.yaml +1 -1
- package/recipes/json-api/recipe.yaml +1 -1
- package/recipes/middleware/middleware/bucket.mjs +12 -2
- package/recipes/middleware/middleware/locale.mjs +7 -3
- package/recipes/middleware/recipe.yaml +1 -1
- package/recipes/protected-download/recipe.yaml +1 -1
- package/recipes/redirect/recipe.yaml +1 -1
- package/recipes/static-plus-api/recipe.yaml +1 -1
- package/recipes/typescript/README.md +2 -1
- package/recipes/typescript/recipe.yaml +1 -1
- package/recipes/webhook-receiver/README.md +5 -1
- package/recipes/webhook-receiver/recipe.yaml +2 -1
- package/recipes/webhook-receiver/urlcode.yaml +7 -0
- package/schemas/recipe.schema.json +4 -3
- package/schemas/urlcode.schema.json +14 -41
- package/skills/urlcode/SKILL.md +29 -8
- package/starters/default/AGENTS.md +18 -18
- package/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -40
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -37
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -8
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -61
- package/docs/MANAGEMENT-SECURITY.md +0 -82
- package/docs/links/cli.md +0 -110
- package/docs/links/limits.md +0 -175
- package/docs/links/management-api.md +0 -80
- package/docs/links/pools.md +0 -75
- package/docs/links/setup.md +0 -135
- package/docs/yaml/links.md +0 -30
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/example.yaml +0 -21
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: urlcode-authoring
|
|
3
|
-
description: Author or modify a URLCode project — write and edit urlcode.yaml routes, function and middleware modules, pages, static assets
|
|
3
|
+
description: Author or modify a URLCode project — write and edit urlcode.yaml routes, function and middleware modules, pages, static assets and downloads, then validate and test them. Use whenever a urlcode.yaml file is present or referenced, when the user mentions URLCode, @jimhoyd/urlcode, urlcode routes/handlers/policies/site keys, or asks for redirects or request functions in a URLCode project. Loads the implemented capability matrix so unsupported features are reported as gaps instead of invented.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Authoring URLCode projects
|
|
@@ -11,6 +11,15 @@ validates. Features outside that contract do not silently degrade — they fail
|
|
|
11
11
|
validation. So the cost of guessing is a broken project, and the whole job here
|
|
12
12
|
is to author only what the pinned revision implements and then prove it.
|
|
13
13
|
|
|
14
|
+
## Declarative-first default
|
|
15
|
+
|
|
16
|
+
> Use URLCode's highest-level declarative features whenever possible. Generate custom code only when the framework cannot express the requirement.
|
|
17
|
+
|
|
18
|
+
Check the installed version's primitives, YAML configuration, policies, supported
|
|
19
|
+
extensions and recipes/templates before writing a custom function or middleware.
|
|
20
|
+
Keep necessary custom code focused and report the capability gap; never invent
|
|
21
|
+
fields or bypass target limits or operator grants. See `docs/PROJECT-DIRECTION.md` in the installed runtime.
|
|
22
|
+
|
|
14
23
|
## Read the contract before writing YAML
|
|
15
24
|
|
|
16
25
|
Documentation, schema and runtime must come from the **same revision**. Read from
|
|
@@ -35,8 +44,9 @@ checkout you are working in — never from memory of another version.
|
|
|
35
44
|
tests and the pinned runtime version. Preserve the user's organization,
|
|
36
45
|
naming and unrelated routes.
|
|
37
46
|
- Choose exactly one handler per route — `function`, `redirect`, `respond`,
|
|
38
|
-
`page`, `static`, `download`
|
|
39
|
-
Prefer a native handler when code is
|
|
47
|
+
`page`, `static`, `download`, `conditional`, `proxy` or an `extension` mount
|
|
48
|
+
— plus optional ordered middleware. Prefer a native handler when code is
|
|
49
|
+
unnecessary.
|
|
40
50
|
- Declare each path placeholder as a required string. Paths match whole
|
|
41
51
|
segments: no regex, no greedy captures, no wildcard handlers.
|
|
42
52
|
- Bind typed inputs through `args` or context. There is no `${...}`
|
|
@@ -56,8 +66,14 @@ mistakes that recur:
|
|
|
56
66
|
- No YAML anchors, aliases, template interpolation or remote includes.
|
|
57
67
|
- No recursive includes or glob discovery; includes are explicit.
|
|
58
68
|
- No regex, optional or greedy route segments, and no host-based routing.
|
|
59
|
-
-
|
|
60
|
-
npm
|
|
69
|
+
- `function`/`middleware` routes run trusted and unsandboxed by default: full
|
|
70
|
+
Node, npm, filesystem and `fetch` access, in-process, like any other project
|
|
71
|
+
code. `sandbox: true` opts a route into isolation — reach for it when that
|
|
72
|
+
route's own code warrants it (untrusted input, an unreviewed contribution, a
|
|
73
|
+
particularly sensitive secret), not reflexively on every route. A
|
|
74
|
+
`sandbox: true` route gets a text/JSON `Request`/`Response` sandbox only:
|
|
75
|
+
**no** `fetch`, Node or npm APIs, filesystem, WebSocket, streaming or crypto
|
|
76
|
+
API.
|
|
61
77
|
- No global middleware, Express compatibility or automatic auth.
|
|
62
78
|
- `policies` accepts only `throttle`, `agents`, `security`, `compression` and
|
|
63
79
|
`cache`, every key off unless declared; `hardened` is the only built-in
|
|
@@ -68,9 +84,9 @@ mistakes that recur:
|
|
|
68
84
|
only and off unless declared; a declared route at the same path wins. Its
|
|
69
85
|
generated routes count toward `--expect-routes`, and `site.sitemap` needs
|
|
70
86
|
`--origin` on every command that activates the project.
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
87
|
+
- There is no native `link` handler or `dynamicLinks` project flag. Stored
|
|
88
|
+
short links are moving to a future `urlcode-dynamic-link` extension package,
|
|
89
|
+
not yet published; report that as a gap, never invent a `link` field.
|
|
74
90
|
- Infrastructure (proxy ranges, storage URLs, vendor rule identifiers) is an
|
|
75
91
|
operator flag, never route YAML.
|
|
76
92
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: urlcode-operations
|
|
3
|
-
description: Deploy, verify, monitor and operate a URLCode project — process/container deployment, release readiness, verifying a live deployment against the project, capacity/audit/benchmark, observability, DDoS/overload resilience, and
|
|
3
|
+
description: Deploy, verify, monitor and operate a URLCode project — process/container deployment, release readiness, verifying a live deployment against the project, capacity/audit/benchmark, observability, DDoS/overload resilience, and operator binding grants. Use when the user asks to deploy, check readiness, verify a running deployment, size/benchmark a project, monitor it, plan for overload, or manage bindings. Reports operational limits and unimplemented capabilities as gaps instead of inventing mitigations.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Operating a URLCode deployment
|
|
@@ -30,9 +30,7 @@ another version.
|
|
|
30
30
|
overload and DDoS; what layer each defense belongs to.
|
|
31
31
|
6. `docs/MONITORING.md` and `docs/OBSERVABILITY.md` — health/ready probes,
|
|
32
32
|
logs, metrics format, what is and is not exported.
|
|
33
|
-
7. `docs/
|
|
34
|
-
policy shape, scope, loopback-only binding.
|
|
35
|
-
8. `docs/POLICIES.md` and `docs/FUNCTION-SECURITY.md` — per-target policy
|
|
33
|
+
7. `docs/POLICIES.md` and `docs/FUNCTION-SECURITY.md` — per-target policy
|
|
36
34
|
support and the operator binding-grant process, needed whenever a
|
|
37
35
|
deployment or verification step touches either.
|
|
38
36
|
|
|
@@ -71,8 +69,8 @@ urlcode verify-deployment --project ./my-links --target https://links.example \
|
|
|
71
69
|
Run the actual commands and report actual results, never "should work" or
|
|
72
70
|
"should be reachable". `verify-deployment` needs a real target; do not
|
|
73
71
|
simulate its output. In a runtime checkout, substitute `node src/cli.ts` for
|
|
74
|
-
`urlcode`. Pass `--policy
|
|
75
|
-
|
|
72
|
+
`urlcode`. Pass `--policy` where a snapshot needs bindings already reviewed
|
|
73
|
+
by the operator.
|
|
76
74
|
|
|
77
75
|
## Hard limits — report these as gaps, never invent around them
|
|
78
76
|
|
|
@@ -84,12 +82,9 @@ already reviewed by the operator.
|
|
|
84
82
|
- `verify-deployment` has no infrastructure access, uses no credential,
|
|
85
83
|
follows no redirect and offers no `--insecure`. It cannot check anything a
|
|
86
84
|
read-only HTTP probe cannot observe.
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- A management credentials policy is operator-owned, outside the application,
|
|
91
|
-
never in YAML or Git, at most 64 KiB, mode 600, at most 128 credentials with
|
|
92
|
-
explicit collection/action allowlists — no wildcards.
|
|
85
|
+
- Core has no durable store and no private management API of its own; stored
|
|
86
|
+
short links are moving to a future `urlcode-dynamic-link` extension
|
|
87
|
+
package, not yet published.
|
|
93
88
|
- Sandbox concurrency, worker slots and execution deadlines are shared across
|
|
94
89
|
every programmable route in a snapshot; there is no per-route fairness or
|
|
95
90
|
reserved capacity, and awaiting a guest timer still occupies a slot.
|
|
@@ -102,10 +97,9 @@ responsibility that covers it instead of inventing a flag.
|
|
|
102
97
|
|
|
103
98
|
## Boundaries
|
|
104
99
|
|
|
105
|
-
- Never generate or approve an operator binding grant
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
real secret.
|
|
100
|
+
- Never generate or approve an operator binding grant on the user's behalf.
|
|
101
|
+
That is the operator's own reviewed decision; produce the shape and let
|
|
102
|
+
them fill in and store the real secret.
|
|
109
103
|
- Keep every credential, token and policy file out of source, examples and
|
|
110
104
|
Git. A synthetic example value is fine; a real one is never committed.
|
|
111
105
|
- Do not deploy, expose a service, rotate a credential, or run
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# URLCode
|
|
2
2
|
|
|
3
3
|
**A portable runtime for programmable URL behavior, and the framework that grows
|
|
4
|
-
from it.** Declare an application's public URL surface in YAML, add
|
|
5
|
-
|
|
4
|
+
from it.** Declare an application's public URL surface in YAML, add JavaScript
|
|
5
|
+
only where declarative handlers are not enough, and run the same
|
|
6
6
|
project locally, in a container, on your own infrastructure or on a provider
|
|
7
7
|
adapter. When the project gets serious, add accounts and an administration
|
|
8
8
|
console as operator-installed extensions instead of building them again.
|
|
@@ -26,16 +26,22 @@ infrastructure for AI-built software, not a framework for building AI models.
|
|
|
26
26
|
|
|
27
27
|
A project is a `urlcode.yaml` with `version: "1"`. Each route has exactly one
|
|
28
28
|
handler: `redirect`, `respond`, `page`, `static`, `download`, `function`,
|
|
29
|
-
`
|
|
29
|
+
`proxy`, `conditional` or an `extension` mount, with optional ordered
|
|
30
30
|
`middleware`. The runtime validates the whole project before serving it,
|
|
31
31
|
compiles it once, and refuses anything a target cannot enforce with the route
|
|
32
|
-
named. Functions
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
named. Functions and middleware run trusted, in-process, with full Node
|
|
33
|
+
access by default; a route opts into an isolated QuickJS/WebAssembly sandbox
|
|
34
|
+
with a fresh heap per call and no Node, filesystem or network by declaring
|
|
35
|
+
`sandbox: true`. Either way, secrets reach them only through operator grants
|
|
36
|
+
pinned to the project revision.
|
|
37
|
+
|
|
38
|
+
URLCode is not a URL shortener: stored short links are an operator-installed
|
|
39
|
+
extension, not core's job. It is not a
|
|
40
|
+
general Node web framework: routing, validation, middleware wiring and
|
|
41
|
+
policies are declared in YAML, not hand-wired; isolating a specific route's
|
|
42
|
+
code from the host is an explicit `sandbox: true` opt-in, not something every
|
|
43
|
+
route gets by writing a handler. It is not a provider configuration format:
|
|
44
|
+
infrastructure settings stay out of route YAML.
|
|
39
45
|
See [project direction](docs/PROJECT-DIRECTION.md).
|
|
40
46
|
|
|
41
47
|
## The framework
|
|
@@ -47,10 +53,20 @@ an AI agent must follow are in [the framework](docs/FRAMEWORK.md).
|
|
|
47
53
|
|
|
48
54
|
| Package | Adds | Status |
|
|
49
55
|
|---|---|---|
|
|
50
|
-
| [urlcode](https://github.com/jimhoyd-com/urlcode) (this repository) | Runtime, CLI, policies,
|
|
51
|
-
| [urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui) | Shared presentation: escaped templates, shadcn/ui partials, themes, translations | `0.1.0-alpha.
|
|
52
|
-
| [urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth) | Accounts: password, passkeys, OIDC, email codes, TOTP, sessions, roles, account page | `0.1.0-alpha.
|
|
53
|
-
| [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin) | Administration: users, sessions, roles, audit, approvals, cases, impersonation | `0.1.0-alpha.
|
|
56
|
+
| [urlcode](https://github.com/jimhoyd-com/urlcode) (this repository) | Runtime, CLI, policies, provider adapters, extension contract | `0.4.0-alpha.2` (alpha) on top of the `0.3.0` release, Apache-2.0 |
|
|
57
|
+
| [urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui) | Shared presentation: escaped templates, shadcn/ui partials, themes, translations | `0.1.0-alpha.5` on npm, alpha: review pending |
|
|
58
|
+
| [urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth) | Accounts: password, passkeys, OIDC, email codes, TOTP, sessions, roles, account page | `0.1.0-alpha.3` on npm, alpha: review pending |
|
|
59
|
+
| [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin) | Administration: users, sessions, roles, audit, approvals, cases, impersonation | `0.1.0-alpha.3` on npm, alpha: review pending |
|
|
60
|
+
| [urlcode-dynamic-link](https://github.com/jimhoyd-com/urlcode-dynamic-link) | Stored short links: the mount-based successor to core's removed `link` handler | `0.1.0-alpha.2` on npm, alpha: review pending |
|
|
61
|
+
| [urlcode-middleware](https://github.com/jimhoyd-com/urlcode-middleware) | Per-route middleware through the extension seam, alongside core's native array | `0.1.0-alpha.2` on npm, alpha: review pending |
|
|
62
|
+
| [urlcode-short](https://github.com/jimhoyd-com/urlcode-short) | A complete link shortener assembled from the packages above | `0.1.0-alpha.2` on npm, alpha: review pending |
|
|
63
|
+
|
|
64
|
+
Every version in this table is the one published to npm under the `alpha`
|
|
65
|
+
dist-tag, and they are released together in the order core → ui → auth →
|
|
66
|
+
admin → dynamic-link/middleware → short. The authoritative cross-repository
|
|
67
|
+
register, including each package's declared peer ranges and the rules that
|
|
68
|
+
keep them consistent, is
|
|
69
|
+
[docs/VERSION-ALIGNMENT.md](docs/VERSION-ALIGNMENT.md).
|
|
54
70
|
|
|
55
71
|
```yaml
|
|
56
72
|
version: "1"
|
|
@@ -74,23 +90,26 @@ it. Cross-repository acceptance is tracked in
|
|
|
74
90
|
|
|
75
91
|
## Status
|
|
76
92
|
|
|
77
|
-
`0.4.0-alpha.
|
|
78
|
-
agent tooling, on top of the `0.3.0` self-hosted release.
|
|
79
|
-
extension contract, capabilities and provider conformance, strict
|
|
80
|
-
interchange, bulk import, recipes and search, TypeScript guest
|
|
81
|
-
conditions, bounded proxy and signals, and the MCP read and
|
|
82
|
-
|
|
93
|
+
`0.4.0-alpha.2` is the current release of the extension contract and the
|
|
94
|
+
agent tooling, on top of the `0.3.0` self-hosted release. `0.4.0-alpha.1`
|
|
95
|
+
added the extension contract, capabilities and provider conformance, strict
|
|
96
|
+
redirect interchange, bulk import, recipes and search, TypeScript guest
|
|
97
|
+
authoring, conditions, bounded proxy and signals, and the MCP read and
|
|
98
|
+
authoring modes. `0.4.0-alpha.2` then made `function` and `middleware` routes
|
|
99
|
+
run trusted and unsandboxed by default, with `sandbox: true` as a per-route
|
|
100
|
+
opt-in, and removed the native `link:`/`dynamicLinks:` YAML shape. That is a
|
|
101
|
+
behaviour change for existing projects with no YAML edit; read
|
|
102
|
+
[the roadmap entry](ROADMAP.md) before upgrading. Use the schema and docs from
|
|
103
|
+
the runtime revision you run.
|
|
83
104
|
The [roadmap](ROADMAP.md) separates implemented from planned, and
|
|
84
105
|
[release readiness](docs/RELEASE-READINESS.md) records what is proven and
|
|
85
106
|
what is not: provider deployments, soak and independent security review
|
|
86
107
|
remain open.
|
|
87
108
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
runs on any supported Node.
|
|
93
|
-
See [pool controls and scaling limits](docs/DYNAMIC-LINKS.md#separate-reader-and-writer-pools).
|
|
109
|
+
Stored short links have moved out of core into
|
|
110
|
+
[urlcode-dynamic-link](https://github.com/jimhoyd-com/urlcode-dynamic-link)
|
|
111
|
+
(mount-based, like `auth`/`admin`, published on npm); core no longer has a
|
|
112
|
+
native `link` handler.
|
|
94
113
|
|
|
95
114
|
URLCode is free and open-source software licensed under the
|
|
96
115
|
[Apache License 2.0](LICENSE). Commercial use, modification, redistribution and
|
|
@@ -123,42 +142,36 @@ npm ci
|
|
|
123
142
|
npm run dev
|
|
124
143
|
```
|
|
125
144
|
|
|
126
|
-
Live stored-link routes require **`dynamicLinks: true`** in the entry `urlcode.yaml`;
|
|
127
|
-
the starter explicitly sets false. Ordinary functions and parameterized redirects
|
|
128
|
-
do not need it. [Live-link setup](docs/DYNAMIC-LINKS.md).
|
|
129
|
-
|
|
130
145
|
## Built with URLCode
|
|
131
146
|
|
|
132
|
-
[urlcode-
|
|
133
|
-
standalone, account-free demo built on URLCode's public runtime
|
|
147
|
+
[urlcode-short](https://github.com/jimhoyd-com/urlcode-short) is a
|
|
148
|
+
standalone, account-free demo built on URLCode's public runtime. It predates
|
|
149
|
+
this repository's removal of the native link-store API from core; its
|
|
150
|
+
retrospective should be read alongside that change, not as current guidance.
|
|
134
151
|
It combines short links that expire after one hour or less, QR downloads, and a
|
|
135
|
-
shadcn/ui + Tailwind frontend. URLCode handles the page/assets and
|
|
136
|
-
|
|
152
|
+
shadcn/ui + Tailwind frontend. URLCode handles the page/assets and routing; the
|
|
153
|
+
application adds anonymous creation, stored-link storage and its own limits.
|
|
137
154
|
|
|
138
|
-
Read its [build retrospective](https://github.com/jimhoyd-com/urlcode-
|
|
155
|
+
Read its [build retrospective](https://github.com/jimhoyd-com/urlcode-short/blob/main/docs/BUILD-RETROSPECTIVE.md)
|
|
139
156
|
for what the runtime supplied, what the application still needed, and proposed
|
|
140
157
|
improvements. The demo's license, hosting and production validation remain open;
|
|
141
158
|
it does not change URLCode's Apache-2.0 license or guest isolation model.
|
|
142
159
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
for reuse, integration work and upstream improvements. Hosting and a public domain
|
|
150
|
-
are not yet selected; the original site-code license is pending.
|
|
160
|
+
`urlcode-docs` demonstrates URLCode hosting a static documentation site with
|
|
161
|
+
shadcn/ui and Tailwind: content authored directly in that repository, applying
|
|
162
|
+
templates through its own sandbox-opted-in (`sandbox: true`) middleware during
|
|
163
|
+
the build, served through native page/static/download routes. That repository
|
|
164
|
+
is currently private, so it isn't publicly browsable yet. Hosting and a public
|
|
165
|
+
domain are not yet selected; the original site-code license is pending.
|
|
151
166
|
|
|
152
167
|
## Start from YAML
|
|
153
168
|
|
|
154
169
|
Already wrote `urlcode.yaml`? Run `urlcode scaffold --project ./my-links --dry-run`,
|
|
155
170
|
then remove `--dry-run` to create missing modules, pages and directories. Existing
|
|
156
171
|
files are preserved; code placeholders return 501 until implemented.
|
|
157
|
-
[Scaffolding guide](docs/SCAFFOLDING.md).
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
everything else runs on any supported Node (22.13+ installed, 22.18+ to run
|
|
161
|
-
the TypeScript source).
|
|
172
|
+
[Scaffolding guide](docs/SCAFFOLDING.md). Node 22.13+ installed, 22.18+ to run
|
|
173
|
+
the TypeScript source; the separate `urlcode-auth` extension may have its own
|
|
174
|
+
SQLite build requirement, unverified from this repository.
|
|
162
175
|
|
|
163
176
|
## Try it
|
|
164
177
|
|
|
@@ -204,9 +217,6 @@ and [middleware](docs/MIDDLEWARE.md).
|
|
|
204
217
|
|
|
205
218
|
- **Pages, files, downloads:** `page`, `static`, `download` with MIME detection,
|
|
206
219
|
ETags, ranges and safety limits. [Assets](docs/ASSETS.md).
|
|
207
|
-
- **Live short links:** a `link` route on an optional SQLite store; create,
|
|
208
|
-
update and delete without reloads through the CLI or the private management
|
|
209
|
-
API. [Dynamic links](docs/DYNAMIC-LINKS.md).
|
|
210
220
|
- **HTTP:** methods, validated path/query/header inputs, body limits, response
|
|
211
221
|
headers and cookies. [HTTP](docs/HTTP.md).
|
|
212
222
|
- **Policies and site conventions:** throttle, agents, security headers,
|
|
@@ -227,11 +237,13 @@ and [middleware](docs/MIDDLEWARE.md).
|
|
|
227
237
|
Self-hosted Node process or container first. `@jimhoyd/urlcode/vercel` and
|
|
228
238
|
`@jimhoyd/urlcode/aws` serve declarative projects as native handlers;
|
|
229
239
|
`urlcode build --target cloudflare` compiles redirects and declared responses
|
|
230
|
-
into a Worker
|
|
240
|
+
into a Worker; `urlcode build --target static` compiles redirects and static
|
|
241
|
+
files into plain objects and redirect metadata for S3 + CloudFront, with no
|
|
242
|
+
server at all. Each target refuses at activation or build time what it cannot
|
|
231
243
|
run, with the route named. None has been exercised on its provider yet; the
|
|
232
244
|
adapters have local conformance tests only. [Operations](docs/OPERATIONS.md),
|
|
233
245
|
[capabilities](docs/CAPABILITIES.md), [Vercel](docs/VERCEL.md), [AWS](docs/AWS.md),
|
|
234
|
-
[Cloudflare](docs/CLOUDFLARE.md).
|
|
246
|
+
[Cloudflare](docs/CLOUDFLARE.md), [static hosting](docs/STATIC.md).
|
|
235
247
|
|
|
236
248
|
## For AI agents
|
|
237
249
|
|
|
@@ -244,10 +256,11 @@ inspection, validation and conversion previews over stdio, and
|
|
|
244
256
|
|
|
245
257
|
## Documentation
|
|
246
258
|
|
|
247
|
-
Full documentation
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
Full documentation is authored in a separate `urlcode-docs` repository, where
|
|
260
|
+
new guides, references and recipes belong — but that repository is currently
|
|
261
|
+
private, so its content isn't publicly browsable yet. Until it's made public,
|
|
262
|
+
the practical reference is this README and [`docs/`](docs/README.md) in this
|
|
263
|
+
repository.
|
|
251
264
|
|
|
252
265
|
`docs/` in this repository is contributor and maintainer material — local
|
|
253
266
|
development, CI, the release process, reviews and the generated field
|
|
@@ -256,11 +269,11 @@ reference. Reader-facing pages still under `docs/` are being migrated.
|
|
|
256
269
|
## Built with URLCode
|
|
257
270
|
|
|
258
271
|
[urlcode-short](https://github.com/jimhoyd-com/urlcode-short), an
|
|
259
|
-
account-free short-link demo with a shadcn/ui front end, and
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
account-free short-link demo with a shadcn/ui front end, and `urlcode-docs`, a
|
|
273
|
+
static documentation site rendered through its own sandbox-opted-in middleware
|
|
274
|
+
at build time (currently a private repository). Both are ordinary consumers of
|
|
275
|
+
the public runtime; urlcode-short's retrospective lists what the runtime
|
|
276
|
+
supplied and what it still had to build.
|
|
264
277
|
|
|
265
278
|
## License and contributing
|
|
266
279
|
|
package/ROADMAP.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Public roadmap
|
|
2
2
|
|
|
3
3
|
URLCode is a portable runtime for programmable URL behavior, not a URL
|
|
4
|
-
shortener.
|
|
4
|
+
shortener. Stored short links are an operator-installed extension, not a core
|
|
5
|
+
handler. The
|
|
5
6
|
[project direction](docs/PROJECT-DIRECTION.md) explains how application
|
|
6
7
|
projects and provider adapters fit without redefining or restricting the free
|
|
7
8
|
runtime.
|
|
@@ -11,7 +12,37 @@ separate late phase. The stable 0.1 self-hosted release covers much of M0/M1 plu
|
|
|
11
12
|
process/container packaging and benchmarks. Provider adapters and the remaining
|
|
12
13
|
production-readiness gates remain open.
|
|
13
14
|
|
|
14
|
-
## 0.4.0-alpha.
|
|
15
|
+
## 0.4.0-alpha.2 — current alpha
|
|
16
|
+
|
|
17
|
+
`0.4.0-alpha.2` is a behavior-changing release on top of `0.4.0-alpha.1`:
|
|
18
|
+
**`function` and `middleware` routes now run trusted and unsandboxed by
|
|
19
|
+
default** — in the host process, with full Node/filesystem/network access,
|
|
20
|
+
exactly like any other project code — instead of always dispatching through
|
|
21
|
+
the QuickJS/WebAssembly worker pool. Sandboxing is now an explicit per-route
|
|
22
|
+
opt-in via `sandbox: true`; a route that declares it gets exactly the
|
|
23
|
+
isolation every earlier alpha provided, unchanged. See
|
|
24
|
+
[docs/SPIKE-DEFAULT-TRUST-MODEL.md](docs/SPIKE-DEFAULT-TRUST-MODEL.md) for
|
|
25
|
+
the maintainer's decision and rationale, and
|
|
26
|
+
[docs/FUNCTION-SECURITY.md](docs/FUNCTION-SECURITY.md) for the resulting
|
|
27
|
+
contract of both execution modes.
|
|
28
|
+
|
|
29
|
+
**This changes existing projects with no YAML edit.** Every `function`/
|
|
30
|
+
`middleware` route that does not declare `sandbox` — which, before this
|
|
31
|
+
release, meant every such route in every existing project — now runs trusted
|
|
32
|
+
instead of sandboxed the moment the runtime is upgraded to `0.4.0-alpha.2` or
|
|
33
|
+
later. Binding grants (`env`/`secrets`) are unaffected: a route still
|
|
34
|
+
receives only what it declares and an operator policy pins to the project
|
|
35
|
+
revision, whether trusted or sandboxed. Review which of your project's
|
|
36
|
+
`function`/`middleware` routes handle input or code you would not otherwise
|
|
37
|
+
trust with full Node/filesystem/network access, and add `sandbox: true` to
|
|
38
|
+
those specifically (docs/AI-AUTHORING.md's "Deciding when a route needs
|
|
39
|
+
`sandbox: true`") before upgrading a project that relies on the old,
|
|
40
|
+
always-sandboxed behavior. An operator policy pinned to a project's revision
|
|
41
|
+
is invalidated by this upgrade regardless of whether the project's own YAML
|
|
42
|
+
changed, since the project hash includes the trust-model-affecting change;
|
|
43
|
+
re-derive and re-approve it (`urlcode permissions`) after upgrading.
|
|
44
|
+
|
|
45
|
+
## 0.4.0-alpha.1
|
|
15
46
|
|
|
16
47
|
`0.4.0-alpha.1` is the first alpha of the extension contract and the agent
|
|
17
48
|
tooling on top of the `0.3.0` self-hosted release. It carries: the
|
|
@@ -86,8 +117,10 @@ signals. See [conditions](docs/CONDITIONS.md), [egress](docs/EGRESS.md),
|
|
|
86
117
|
|
|
87
118
|
Bundled Git-owned recipes, safe bulk imports into route includes, build-time
|
|
88
119
|
TypeScript guest transpilation, read-only inspection APIs and optional stdio
|
|
89
|
-
MCP tooling are available. The runtime still executes only JavaScript
|
|
90
|
-
|
|
120
|
+
MCP tooling are available. The runtime still executes only JavaScript, and
|
|
121
|
+
TypeScript authoring adds no execution mode: transpilation happens at build
|
|
122
|
+
time, is not type checking, and a `sandbox: true` route's emitted JavaScript
|
|
123
|
+
runs inside QuickJS/WASM exactly as before. Bulk benchmarks
|
|
91
124
|
successfully cover 1,000, 10,000 and 100,000 routes without relaxing parser
|
|
92
125
|
limits. See [recipes](docs/RECIPES.md), [bulk evidence](docs/BULK.md),
|
|
93
126
|
[TypeScript authoring](docs/TYPESCRIPT-AUTHORING.md) and
|
|
@@ -140,9 +173,10 @@ deployment returns byte-identical status, body and headers to the self-hosted
|
|
|
140
173
|
server. Bindings arrive through a `URLCODE_POLICY` environment variable holding
|
|
141
174
|
the same revision-pinned grant document the operator policy file carries.
|
|
142
175
|
|
|
143
|
-
Native handlers only:
|
|
144
|
-
|
|
145
|
-
|
|
176
|
+
Native handlers only: `function` and `middleware` routes are refused at
|
|
177
|
+
activation, trusted or sandboxed alike, because they need the self-hosted Node
|
|
178
|
+
lifecycle and a sandboxed one would pay worker and WASM startup on every cold
|
|
179
|
+
start. The
|
|
146
180
|
`@jimhoyd/urlcode/aws` does the same for a Lambda Function URL or API Gateway HTTP API.
|
|
147
181
|
Payload format 2.0 only: format 1.0 supplies an already-decoded path and query,
|
|
148
182
|
and this runtime rejects ambiguous encoding deliberately, so rebuilding a target
|
|
@@ -161,7 +195,7 @@ generation, so it gets a compiler rather than an adapter: `urlcode build
|
|
|
161
195
|
validators, and `@jimhoyd/urlcode/cloudflare` serves them with the same matching, request
|
|
162
196
|
policy and response policy as every other host. Declarative routes only —
|
|
163
197
|
redirects and declared responses with parameters, defaults, validation, response
|
|
164
|
-
headers, `enabled` and `expires`. Functions, middleware,
|
|
198
|
+
headers, `enabled` and `expires`. Functions, middleware, assets and
|
|
165
199
|
bindings are refused at build time with the route named, so an unsupported
|
|
166
200
|
project fails the build instead of the deployment. Bindings are refused even as
|
|
167
201
|
literals, because a build artifact must never carry a secret.
|
|
@@ -202,18 +236,25 @@ does not cover.
|
|
|
202
236
|
|
|
203
237
|
## Hardening checkpoint — alpha.8
|
|
204
238
|
|
|
205
|
-
Bound HTTP admission and inactive sockets,
|
|
206
|
-
|
|
239
|
+
Bound HTTP admission and inactive sockets, and correct management
|
|
240
|
+
defaults/method responses.
|
|
207
241
|
The [readiness register](docs/RELEASE-READINESS.md) distinguishes tested safeguards
|
|
208
242
|
from deployment and stable-release gates. Feature breadth does not imply stability.
|
|
209
243
|
|
|
210
|
-
## Live short links — alpha.8
|
|
244
|
+
## Live short links — alpha.8 (removed from core, superseded)
|
|
211
245
|
|
|
212
246
|
Implemented an optional native `link` handler, local SQLite persistence, CLI CRUD
|
|
213
|
-
and a separate authenticated management API. Links
|
|
214
|
-
changes/reloads; versioned writes
|
|
215
|
-
or network access
|
|
216
|
-
user accounts and provider adapters
|
|
247
|
+
and a separate authenticated management API. Links became visible without YAML
|
|
248
|
+
changes/reloads; versioned writes prevented silent lost updates. No guest storage
|
|
249
|
+
or network access was added. Same-host only; distributed storage, general state,
|
|
250
|
+
user accounts and provider adapters remained open.
|
|
251
|
+
|
|
252
|
+
This native `link` handler, its SQLite store, CLI and management API were
|
|
253
|
+
removed from core in the layering work that followed: stored short links are
|
|
254
|
+
moving to a future `urlcode-dynamic-link` extension package (mount-based, like
|
|
255
|
+
`auth`/`admin`, not yet published). A project that used `link`/`dynamicLinks`
|
|
256
|
+
needs that extension once it ships; there is no in-core replacement or
|
|
257
|
+
deprecation shim.
|
|
217
258
|
|
|
218
259
|
## Middleware — alpha.7
|
|
219
260
|
|
|
@@ -254,13 +295,17 @@ Bulk tools, recipes and best-effort signals were added in the unreleased next-ph
|
|
|
254
295
|
|
|
255
296
|
## Security correction — 0.1.0-alpha.2
|
|
256
297
|
|
|
298
|
+
<!-- trust-model-prose: historical -->
|
|
257
299
|
All function code is untrusted. Node host execution has been replaced by
|
|
258
300
|
QuickJS/WebAssembly isolation with fresh invocation state, no ambient host or
|
|
259
301
|
network APIs, bounded resources, restricted module graphs and revision-pinned
|
|
260
302
|
operator binding policy. This protection is part of the free product. See the
|
|
261
303
|
[security model](docs/FUNCTION-SECURITY.md). Full Fetch/Node
|
|
262
304
|
API compatibility and network integrations were not part of that alpha and
|
|
263
|
-
remain outside the 0.1 contract.
|
|
305
|
+
remain outside the 0.1 contract. That default was superseded in
|
|
306
|
+
`0.4.0-alpha.2`, which made this isolation the per-route `sandbox: true`
|
|
307
|
+
opt-in instead (see
|
|
308
|
+
[docs/SPIKE-DEFAULT-TRUST-MODEL.md](docs/SPIKE-DEFAULT-TRUST-MODEL.md)).
|
|
264
309
|
|
|
265
310
|
## Earlier implementation checkpoint — 0.1.0-alpha.1
|
|
266
311
|
|
package/SECURITY.md
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
Project `function`/`middleware` code is **trusted and unsandboxed by default**:
|
|
4
|
+
it runs directly in the host process, exactly like any other project code,
|
|
5
|
+
with full Node, filesystem and network access (docs/SPIKE-DEFAULT-TRUST-MODEL.md).
|
|
6
|
+
A route opts into isolation explicitly with `sandbox: true`, which dispatches
|
|
7
|
+
that route through the QuickJS/WebAssembly worker pool instead — unchanged
|
|
8
|
+
from the isolation this project has always provided, still the boundary to
|
|
9
|
+
reach for when a route's code specifically warrants it (input from a source
|
|
10
|
+
the project doesn't fully trust, a contribution nobody has reviewed, logic
|
|
11
|
+
handling an especially sensitive secret).
|
|
12
|
+
|
|
13
|
+
A `sandbox: true` guest has no Node, filesystem, shell, network or ambient
|
|
14
|
+
process-environment access. Each invocation gets fresh state and bounded
|
|
15
|
+
resources. Imports stay inside a snapshotted project module graph. Binding
|
|
16
|
+
grants — for a trusted route as much as a sandboxed one — come from operator
|
|
17
|
+
policy outside the project and are pinned to the configuration/code revision;
|
|
18
|
+
trusting a route's code by default does not grant it any `env`/`secrets` it
|
|
19
|
+
was not explicitly declared and pinned to receive. This is a claim about what
|
|
20
|
+
URLCode injects into `context.env`/`context.secrets` for a route, not an
|
|
21
|
+
access-control boundary on trusted code itself: a trusted (non-`sandbox`)
|
|
22
|
+
route runs with full Node access by design, so its own code can read
|
|
23
|
+
`process.env`, the filesystem or the network independently of anything the
|
|
24
|
+
binding grant declared or withheld. The grant only governs what URLCode hands
|
|
25
|
+
that code through `context`; it is not a restriction the code is confined to.
|
|
11
26
|
See the [security model and policy instructions](docs/FUNCTION-SECURITY.md).
|
|
12
27
|
|
|
13
28
|
The host/runtime and sandbox engine still require patching, independent review
|