@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.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 +106 -0
- package/.claude/skills/urlcode-operations/SKILL.md +114 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/CONTRIBUTING.md +30 -2
- package/README.md +157 -230
- package/ROADMAP.md +85 -2
- package/SECURITY.md +8 -1
- package/dist/BUILD-MANIFEST.json +62 -32
- package/dist/adapters.js +4 -23
- package/dist/agent-lists.js +1 -1
- package/dist/agents-guide.js +113 -0
- package/dist/authoring-files.js +60 -0
- package/dist/authoring.js +11 -1
- package/dist/aws.js +4 -3
- package/dist/build-cloudflare.js +11 -24
- package/dist/bulk.js +37 -0
- package/dist/capabilities.js +208 -0
- package/dist/capability-query.js +72 -0
- package/dist/catalog.js +105 -0
- package/dist/cli.js +154 -15
- package/dist/client-address.js +1 -1
- package/dist/compliance-rules/baseline.js +8 -8
- package/dist/compliance-rules/privacy.js +3 -3
- package/dist/compliance-rules/strict.js +5 -5
- package/dist/conditions.js +88 -0
- package/dist/config.js +60 -4
- package/dist/context.js +156 -0
- package/dist/ecosystem-cli.js +88 -0
- package/dist/egress.js +98 -0
- package/dist/examples.js +92 -0
- package/dist/explain-cli.js +64 -0
- package/dist/explain.js +132 -0
- package/dist/extensions.js +172 -0
- package/dist/function-sources.js +15 -3
- package/dist/index.js +37 -0
- package/dist/init-with.js +165 -0
- package/dist/interchange-cli.js +42 -0
- package/dist/interchange.js +189 -0
- package/dist/link-cli.js +1 -1
- package/dist/management-policy.js +0 -1
- package/dist/manifest.js +111 -0
- package/dist/match.js +2 -2
- package/dist/mcp-authoring.js +147 -0
- package/dist/mcp.js +97 -0
- package/dist/observability.js +6 -0
- package/dist/operator-host.js +29 -0
- package/dist/plugins.js +12 -0
- package/dist/policies/agents.js +2 -2
- package/dist/policies/compression.js +2 -1
- package/dist/policies/security.js +0 -0
- package/dist/policies.js +1 -1
- package/dist/policy.js +29 -7
- package/dist/prerender.js +100 -41
- package/dist/project-tests.js +3 -3
- package/dist/provider-verification.js +92 -0
- package/dist/proxy.js +44 -0
- package/dist/readiness.js +5 -5
- package/dist/recipes.js +41 -0
- package/dist/route-diff.js +106 -0
- package/dist/router.js +42 -2
- package/dist/runtime.js +95 -14
- package/dist/schema-query.js +62 -0
- package/dist/signals.js +24 -0
- package/dist/site.js +0 -0
- package/dist/tooling.js +96 -0
- package/dist/types/adapters.d.ts +7 -4
- package/dist/types/agent-lists.d.ts +0 -1
- package/dist/types/agents-guide.d.ts +17 -0
- package/dist/types/authoring-files.d.ts +10 -0
- package/dist/types/aws.d.ts +3 -1
- package/dist/types/build-cloudflare.d.ts +1 -0
- package/dist/types/bulk.d.ts +27 -0
- package/dist/types/capabilities.d.ts +55 -0
- package/dist/types/capability-query.d.ts +24 -0
- package/dist/types/catalog.d.ts +65 -0
- package/dist/types/client-address.d.ts +0 -1
- package/dist/types/compliance-rules/baseline.d.ts +1 -9
- package/dist/types/compliance-rules/privacy.d.ts +1 -4
- package/dist/types/compliance-rules/strict.d.ts +0 -5
- package/dist/types/conditions.d.ts +19 -0
- package/dist/types/config.d.ts +20 -2
- package/dist/types/context.d.ts +65 -0
- package/dist/types/ecosystem-cli.d.ts +17 -0
- package/dist/types/egress.d.ts +46 -0
- package/dist/types/examples.d.ts +50 -0
- package/dist/types/explain-cli.d.ts +11 -0
- package/dist/types/explain.d.ts +95 -0
- package/dist/types/extensions.d.ts +122 -0
- package/dist/types/function-sources.d.ts +5 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/init-with.d.ts +30 -0
- package/dist/types/interchange-cli.d.ts +16 -0
- package/dist/types/interchange.d.ts +42 -0
- package/dist/types/link-cli.d.ts +2 -1
- package/dist/types/management-policy.d.ts +0 -1
- package/dist/types/manifest.d.ts +81 -0
- package/dist/types/match.d.ts +1 -0
- package/dist/types/mcp-authoring.d.ts +92 -0
- package/dist/types/mcp.d.ts +12 -0
- package/dist/types/observability.d.ts +2 -0
- package/dist/types/operator-host.d.ts +8 -0
- package/dist/types/plugins.d.ts +2 -0
- package/dist/types/policies/agents.d.ts +0 -2
- package/dist/types/policies/compression.d.ts +2 -0
- package/dist/types/policies/security.d.ts +0 -1
- package/dist/types/policy.d.ts +15 -4
- package/dist/types/project-tests.d.ts +3 -1
- package/dist/types/provider-verification.d.ts +53 -0
- package/dist/types/proxy.d.ts +21 -0
- package/dist/types/readiness.d.ts +1 -1
- package/dist/types/recipes.d.ts +30 -0
- package/dist/types/route-diff.d.ts +27 -0
- package/dist/types/runtime.d.ts +11 -0
- package/dist/types/schema-query.d.ts +12 -0
- package/dist/types/signals.d.ts +25 -0
- package/dist/types/site.d.ts +0 -1
- package/dist/types/tooling.d.ts +115 -0
- package/dist/types/types.d.ts +57 -0
- package/dist/types/typescript-authoring.d.ts +12 -0
- package/dist/types/vercel.d.ts +3 -1
- package/dist/types/verify-deployment.d.ts +47 -0
- package/dist/types.js +21 -2
- package/dist/typescript-authoring.js +104 -0
- package/dist/vercel.js +4 -3
- package/dist/verify-deployment.js +270 -0
- package/docs/AI-AUTHORING.md +130 -8
- package/docs/BULK.md +79 -0
- package/docs/CAPABILITIES.md +179 -0
- package/docs/CAPACITY.md +1 -1
- package/docs/CI.md +142 -0
- package/docs/CONDITIONS.md +74 -0
- package/docs/DEPLOYMENT-CHECKS.md +108 -0
- package/docs/DYNAMIC-LINKS.md +18 -518
- package/docs/EGRESS.md +125 -0
- package/docs/EXTENSIONS.md +226 -0
- package/docs/FRAMEWORK.md +182 -0
- package/docs/INSTALL.md +45 -7
- package/docs/INTERCHANGE.md +134 -0
- package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
- package/docs/MIDDLEWARE.md +2 -0
- package/docs/NEXT-PHASE-PLAN.md +90 -0
- package/docs/NEXT-STEPS.md +415 -0
- package/docs/OBSERVABILITY.md +4 -2
- package/docs/OPERATIONAL-PROOF.md +4 -1
- package/docs/OPERATIONS.md +6 -3
- package/docs/PLUGINS.md +37 -0
- package/docs/POLICIES.md +12 -309
- package/docs/PRERENDER.md +40 -0
- package/docs/PROJECT-DIRECTION.md +42 -0
- package/docs/PROVIDER-VERIFICATION.md +84 -0
- package/docs/READINESS.md +21 -1
- package/docs/README.md +82 -31
- package/docs/RECIPES.md +99 -0
- package/docs/RELEASE-READINESS.md +11 -9
- package/docs/RELEASE-SECURITY.md +27 -4
- package/docs/SECURITY-AUDIT.md +1 -1
- package/docs/SPECIFICATION.md +95 -8
- package/docs/SPIKE-BUSINESS-SUITE.md +1013 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
- package/docs/SPIKE-EXTENSIONS.md +1 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +199 -0
- package/docs/STANDARDS.md +150 -142
- package/docs/STARTERS.md +21 -1
- package/docs/TOOLING.md +291 -0
- package/docs/TYPESCRIPT-AUTHORING.md +67 -0
- package/docs/TYPESCRIPT.md +1 -1
- package/docs/USABILITY-REVIEW.md +123 -0
- package/docs/YAML-GUIDE.md +18 -479
- package/docs/YAML-REFERENCE.md +127 -16
- package/docs/links/cli.md +110 -0
- package/docs/links/limits.md +175 -0
- package/docs/links/management-api.md +80 -0
- package/docs/links/pools.md +75 -0
- package/docs/links/setup.md +135 -0
- package/docs/policies/agents.md +1 -1
- package/docs/policies/contract.md +52 -0
- package/docs/policies/hardened.md +56 -0
- package/docs/policies/interoperability.md +169 -0
- package/docs/policies/operations.md +45 -0
- package/docs/yaml/assets.md +36 -0
- package/docs/yaml/conditions.md +20 -0
- package/docs/yaml/functions.md +160 -0
- package/docs/yaml/links.md +30 -0
- package/docs/yaml/middleware.md +29 -0
- package/docs/yaml/organization.md +74 -0
- package/docs/yaml/policies.md +37 -0
- package/docs/yaml/redirects.md +64 -0
- package/docs/yaml/responses.md +57 -0
- package/docs/yaml/site.md +24 -0
- package/examples/assets/example.yaml +17 -0
- package/examples/aws/example.yaml +20 -0
- package/examples/cloudflare/example.yaml +19 -0
- package/examples/compliance/example.yaml +11 -0
- package/examples/conditions/README.md +12 -0
- package/examples/conditions/example.yaml +19 -0
- package/examples/conditions/tests/requests.json +13 -0
- package/examples/conditions/urlcode.yaml +24 -0
- package/examples/cookbook/README.md +8 -4
- package/examples/cookbook/example.yaml +17 -0
- package/examples/cookbook/functions/catalog.mjs +3 -0
- package/examples/cookbook/functions/fail.mjs +4 -0
- package/examples/cookbook/functions/items.mjs +3 -0
- package/examples/cookbook/functions/profile.mjs +3 -0
- package/examples/cookbook/functions/resource.mjs +3 -0
- package/examples/cookbook/functions/status.mjs +3 -0
- package/examples/cookbook/middleware/auth.mjs +48 -0
- package/examples/cookbook/middleware/body.mjs +15 -0
- package/examples/cookbook/middleware/bucket.mjs +19 -0
- package/examples/cookbook/middleware/cors.mjs +21 -0
- package/examples/cookbook/middleware/debug.mjs +13 -0
- package/examples/cookbook/middleware/envelope.mjs +11 -0
- package/examples/cookbook/middleware/errors.mjs +11 -0
- package/examples/cookbook/middleware/etag.mjs +18 -0
- package/examples/cookbook/middleware/locale.mjs +16 -0
- package/examples/cookbook/middleware/maintenance.mjs +10 -0
- package/examples/cookbook/middleware/methods.mjs +15 -0
- package/examples/cookbook/middleware/negotiate.mjs +20 -0
- package/examples/cookbook/middleware/referer.mjs +12 -0
- package/examples/cookbook/middleware/request-id.mjs +16 -0
- package/examples/cookbook/route-index.json +676 -0
- package/examples/cookbook/routes/middleware.yaml +126 -0
- package/examples/cookbook/tests/requests.json +526 -0
- package/examples/cookbook/urlcode.yaml +1 -0
- package/examples/egress/README.md +22 -0
- package/examples/egress/example.yaml +19 -0
- package/examples/egress/urlcode.yaml +19 -0
- package/examples/extensions/README.md +7 -0
- package/examples/extensions/example.yaml +21 -0
- package/examples/extensions/urlcode.yaml +25 -0
- package/examples/live-links/example.yaml +21 -0
- package/examples/monitoring/example.yaml +8 -0
- package/examples/prerender/example.yaml +16 -0
- package/examples/provider-conformance/README.md +12 -0
- package/examples/provider-conformance/example.yaml +14 -0
- package/examples/provider-conformance/urlcode.yaml +34 -0
- package/examples/tunnel/example.yaml +8 -0
- package/examples/vercel/example.yaml +19 -0
- package/llms-full.txt +2709 -0
- package/llms.txt +48 -19
- package/package.json +29 -7
- package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +106 -0
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +114 -0
- package/recipes/authenticated-json-api/README.md +51 -0
- package/recipes/authenticated-json-api/functions/profile.mjs +5 -0
- package/recipes/authenticated-json-api/recipe.yaml +34 -0
- package/recipes/authenticated-json-api/tests/requests.json +39 -0
- package/recipes/authenticated-json-api/urlcode.yaml +12 -0
- package/recipes/contact-form/README.md +25 -0
- package/recipes/contact-form/functions/contact.mjs +17 -0
- package/recipes/contact-form/recipe.yaml +33 -0
- package/recipes/contact-form/tests/requests.json +47 -0
- package/recipes/contact-form/urlcode.yaml +18 -0
- package/recipes/cors-api/README.md +16 -0
- package/recipes/cors-api/functions/items.mjs +3 -0
- package/recipes/cors-api/middleware/cors.mjs +21 -0
- package/recipes/cors-api/recipe.yaml +26 -0
- package/recipes/cors-api/tests/requests.json +65 -0
- package/recipes/cors-api/urlcode.yaml +12 -0
- package/recipes/health-page/README.md +13 -0
- package/recipes/health-page/recipe.yaml +23 -0
- package/recipes/health-page/tests/requests.json +36 -0
- package/recipes/health-page/urlcode.yaml +19 -0
- package/recipes/json-api/README.md +6 -0
- package/recipes/json-api/functions/echo.mjs +3 -0
- package/recipes/json-api/recipe.yaml +25 -0
- package/recipes/json-api/tests/requests.json +34 -0
- package/recipes/json-api/urlcode.yaml +12 -0
- package/recipes/middleware/README.md +34 -0
- package/recipes/middleware/functions/catalog.mjs +3 -0
- package/recipes/middleware/functions/fail.mjs +4 -0
- package/recipes/middleware/functions/items.mjs +3 -0
- package/recipes/middleware/functions/profile.mjs +3 -0
- package/recipes/middleware/functions/resource.mjs +3 -0
- package/recipes/middleware/functions/status.mjs +3 -0
- package/recipes/middleware/middleware/auth.mjs +48 -0
- package/recipes/middleware/middleware/body.mjs +15 -0
- package/recipes/middleware/middleware/bucket.mjs +19 -0
- package/recipes/middleware/middleware/cors.mjs +21 -0
- package/recipes/middleware/middleware/debug.mjs +13 -0
- package/recipes/middleware/middleware/envelope.mjs +11 -0
- package/recipes/middleware/middleware/errors.mjs +11 -0
- package/recipes/middleware/middleware/etag.mjs +18 -0
- package/recipes/middleware/middleware/locale.mjs +16 -0
- package/recipes/middleware/middleware/maintenance.mjs +10 -0
- package/recipes/middleware/middleware/methods.mjs +15 -0
- package/recipes/middleware/middleware/negotiate.mjs +20 -0
- package/recipes/middleware/middleware/referer.mjs +12 -0
- package/recipes/middleware/middleware/request-id.mjs +16 -0
- package/recipes/middleware/public/guide.txt +1 -0
- package/recipes/middleware/recipe.yaml +50 -0
- package/recipes/middleware/tests/requests.json +528 -0
- package/recipes/middleware/urlcode.yaml +127 -0
- package/recipes/protected-download/README.md +22 -0
- package/recipes/protected-download/files/report.txt +1 -0
- package/recipes/protected-download/recipe.yaml +31 -0
- package/recipes/protected-download/tests/requests.json +32 -0
- package/recipes/protected-download/urlcode.yaml +15 -0
- package/recipes/redirect/README.md +7 -0
- package/recipes/redirect/recipe.yaml +25 -0
- package/recipes/redirect/tests/requests.json +19 -0
- package/recipes/redirect/urlcode.yaml +9 -0
- package/recipes/static-plus-api/README.md +15 -0
- package/recipes/static-plus-api/functions/info.mjs +3 -0
- package/recipes/static-plus-api/public/assets/index.html +3 -0
- package/recipes/static-plus-api/public/assets/site.css +1 -0
- package/recipes/static-plus-api/public/index.html +8 -0
- package/recipes/static-plus-api/recipe.yaml +29 -0
- package/recipes/static-plus-api/tests/requests.json +56 -0
- package/recipes/static-plus-api/urlcode.yaml +23 -0
- package/recipes/typescript/README.md +7 -0
- package/recipes/typescript/functions/hello.ts +5 -0
- package/recipes/typescript/recipe.yaml +23 -0
- package/recipes/typescript/tests/requests.json +18 -0
- package/recipes/typescript/urlcode.yaml +5 -0
- package/recipes/webhook-receiver/README.md +16 -0
- package/recipes/webhook-receiver/functions/receive.mjs +16 -0
- package/recipes/webhook-receiver/recipe.yaml +26 -0
- package/recipes/webhook-receiver/tests/requests.json +59 -0
- package/recipes/webhook-receiver/urlcode.yaml +16 -0
- package/schemas/recipe.schema.json +138 -0
- package/schemas/urlcode.schema.json +656 -80
- package/skills/urlcode/SKILL.md +98 -0
- package/starters/default/.github/workflows/urlcode.yml +23 -0
- package/starters/default/.mcp.json +12 -0
- package/starters/default/AGENTS.md +79 -0
package/README.md
CHANGED
|
@@ -1,30 +1,89 @@
|
|
|
1
1
|
# URLCode
|
|
2
2
|
|
|
3
|
-
**A portable runtime for programmable URL behavior
|
|
4
|
-
public URL surface in YAML, add isolated
|
|
5
|
-
handlers are not enough, and run the same
|
|
6
|
-
|
|
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 isolated
|
|
5
|
+
JavaScript only where declarative handlers are not enough, and run the same
|
|
6
|
+
project locally, in a container, on your own infrastructure or on a provider
|
|
7
|
+
adapter. When the project gets serious, add accounts and an administration
|
|
8
|
+
console as operator-installed extensions instead of building them again.
|
|
9
|
+
**URL behavior as code.**
|
|
7
10
|
|
|
8
11
|
[](https://github.com/jimhoyd-com/urlcode/actions/workflows/ci.yml)
|
|
9
12
|
|
|
10
|
-
[Documentation](docs/README.md) · [Starter](https://github.com/jimhoyd-com/urlcode-template) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md)
|
|
13
|
+
[Documentation](docs/README.md) · [The framework](docs/FRAMEWORK.md) · [For AI agents](llms.txt) · [Starter](https://github.com/jimhoyd-com/urlcode-template) · [Contributing](CONTRIBUTING.md) · [Security](SECURITY.md)
|
|
14
|
+
|
|
15
|
+
**Your AI should build your application, not your framework.** Coding agents
|
|
16
|
+
rebuild the same routing, validation, middleware, policies and authentication
|
|
17
|
+
plumbing on every project, and the person ends up owning the plumbing. URLCode
|
|
18
|
+
represents those behaviors as a strict, portable YAML contract that both people
|
|
19
|
+
and agents can read: the agent describes what, the runtime owns how, and
|
|
20
|
+
generated code goes to the part that is actually the application. It is
|
|
21
|
+
infrastructure for AI-built software, not a framework for building AI models.
|
|
22
|
+
[Why](docs/PROJECT-DIRECTION.md#why-your-ai-should-build-your-application-not-your-framework) ·
|
|
23
|
+
[next steps](docs/NEXT-STEPS.md).
|
|
24
|
+
|
|
25
|
+
## What it is
|
|
26
|
+
|
|
27
|
+
A project is a `urlcode.yaml` with `version: "1"`. Each route has exactly one
|
|
28
|
+
handler: `redirect`, `respond`, `page`, `static`, `download`, `function`,
|
|
29
|
+
`link`, `proxy`, `conditional` or an `extension` mount, with optional ordered
|
|
30
|
+
`middleware`. The runtime validates the whole project before serving it,
|
|
31
|
+
compiles it once, and refuses anything a target cannot enforce with the route
|
|
32
|
+
named. Functions run in a QuickJS/WebAssembly sandbox with a fresh heap per
|
|
33
|
+
call and no Node, filesystem or network; secrets reach them only through
|
|
34
|
+
operator grants pinned to the project revision.
|
|
35
|
+
|
|
36
|
+
URLCode is not a URL shortener: short links are one handler. It is not a
|
|
37
|
+
general Node web framework: guest code cannot reach the host. It is not a
|
|
38
|
+
provider configuration format: infrastructure settings stay out of route YAML.
|
|
39
|
+
See [project direction](docs/PROJECT-DIRECTION.md).
|
|
40
|
+
|
|
41
|
+
## The framework
|
|
42
|
+
|
|
43
|
+
Four packages, one project shape. A project climbs from redirects to a full
|
|
44
|
+
application by adding YAML; the operator wires trusted packages in one host
|
|
45
|
+
file outside the project. The full map, the composition contract and the rules
|
|
46
|
+
an AI agent must follow are in [the framework](docs/FRAMEWORK.md).
|
|
47
|
+
|
|
48
|
+
| Package | Adds | Status |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| [urlcode](https://github.com/jimhoyd-com/urlcode) (this repository) | Runtime, CLI, policies, live links, provider adapters, extension contract | `0.4.0-alpha.1` (alpha) on top of the `0.3.0` release, Apache-2.0 |
|
|
51
|
+
| [urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui) | Shared presentation: escaped templates, shadcn/ui partials, themes, translations | `0.1.0-alpha.1` on npm, alpha: review pending |
|
|
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.1` on npm, alpha: review pending |
|
|
53
|
+
| [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin) | Administration: users, sessions, roles, audit, approvals, cases, impersonation | `0.1.0-alpha.1` on npm, alpha: review pending |
|
|
11
54
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
55
|
+
```yaml
|
|
56
|
+
version: "1"
|
|
57
|
+
extensions:
|
|
58
|
+
auth: { version: "1", config: { registration: "off" } }
|
|
59
|
+
admin: { version: "1", config: {} }
|
|
60
|
+
routes:
|
|
61
|
+
/go: { redirect: { url: https://example.com, status: 302 } }
|
|
62
|
+
/account/*: { extension: auth, methods: [GET, HEAD, POST] }
|
|
63
|
+
/admin/*: { extension: admin, methods: [GET, HEAD, POST] }
|
|
64
|
+
/private:
|
|
65
|
+
respond: { text: Signed in }
|
|
66
|
+
policies: { extensions: { auth: {} } }
|
|
67
|
+
```
|
|
17
68
|
|
|
18
|
-
|
|
19
|
-
the
|
|
69
|
+
The YAML names logical extensions; it never names packages, code, databases
|
|
70
|
+
or credentials. `urlcode-auth init` writes the operator host, keys and a
|
|
71
|
+
private data directory beside the project; `urlcode serve --host-file` loads
|
|
72
|
+
it. Cross-repository acceptance is tracked in
|
|
73
|
+
[issue 58](https://github.com/jimhoyd-com/urlcode/issues/58).
|
|
20
74
|
|
|
21
75
|
## Status
|
|
22
76
|
|
|
23
|
-
`0.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
and
|
|
77
|
+
`0.4.0-alpha.1` is the current release of the extension contract and the
|
|
78
|
+
agent tooling, on top of the `0.3.0` self-hosted release. It adds the
|
|
79
|
+
extension contract, capabilities and provider conformance, strict redirect
|
|
80
|
+
interchange, bulk import, recipes and search, TypeScript guest authoring,
|
|
81
|
+
conditions, bounded proxy and signals, and the MCP read and authoring modes;
|
|
82
|
+
use the schema and docs from the runtime revision you run.
|
|
83
|
+
The [roadmap](ROADMAP.md) separates implemented from planned, and
|
|
84
|
+
[release readiness](docs/RELEASE-READINESS.md) records what is proven and
|
|
85
|
+
what is not: provider deployments, soak and independent security review
|
|
86
|
+
remain open.
|
|
28
87
|
|
|
29
88
|
Live-link storage uses separate bounded reader/writer pools. It requires a Node
|
|
30
89
|
build containing a patched SQLite version — 3.51.3 or newer, 3.50.7, or 3.44.6 —
|
|
@@ -42,7 +101,9 @@ self-hosting are permitted under its terms.
|
|
|
42
101
|
Start with the [YAML guide and recipe book](docs/YAML-GUIDE.md),
|
|
43
102
|
[complete field reference](docs/YAML-REFERENCE.md), and
|
|
44
103
|
[runnable 25-route cookbook](examples/cookbook/README.md). For AI-assisted
|
|
45
|
-
authoring, use [the AI guide](docs/AI-AUTHORING.md)
|
|
104
|
+
authoring, use [the AI guide](docs/AI-AUTHORING.md), the bundled agent skills
|
|
105
|
+
([authoring](.claude/skills/urlcode-authoring/SKILL.md),
|
|
106
|
+
[operations](.claude/skills/urlcode-operations/SKILL.md)) and [llms.txt](llms.txt).
|
|
46
107
|
Follow [organization and readability practices](docs/BEST-PRACTICES.md) as your
|
|
47
108
|
project grows. Operators should read [capacity/concurrency](docs/CAPACITY.md) and the
|
|
48
109
|
[DDoS and recovery playbook](docs/RESILIENCE.md). Embedding the runtime from
|
|
@@ -94,249 +155,115 @@ Already wrote `urlcode.yaml`? Run `urlcode scaffold --project ./my-links --dry-r
|
|
|
94
155
|
then remove `--dry-run` to create missing modules, pages and directories. Existing
|
|
95
156
|
files are preserved; code placeholders return 501 until implemented.
|
|
96
157
|
[Scaffolding guide](docs/SCAFFOLDING.md).
|
|
158
|
+
Live-link storage and the auth extension need a Node build whose SQLite is
|
|
159
|
+
3.51.3 or newer, 3.50.7 or 3.44.6. `urlcode doctor` reports `liveLinks`;
|
|
160
|
+
everything else runs on any supported Node (22.13+ installed, 22.18+ to run
|
|
161
|
+
the TypeScript source).
|
|
97
162
|
|
|
98
163
|
## Try it
|
|
99
164
|
|
|
100
|
-
Requires Node.js 22.13+ and npm; CI targets Node 22, 24 and 26 on macOS, Linux and
|
|
101
|
-
Windows.
|
|
102
|
-
|
|
103
165
|
```sh
|
|
104
|
-
npm install --global urlcode
|
|
166
|
+
npm install --global @jimhoyd/urlcode # or: brew tap jimhoyd-com/urlcode && brew install urlcode
|
|
105
167
|
urlcode init my-urls && cd my-urls
|
|
106
168
|
urlcode dev
|
|
107
169
|
```
|
|
108
170
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
git clone
|
|
114
|
-
cd urlcode
|
|
115
|
-
make dev
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
`make dev` installs dependencies if needed and starts the included function/redirect demo.
|
|
119
|
-
No global install, account, database, Docker or configuration step is required.
|
|
120
|
-
A clone runs the TypeScript source directly (`node src/cli.ts`, which needs
|
|
121
|
-
Node 22.18+); the installed package runs the built `dist/cli.js`.
|
|
122
|
-
Without Make (including Windows), use:
|
|
123
|
-
|
|
124
|
-
```sh
|
|
125
|
-
npm ci
|
|
126
|
-
npm run dev
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Open `http://127.0.0.1:3000/hello/Ada` to run your custom function,
|
|
130
|
-
`/go` for a regular redirect.
|
|
131
|
-
Edit `starters/default/routes/` or `functions/hello.mjs` under
|
|
132
|
-
that starter; valid changes reload automatically. Press Ctrl+C to stop.
|
|
133
|
-
In another terminal, run `make test-project` or `npm run test:project`.
|
|
134
|
-
|
|
135
|
-
To create your own independent project:
|
|
136
|
-
|
|
137
|
-
```sh
|
|
138
|
-
make init DEST=../my-links
|
|
139
|
-
make dev PROJECT=../my-links PORT=3001
|
|
140
|
-
# Without Make:
|
|
141
|
-
npm run init -- ../my-links
|
|
142
|
-
npm run dev -- --project ../my-links --port 3001
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Choose either command pair; initialization refuses to overwrite existing work.
|
|
146
|
-
[Starters](docs/STARTERS.md) are ordinary application files, independent of the
|
|
147
|
-
runtime checkout. Own them in your own Git repository. Global `npm link` remains
|
|
148
|
-
optional if you want the `urlcode` command everywhere. See
|
|
149
|
-
[local development](docs/LOCAL-DEVELOPMENT.md) for commands and troubleshooting.
|
|
171
|
+
Open `http://127.0.0.1:3000/hello/Ada` for the function route and `/go` for
|
|
172
|
+
the redirect. Edit the YAML; valid changes reload. `urlcode test` runs the
|
|
173
|
+
project's HTTP fixtures. The [install guide](docs/INSTALL.md) covers the
|
|
174
|
+
checksum-verified script, project-local installs, the container image and
|
|
175
|
+
signed provenance. To work from a clone: `git clone … && make dev`.
|
|
150
176
|
|
|
151
177
|
## A URL that runs your function
|
|
152
178
|
|
|
153
|
-
A request to `/hello/Ada` runs your JavaScript and returns
|
|
154
|
-
`{"message":"Hello, Ada!"}`. Put this in `urlcode.yaml`:
|
|
155
|
-
|
|
156
179
|
```yaml
|
|
157
180
|
version: "1"
|
|
158
181
|
routes:
|
|
159
182
|
/hello/{name}:
|
|
160
183
|
parameters:
|
|
161
|
-
- name: name
|
|
162
|
-
in: path
|
|
163
|
-
required: true
|
|
164
|
-
schema: {type: string, minLength: 1, maxLength: 80}
|
|
184
|
+
- { name: name, in: path, required: true, schema: { type: string, minLength: 1, maxLength: 80 } }
|
|
165
185
|
function:
|
|
166
186
|
source: functions/hello.mjs
|
|
167
|
-
args:
|
|
168
|
-
name: {from: path, name: name}
|
|
187
|
+
args: { name: { from: path, name: name } }
|
|
169
188
|
env:
|
|
170
|
-
GREETING: {value: Hello}
|
|
189
|
+
GREETING: { value: Hello }
|
|
171
190
|
```
|
|
172
191
|
|
|
173
|
-
And in `functions/hello.mjs`:
|
|
174
|
-
|
|
175
192
|
```js
|
|
176
193
|
export default function hello(request, { args, env }) {
|
|
177
194
|
return Response.json({ message: `${env.GREETING}, ${args.name}!` });
|
|
178
195
|
}
|
|
179
196
|
```
|
|
180
197
|
|
|
181
|
-
|
|
182
|
-
`
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
##
|
|
198
|
+
Add `middleware: [{ source: middleware/headers.mjs }]` to wrap any handler with
|
|
199
|
+
`await next()`. Fourteen ready-made middleware patterns ship in the cookbook
|
|
200
|
+
and as `urlcode recipes add middleware`. See [functions and the sandbox](docs/FUNCTION-SECURITY.md)
|
|
201
|
+
and [middleware](docs/MIDDLEWARE.md).
|
|
202
|
+
|
|
203
|
+
## Everything else in YAML
|
|
204
|
+
|
|
205
|
+
- **Pages, files, downloads:** `page`, `static`, `download` with MIME detection,
|
|
206
|
+
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
|
+
- **HTTP:** methods, validated path/query/header inputs, body limits, response
|
|
211
|
+
headers and cookies. [HTTP](docs/HTTP.md).
|
|
212
|
+
- **Policies and site conventions:** throttle, agents, security headers,
|
|
213
|
+
compression, cache; robots, sitemap, favicon, security.txt, llms.txt.
|
|
214
|
+
[Policies](docs/POLICIES.md), [site](docs/SITE.md).
|
|
215
|
+
- **Conditions, proxy, signals:** exact predicates with disjoint cases; a bounded
|
|
216
|
+
HTTPS proxy and best-effort webhooks behind operator grants.
|
|
217
|
+
[Conditions](docs/CONDITIONS.md), [egress](docs/EGRESS.md).
|
|
218
|
+
- **Organization:** `includes` across folders; strict CSV/JSON/YAML and
|
|
219
|
+
provider-file import; searchable recipes and examples. [Organization](docs/ORGANIZATION.md),
|
|
220
|
+
[interchange](docs/INTERCHANGE.md), [bulk](docs/BULK.md), [recipes](docs/RECIPES.md).
|
|
221
|
+
- **Checks:** `validate`, `test`, `routes`, `audit --expect-routes`, `benchmark`,
|
|
222
|
+
`capabilities`, deployment verification and a GitHub Action.
|
|
223
|
+
[Readiness](docs/READINESS.md), [CI](docs/CI.md).
|
|
224
|
+
|
|
225
|
+
## Deploy
|
|
226
|
+
|
|
227
|
+
Self-hosted Node process or container first. `@jimhoyd/urlcode/vercel` and
|
|
228
|
+
`@jimhoyd/urlcode/aws` serve declarative projects as native handlers;
|
|
229
|
+
`urlcode build --target cloudflare` compiles redirects and declared responses
|
|
230
|
+
into a Worker. Each target refuses at activation or build time what it cannot
|
|
231
|
+
run, with the route named. None has been exercised on its provider yet; the
|
|
232
|
+
adapters have local conformance tests only. [Operations](docs/OPERATIONS.md),
|
|
233
|
+
[capabilities](docs/CAPABILITIES.md), [Vercel](docs/VERCEL.md), [AWS](docs/AWS.md),
|
|
234
|
+
[Cloudflare](docs/CLOUDFLARE.md).
|
|
235
|
+
|
|
236
|
+
## For AI agents
|
|
237
|
+
|
|
238
|
+
[llms.txt](llms.txt) is the compact index; [the framework](docs/FRAMEWORK.md)
|
|
239
|
+
is the map; [AI authoring](docs/AI-AUTHORING.md) is the contract with the
|
|
240
|
+
capability matrix and a copyable task prompt. `urlcode mcp` exposes read-only
|
|
241
|
+
inspection, validation and conversion previews over stdio, and
|
|
242
|
+
`--allow-authoring` adds project-confined authoring tools
|
|
243
|
+
([tooling](docs/TOOLING.md)).
|
|
187
244
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```yaml
|
|
191
|
-
middleware:
|
|
192
|
-
- source: middleware/headers.mjs
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
```js
|
|
196
|
-
export default async function headers(request, context, next) {
|
|
197
|
-
const response = await next();
|
|
198
|
-
response.headers.set('x-example-middleware', 'active');
|
|
199
|
-
return response;
|
|
200
|
-
}
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Middleware can return a response early, share request-local `context.state`, or
|
|
204
|
-
wrap the handler with `await next()`. It runs in the same isolated sandbox and
|
|
205
|
-
under one deadline for the whole chain. The starter's function route includes
|
|
206
|
-
this example. See [middleware semantics and limits](docs/MIDDLEWARE.md).
|
|
207
|
-
|
|
208
|
-
## A URL that redirects
|
|
209
|
-
|
|
210
|
-
```yaml
|
|
211
|
-
version: "1"
|
|
212
|
-
routes:
|
|
213
|
-
/go:
|
|
214
|
-
redirect:
|
|
215
|
-
url: https://example.com
|
|
216
|
-
status: 302
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Ordinary redirects use an indexed lookup: no database, Lambda or per-route
|
|
220
|
-
user function. Configuration is compiled at startup, not parsed per request.
|
|
221
|
-
Literal paths win over parameterized routes; conflicting definitions fail validation.
|
|
222
|
-
|
|
223
|
-
Custom functions are ES modules using a documented text/JSON `Request`/`Response`
|
|
224
|
-
subset and validated context. See the
|
|
225
|
-
[starter](starters/default/urlcode.yaml) and [function](starters/default/functions/hello.mjs).
|
|
226
|
-
Functions are treated as untrusted and run inside a QuickJS/WebAssembly sandbox,
|
|
227
|
-
with a fresh heap per invocation. No Node APIs, filesystem, shell, network or
|
|
228
|
-
ambient environment is exposed. Independent worker deadlines bound execution.
|
|
229
|
-
External env/secret bindings require route-scoped operator grants pinned to the
|
|
230
|
-
project revision. See the [security model](docs/FUNCTION-SECURITY.md).
|
|
231
|
-
|
|
232
|
-
## Pages, files and downloads
|
|
233
|
-
|
|
234
|
-
Add these routes alongside your functions and redirects:
|
|
235
|
-
|
|
236
|
-
```yaml
|
|
237
|
-
/about:
|
|
238
|
-
page:
|
|
239
|
-
file: public/about.html
|
|
240
|
-
/assets/*:
|
|
241
|
-
static:
|
|
242
|
-
directory: public/assets
|
|
243
|
-
/download:
|
|
244
|
-
download:
|
|
245
|
-
file: public/guide.txt
|
|
246
|
-
filename: urlcode-guide.txt
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Create the referenced files first. MIME types are detected from file extensions;
|
|
250
|
-
unknown types use `application/octet-stream`. Downloads set attachment headers.
|
|
251
|
-
Optional `contentType` overrides detection. HEAD, ETags, conditional requests and
|
|
252
|
-
single byte ranges are supported. Files are served natively without executing a
|
|
253
|
-
function. See [asset configuration and safety limits](docs/ASSETS.md).
|
|
254
|
-
|
|
255
|
-
## Organize routes across files
|
|
245
|
+
## Documentation
|
|
256
246
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
247
|
+
Full documentation lives in
|
|
248
|
+
[urlcode-docs](https://github.com/jimhoyd-com/urlcode-docs). It is authored
|
|
249
|
+
there directly, not generated from this repository, and it is where new guides,
|
|
250
|
+
references and recipes belong.
|
|
261
251
|
|
|
262
|
-
|
|
252
|
+
`docs/` in this repository is contributor and maintainer material — local
|
|
253
|
+
development, CI, the release process, reviews and the generated field
|
|
254
|
+
reference. Reader-facing pages still under `docs/` are being migrated.
|
|
263
255
|
|
|
264
|
-
|
|
265
|
-
`/r/{code}`. Only static-file mounts support a trailing `/*`; regex routing is
|
|
266
|
-
not supported. `dev` swaps validated configuration snapshots when YAML changes;
|
|
267
|
-
`serve` requires restart/redeployment for YAML changes. Stored short links can
|
|
268
|
-
now be created/updated/deleted live without reloads through the optional
|
|
269
|
-
[dynamic-link handler and management API](docs/DYNAMIC-LINKS.md). See [matching, precedence and dynamic-link behavior](docs/ROUTING.md).
|
|
256
|
+
## Built with URLCode
|
|
270
257
|
|
|
271
|
-
|
|
258
|
+
[urlcode-short](https://github.com/jimhoyd-com/urlcode-short), an
|
|
259
|
+
account-free short-link demo with a shadcn/ui front end, and
|
|
260
|
+
[urlcode-docs](https://github.com/jimhoyd-com/urlcode-docs), a static
|
|
261
|
+
documentation site rendered through sandboxed middleware at build time. Both are
|
|
262
|
+
ordinary consumers of the public runtime; their retrospectives list what the
|
|
263
|
+
runtime supplied and what they still had to build.
|
|
272
264
|
|
|
273
|
-
|
|
274
|
-
/r/{code}:
|
|
275
|
-
parameters:
|
|
276
|
-
- name: code
|
|
277
|
-
in: path
|
|
278
|
-
required: true
|
|
279
|
-
schema: {type: string, minLength: 1, maxLength: 128}
|
|
280
|
-
link:
|
|
281
|
-
collection: links
|
|
282
|
-
code: {from: path, name: code}
|
|
283
|
-
```
|
|
265
|
+
## License and contributing
|
|
284
266
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
record changes are visible without rewriting YAML or rebuilding the route table.
|
|
289
|
-
Ordinary YAML routes still need no database. See [setup, API and limitations](docs/DYNAMIC-LINKS.md).
|
|
290
|
-
|
|
291
|
-
## HTTP in YAML
|
|
292
|
-
|
|
293
|
-
Configure methods and validated path/query/header inputs, request body size and
|
|
294
|
-
media types, response headers, cookies, and declared text/JSON responses.
|
|
295
|
-
See the [HTTP configuration reference](docs/HTTP.md) for supported fields and
|
|
296
|
-
examples. Runtime framing and asset validators stay protected.
|
|
297
|
-
|
|
298
|
-
## Check your links before release
|
|
299
|
-
|
|
300
|
-
`urlcode routes` lists the configured routes. `urlcode audit --expect-routes 2`
|
|
301
|
-
checks the count, generates native response checks and reports missing route/method
|
|
302
|
-
coverage in your request fixtures. `urlcode benchmark --requests 1000 --concurrency 2`
|
|
303
|
-
measures your local project without following external redirects. Each command
|
|
304
|
-
accepts `--project`. See [readiness and release checks](docs/READINESS.md).
|
|
305
|
-
|
|
306
|
-
## Commands available
|
|
307
|
-
|
|
308
|
-
| Command | Purpose |
|
|
309
|
-
|---|---|
|
|
310
|
-
| `init <directory>` | Create an independent starter; refuse existing destinations |
|
|
311
|
-
| `add <url> --alias <code>` | Validate and atomically add a redirect; generate a code if omitted |
|
|
312
|
-
| `validate --local` | Validate config, references, bindings and function initialization; read `.env.local` |
|
|
313
|
-
| `dev` | Local server, watched reload and `.env.local` |
|
|
314
|
-
| `serve` | Fixed production process snapshot; environment injection, no dotenv loading |
|
|
315
|
-
| `test` | Local HTTP assertions from `tests/requests.json`; never follow redirects |
|
|
316
|
-
| `permissions` | Inspect requested bindings and project digest without executing code; grants nothing |
|
|
317
|
-
| `doctor` | Report runtime/platform details and implemented provider scope |
|
|
318
|
-
|
|
319
|
-
Use `--project <directory>` to select an app. Servers accept `--host`, `--port`
|
|
320
|
-
and `--origin` (public URL origin for functions). Bind defaults to `127.0.0.1`.
|
|
321
|
-
|
|
322
|
-
## Production direction
|
|
323
|
-
|
|
324
|
-
The free runtime is meant to be useful and production-capable for people who
|
|
325
|
-
operate it themselves. Current hardening includes strict YAML/schema checks,
|
|
326
|
-
request/response limits, worker deadlines, bounded function concurrency, safe
|
|
327
|
-
configuration replacement, graceful shutdown, health/readiness and structured
|
|
328
|
-
logs without request content. It still needs broader deployment/soak validation
|
|
329
|
-
and the remaining release features. Read [operations](docs/OPERATIONS.md) before
|
|
330
|
-
exposing a server. [Benchmark instructions and measurements](docs/PERFORMANCE.md)
|
|
331
|
-
are available; measurements are not capacity guarantees.
|
|
332
|
-
|
|
333
|
-
Git owns definitions and code. Secrets stay in ignored `.env.local` for development
|
|
334
|
-
or injected environment values for serving, accessible to functions only through
|
|
335
|
-
an explicit operator policy. Vercel, AWS Lambda and Cloudflare Workers each have a
|
|
336
|
-
target guide in [docs](docs/README.md); none has been deployed to its platform
|
|
337
|
-
yet. Provider secret-store integration, CSV tools, templates/signals,
|
|
338
|
-
Homebrew and richer monitoring are future work. Unsupported config fails rather
|
|
339
|
-
than silently losing behavior. There is no required admin UI or database.
|
|
340
|
-
|
|
341
|
-
See [contributing](CONTRIBUTING.md), [security](SECURITY.md), and the
|
|
342
|
-
[roadmap](ROADMAP.md).
|
|
267
|
+
Apache-2.0. Commercial use, modification, redistribution and self-hosting are
|
|
268
|
+
permitted. See [contributing](CONTRIBUTING.md), [security](SECURITY.md),
|
|
269
|
+
[governance](GOVERNANCE.md) and the [roadmap](ROADMAP.md).
|
package/ROADMAP.md
CHANGED
|
@@ -11,6 +11,89 @@ separate late phase. The stable 0.1 self-hosted release covers much of M0/M1 plu
|
|
|
11
11
|
process/container packaging and benchmarks. Provider adapters and the remaining
|
|
12
12
|
production-readiness gates remain open.
|
|
13
13
|
|
|
14
|
+
## 0.4.0-alpha.1 — current alpha
|
|
15
|
+
|
|
16
|
+
`0.4.0-alpha.1` is the first alpha of the extension contract and the agent
|
|
17
|
+
tooling on top of the `0.3.0` self-hosted release. It carries: the
|
|
18
|
+
revision-pinned extension contract, capabilities and provider conformance,
|
|
19
|
+
strict redirect interchange, bulk import, recipes and search, TypeScript
|
|
20
|
+
guests, conditions, bounded proxy and signals, MCP read and authoring modes,
|
|
21
|
+
the `context`, `explain`, `manifest` and `schema` queries, short forms,
|
|
22
|
+
route-level auth, `init --with`, the agent benchmark harness, `llms-full`,
|
|
23
|
+
and the generated `AGENTS.md` and skill. It is an alpha: provider
|
|
24
|
+
deployments, soak and independent security review remain open. The
|
|
25
|
+
extension packages declare `@jimhoyd/urlcode >=0.4.0-alpha.1 <0.5.0` and
|
|
26
|
+
are published after core.
|
|
27
|
+
|
|
28
|
+
## Extensions: accounts, administration and presentation — implemented, unreleased
|
|
29
|
+
|
|
30
|
+
The runtime now carries a generic, revision-pinned extension contract
|
|
31
|
+
(`@jimhoyd/urlcode/extensions`, [extensions](docs/EXTENSIONS.md)): a project
|
|
32
|
+
declares versioned `extensions.<name>` blocks, exclusive `extension` mounts and
|
|
33
|
+
`policies.extensions` requirements; the operator supplies the implementations
|
|
34
|
+
in a host file loaded with `--host-file`, outside the project. Guest requests
|
|
35
|
+
never see `Cookie`, `Authorization` or declared credential headers. Cloudflare
|
|
36
|
+
refuses extensions until its artifact format can run them.
|
|
37
|
+
|
|
38
|
+
The implementations live in their own repositories, each with an
|
|
39
|
+
implementation-status file that is the authoritative feature list:
|
|
40
|
+
[urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth) (accounts, sessions,
|
|
41
|
+
MFA, roles, account page, operator CLI), [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin)
|
|
42
|
+
(users, sessions, roles, audit, approvals, cases, impersonation) and
|
|
43
|
+
[urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui) (escaped templates,
|
|
44
|
+
partials, themes, translations). All three are Apache-2.0 and published to
|
|
45
|
+
npm as `0.1.0-alpha.1` while first-release acceptance is reviewed; see
|
|
46
|
+
[issue 58](https://github.com/jimhoyd-com/urlcode/issues/58) for what remains:
|
|
47
|
+
browser and device WebAuthn coverage, accessibility assessment, soak, backup
|
|
48
|
+
and recovery drills on a deployment, live provider senders and independent
|
|
49
|
+
security review. [The framework](docs/FRAMEWORK.md) describes how the four
|
|
50
|
+
packages compose, and [next steps](docs/NEXT-STEPS.md) is the phased plan to
|
|
51
|
+
close the remaining gaps.
|
|
52
|
+
|
|
53
|
+
## Capability foundation — implemented, unreleased
|
|
54
|
+
|
|
55
|
+
`urlcode capabilities [--target self-hosted|cloudflare|aws|vercel] [--json]`
|
|
56
|
+
and the public capability API centralize target support for handlers, bindings
|
|
57
|
+
and effective policies. Runtime activation and Cloudflare builds use the shared
|
|
58
|
+
preflight; unknown targets fail closed and unsupported requirements identify the
|
|
59
|
+
route and capability before resources or artifacts are created. The existing
|
|
60
|
+
compiled route IR is documented, not replaced. Configuration-dependent and
|
|
61
|
+
delegated behavior remain explicit; all provider deployments remain unverified.
|
|
62
|
+
See [capabilities](docs/CAPABILITIES.md) and the
|
|
63
|
+
[next-phase review and implementation status](docs/NEXT-PHASE-PLAN.md).
|
|
64
|
+
|
|
65
|
+
## Portability and URL behavior — implemented, unreleased
|
|
66
|
+
|
|
67
|
+
Strict redirect interchange supports CSV/JSON/YAML, Netlify and Cloudflare
|
|
68
|
+
`_redirects`, a bounded Netlify TOML subset and Vercel redirects. Conversion
|
|
69
|
+
reports refuse unsupported semantics; provider differences require explicit
|
|
70
|
+
acknowledgment and are never called lossless. A synthetic conformance fixture
|
|
71
|
+
and bounded HTTPS runner distinguish local adapter tests from observed
|
|
72
|
+
provider deployments. Actual Cloudflare/AWS/Vercel deployment evidence remains
|
|
73
|
+
pending; this does not complete M4.
|
|
74
|
+
|
|
75
|
+
Exact query/header/cookie/origin/method conditions and disjoint conditional
|
|
76
|
+
redirect/response cases run in the self-hosted, AWS and Vercel runtimes.
|
|
77
|
+
Cloudflare refuses these until its compiler can preserve their semantics.
|
|
78
|
+
Self-hosted proxy and webhook signals use explicit revision-pinned operator
|
|
79
|
+
origin grants, connection-pinned public DNS and bounded transport. Signals
|
|
80
|
+
have no durable delivery or retry guarantee. Other targets refuse proxy and
|
|
81
|
+
signals. See [conditions](docs/CONDITIONS.md), [egress](docs/EGRESS.md),
|
|
82
|
+
[interchange](docs/INTERCHANGE.md) and
|
|
83
|
+
[provider verification](docs/PROVIDER-VERIFICATION.md).
|
|
84
|
+
|
|
85
|
+
## Developer ecosystem — implemented, unreleased
|
|
86
|
+
|
|
87
|
+
Bundled Git-owned recipes, safe bulk imports into route includes, build-time
|
|
88
|
+
TypeScript guest transpilation, read-only inspection APIs and optional stdio
|
|
89
|
+
MCP tooling are available. The runtime still executes only JavaScript inside
|
|
90
|
+
QuickJS/WASM; TypeScript authoring does not add host execution. Bulk benchmarks
|
|
91
|
+
successfully cover 1,000, 10,000 and 100,000 routes without relaxing parser
|
|
92
|
+
limits. See [recipes](docs/RECIPES.md), [bulk evidence](docs/BULK.md),
|
|
93
|
+
[TypeScript authoring](docs/TYPESCRIPT-AUTHORING.md) and
|
|
94
|
+
[SDK/MCP](docs/TOOLING.md). These features do not supply durable signals,
|
|
95
|
+
protected downloads, a remote marketplace or provider deployment proof.
|
|
96
|
+
|
|
14
97
|
## TypeScript source and shipped declarations — implemented, unreleased
|
|
15
98
|
|
|
16
99
|
The runtime, scripts, tests and benchmarks are TypeScript under a strict
|
|
@@ -167,7 +250,7 @@ Implemented the page/static/download portion of M2: project-contained asset
|
|
|
167
250
|
snapshots, automatic MIME types, attachment names, HEAD, cache validators and
|
|
168
251
|
single byte ranges. Dedicated public directories, symlink/hardlink rejection and
|
|
169
252
|
bounded memory are part of the contract. [Asset guide](docs/ASSETS.md).
|
|
170
|
-
Bulk tools,
|
|
253
|
+
Bulk tools, recipes and best-effort signals were added in the unreleased next-phase work above; they were not part of alpha.3.
|
|
171
254
|
|
|
172
255
|
## Security correction — 0.1.0-alpha.2
|
|
173
256
|
|
|
@@ -190,7 +273,7 @@ CI and a non-root container build are included. See the [contract](docs/SPECIFIC
|
|
|
190
273
|
and [operations guide](docs/OPERATIONS.md) for exact support and evidence limits.
|
|
191
274
|
|
|
192
275
|
Still open in the early contract: host namespaces, stable identity beyond paths,
|
|
193
|
-
|
|
276
|
+
fuller parameter vocabulary. Build-time TypeScript authoring and capability planning are now implemented in the unreleased work above.
|
|
194
277
|
No claims of complete M0/M1 or stable production readiness. M2–M4 work continues
|
|
195
278
|
in the order below; a few independently useful operational foundations shipped early.
|
|
196
279
|
|
package/SECURITY.md
CHANGED
|
@@ -16,6 +16,13 @@ execution platform. Authorized inputs/secrets can be exposed
|
|
|
16
16
|
by code receiving them; grant the minimum required authority. Do not deploy
|
|
17
17
|
older snapshots for untrusted functions; review and upgrade to the current revision.
|
|
18
18
|
|
|
19
|
+
Declarative proxy and signal handlers run in a separate bounded host transport;
|
|
20
|
+
they do not grant guest networking. They require per-route, per-purpose HTTPS
|
|
21
|
+
origin grants pinned to the project revision. Every connection checks public
|
|
22
|
+
addresses and pins DNS, refuses redirects, filters headers and limits resources.
|
|
23
|
+
See [egress semantics and limitations](docs/EGRESS.md). Build-time TypeScript
|
|
24
|
+
transpilation and read-only MCP do not execute project code in the host.
|
|
25
|
+
|
|
19
26
|
## Report a vulnerability privately
|
|
20
27
|
|
|
21
28
|
Use [GitHub private vulnerability reporting](https://github.com/jimhoyd-com/urlcode/security/advisories/new).
|
|
@@ -36,5 +43,5 @@ Bind loopback by default; protect public deployments with HTTPS, rate limits,
|
|
|
36
43
|
network controls and restricted operational endpoints. See [operations](docs/OPERATIONS.md).
|
|
37
44
|
|
|
38
45
|
See the [internal security reviews](docs/SECURITY-AUDIT.md) — most recently
|
|
39
|
-
2026-09-17 — for fixed findings and remaining gates. Use a current reviewed commit: the shared 0.
|
|
46
|
+
2026-09-17 — for fixed findings and remaining gates. Use a current reviewed commit: the shared 0.3.0
|
|
40
47
|
version label alone does not identify which hardening patches are present.
|