@jimhoyd/urlcode 0.4.0-alpha.1 → 0.4.0-alpha.3
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 +36 -22
- package/.claude/skills/urlcode-operations/SKILL.md +16 -22
- package/.claude-plugin/marketplace.json +1 -1
- package/CONTRIBUTING.md +20 -16
- package/README.md +83 -80
- package/ROADMAP.md +61 -331
- package/SECURITY.md +23 -8
- package/dist/BUILD-MANIFEST.json +42 -47
- package/dist/agents-guide.js +18 -18
- package/dist/build-static.js +136 -0
- package/dist/capabilities.js +85 -31
- package/dist/capability-query.js +0 -1
- package/dist/cli.js +24 -32
- 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 +7 -5
- package/dist/explain.js +10 -5
- 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 +11 -7
- package/dist/mcp-authoring.js +2 -2
- package/dist/mcp.js +1 -1
- package/dist/observability.js +1 -21
- package/dist/policies/cache.js +8 -3
- package/dist/policies.js +3 -1
- package/dist/policy.js +28 -9
- package/dist/prerender.js +4 -0
- package/dist/project-tests.js +3 -3
- package/dist/readiness.js +35 -9
- package/dist/route-diff.js +12 -5
- 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/explain.d.ts +6 -0
- 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 +5 -3
- package/dist/types/observability.d.ts +1 -14
- package/dist/types/project-tests.d.ts +1 -2
- package/dist/types/readiness.d.ts +12 -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 +22 -8
- package/dist/types/verify-deployment.d.ts +2 -2
- package/dist/types.js +25 -5
- package/dist/typescript-authoring.js +67 -18
- package/dist/verify-deployment.js +3 -3
- package/docs/AI-AUTHORING.md +109 -10
- package/docs/ASSETS.md +2 -1
- package/docs/AUTH-BACKUP.md +32 -0
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +17 -8
- package/docs/CAPABILITIES.md +30 -17
- package/docs/CAPACITY.md +128 -31
- 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/CLOUDFLARE.md +1 -2
- package/docs/CODEBASE-AUDIT-2026-09-20.md +278 -0
- package/docs/COMPLIANCE.md +6 -9
- package/docs/DEPLOYMENT-CHECKS.md +1 -1
- package/docs/DEVELOPMENT-PIPELINE.md +181 -0
- package/docs/EXTENSIONS.md +193 -11
- package/docs/FRAMEWORK.md +53 -33
- package/docs/FUNCTION-SECURITY.md +173 -32
- package/docs/INSTALL.md +0 -5
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/LOCAL-DEVELOPMENT.md +3 -0
- package/docs/MIDDLEWARE.md +27 -16
- package/docs/MONITORING.md +2 -19
- package/docs/OBSERVABILITY.md +7 -16
- package/docs/OPEN-DECISIONS.md +184 -0
- package/docs/OPERATIONAL-PROOF.md +26 -30
- package/docs/OPERATIONS.md +23 -32
- package/docs/POLICIES.md +27 -8
- package/docs/PRERENDER.md +25 -13
- package/docs/PROJECT-DIRECTION.md +35 -10
- package/docs/READINESS.md +6 -2
- package/docs/README.md +20 -41
- package/docs/RELEASE-0.4.0-alpha.3.md +50 -0
- package/docs/RELEASE-READINESS.md +50 -30
- package/docs/RELEASE-SECURITY.md +72 -86
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +7 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +42 -2
- package/docs/SPECIFICATION.md +63 -27
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +288 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +16 -0
- package/docs/SPIKE-CORE-LAYERING.md +368 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +211 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +12 -2
- package/docs/STARTERS.md +1 -1
- package/docs/STATIC.md +105 -0
- package/docs/TOOLING.md +17 -12
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +32 -12
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +46 -0
- package/docs/YAML-GUIDE.md +0 -3
- package/docs/YAML-REFERENCE.md +16 -6
- package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +68 -0
- package/docs/{MANAGEMENT-SECURITY.md → archive/2026-09-19/MANAGEMENT-SECURITY.md} +20 -0
- package/docs/{NEXT-PHASE-PLAN.md → archive/2026-09-19/NEXT-PHASE-PLAN.md} +26 -8
- package/docs/{NEXT-STEPS.md → archive/2026-09-19/NEXT-STEPS.md} +274 -43
- 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 +386 -0
- package/docs/{SPIKE-EXTENSION-MODEL.md → archive/2026-09-19/SPIKE-EXTENSION-MODEL.md} +12 -2
- package/docs/{SPIKE-EXTENSIONS.md → archive/2026-09-19/SPIKE-EXTENSIONS.md} +28 -12
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +776 -0
- package/docs/{USABILITY-REVIEW.md → archive/2026-09-19/USABILITY-REVIEW.md} +18 -2
- package/docs/archive/README.md +27 -0
- package/docs/policies/agents.md +1 -1
- package/docs/policies/cache.md +13 -0
- package/docs/policies/compression.md +3 -2
- package/docs/policies/security.md +3 -2
- package/examples/assets/example.yaml +2 -2
- 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/cookbook/route-index.json +1 -1
- package/examples/cookbook/routes/middleware.yaml +1 -1
- package/examples/egress/example.yaml +1 -1
- package/examples/extensions/example.yaml +1 -1
- package/examples/prerender/README.md +14 -6
- package/examples/prerender/example.yaml +1 -1
- 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/examples/provider-conformance/example.yaml +1 -1
- package/examples/vercel/example.yaml +1 -1
- package/llms-full.txt +686 -239
- package/llms.txt +27 -15
- package/package.json +32 -5
- package/packaging/claude-plugin/.claude-plugin/plugin.json +2 -2
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +36 -22
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +16 -22
- 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 +2 -2
- package/recipes/contact-form/functions/contact.mjs +2 -1
- package/recipes/contact-form/recipe.yaml +3 -3
- package/recipes/cors-api/README.md +2 -2
- package/recipes/cors-api/recipe.yaml +2 -2
- package/recipes/health-page/README.md +1 -1
- package/recipes/health-page/recipe.yaml +1 -1
- package/recipes/json-api/README.md +1 -1
- package/recipes/json-api/recipe.yaml +4 -4
- package/recipes/middleware/README.md +8 -4
- 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/README.md +1 -1
- package/recipes/protected-download/recipe.yaml +2 -2
- package/recipes/redirect/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 +2 -2
- package/recipes/static-plus-api/urlcode.yaml +1 -1
- package/recipes/typescript/README.md +2 -1
- package/recipes/typescript/recipe.yaml +5 -5
- 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 +32 -11
- 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/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
package/docs/README.md
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
# URLCode documentation
|
|
2
2
|
|
|
3
|
-
> **Public documentation has moved to
|
|
4
|
-
> [urlcode-docs](https://github.com/jimhoyd-com/urlcode-docs).** That repository
|
|
5
|
-
> is the documentation home and is authored directly — this tree is no longer
|
|
6
|
-
> mirrored into it. New reader-facing pages belong in urlcode-docs; `docs/` here
|
|
7
|
-
> keeps contributor and maintainer material (local development, CI, release
|
|
8
|
-
> process, reviews, spikes, plans and the generated field reference). The
|
|
9
|
-
> reader-facing pages still listed below are being migrated.
|
|
10
|
-
|
|
11
3
|
Start with [the framework](FRAMEWORK.md): the four packages, the ladder from
|
|
12
4
|
redirects to a full application, the composition contract and the rules an AI
|
|
13
5
|
agent must follow. [Project direction](PROJECT-DIRECTION.md) states the
|
|
@@ -24,18 +16,14 @@ boundary and the license. Use documentation pinned to your runtime revision;
|
|
|
24
16
|
| Let an AI build routes | [AI authoring guide](AI-AUTHORING.md), [llms.txt](../llms.txt) |
|
|
25
17
|
| Load authoring/operations rules into an agent | [Authoring skill](../.claude/skills/urlcode-authoring/SKILL.md), [operations skill](../.claude/skills/urlcode-operations/SKILL.md), [how they are distributed](AI-AUTHORING.md#agent-skills) |
|
|
26
18
|
| Run examples | [25-route cookbook](../examples/cookbook/README.md), [prerender recipe](../examples/prerender/README.md), [small starter](STARTERS.md) |
|
|
27
|
-
| Explore a standalone application | [URLCode Shortener demo](https://github.com/jimhoyd-com/urlcode-shortener), [build retrospective](https://github.com/jimhoyd-com/urlcode-shortener/blob/main/docs/BUILD-RETROSPECTIVE.md) |
|
|
28
|
-
| Explore a static docs-site integration | [URLCode Docs project](https://github.com/jimhoyd-com/urlcode-docs), [build retrospective](https://github.com/jimhoyd-com/urlcode-docs/blob/main/docs/BUILD-RETROSPECTIVE.md) — synced from this repository, which remains the source of truth |
|
|
29
|
-
| Create/update short links live | [Dynamic links, storage and management API](DYNAMIC-LINKS.md) |
|
|
30
19
|
| Understand exact behavior | [Specification](SPECIFICATION.md), [routing](ROUTING.md), [HTTP](HTTP.md) |
|
|
31
20
|
| Run examples | [40-route cookbook](../examples/cookbook/README.md), [prerender recipe](../examples/prerender/README.md), [small starter](STARTERS.md) |
|
|
32
21
|
| Let an AI build routes | [The framework](FRAMEWORK.md), [AI authoring guide](AI-AUTHORING.md), [llms.txt](../llms.txt), [SDK and read-only MCP](TOOLING.md) |
|
|
33
22
|
| Reuse code around routes | [Middleware](MIDDLEWARE.md), [middleware examples](MIDDLEWARE-EXAMPLES.md) |
|
|
34
|
-
| Handle secrets and
|
|
23
|
+
| Handle secrets and decide what to sandbox | [Function security](FUNCTION-SECURITY.md) |
|
|
35
24
|
| Author guest functions in TypeScript | [Build-time guest transpilation](TYPESCRIPT-AUTHORING.md) |
|
|
36
25
|
| Serve pages, files and downloads | [Assets](ASSETS.md) |
|
|
37
26
|
| Publish a site with no request-time guest code | [Prerendering helper and recipe](PRERENDER.md) |
|
|
38
|
-
| Create and update short links live | [Dynamic links, storage and management API](DYNAMIC-LINKS.md) |
|
|
39
27
|
| Select response branches | [Exact conditions](CONDITIONS.md) |
|
|
40
28
|
| Proxy an API or emit a webhook | [Bounded egress and operator grants](EGRESS.md) |
|
|
41
29
|
| Throttle, block agents, set security headers, compress or cache | [Policies](POLICIES.md): [throttle](policies/throttle.md), [agents](policies/agents.md), [security](policies/security.md), [compression](policies/compression.md), [cache](policies/cache.md) |
|
|
@@ -53,8 +41,10 @@ boundary and the license. Use documentation pinned to your runtime revision;
|
|
|
53
41
|
|---|---|
|
|
54
42
|
| Add accounts, sign-in and protected routes | [urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth#readme) |
|
|
55
43
|
| Manage users, sessions, roles and audit | [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin#readme) |
|
|
56
|
-
| Restyle every extension page and translate copy | [urlcode-ui](
|
|
44
|
+
| Restyle every extension page and translate copy | [urlcode-ui](../packages/ui#readme), [ui contract](../packages/ui/CONTRACT.md) |
|
|
57
45
|
| Write or install a versioned extension | [Extensions](EXTENSIONS.md), [example fixture](../examples/extensions/README.md) |
|
|
46
|
+
| Follow implementation of the auth, admin and UI extensions | [Extension implementation sequence](archive/2026-09-19/EXTENSION-IMPLEMENTATION.md) |
|
|
47
|
+
| Know which core version an extension package supports, and how it says so | [Core version alignment](VERSION-ALIGNMENT.md) |
|
|
58
48
|
| Add host behavior in operator code | [Plugins](PLUGINS.md) |
|
|
59
49
|
| Use the API from TypeScript | [TypeScript: shipped declarations, exports, build and fidelity](TYPESCRIPT.md) |
|
|
60
50
|
|
|
@@ -69,11 +59,6 @@ boundary and the license. Use documentation pinned to your runtime revision;
|
|
|
69
59
|
| Review security findings and gaps | [Internal security audit](SECURITY-AUDIT.md) |
|
|
70
60
|
| Assess release readiness | [Evidence and open gates](RELEASE-READINESS.md) |
|
|
71
61
|
| See unfinished work | [Roadmap](../ROADMAP.md) |
|
|
72
|
-
| Read the design behind policies, plugins and templates | [Extensions spike](SPIKE-EXTENSIONS.md) |
|
|
73
|
-
| Read the design for an authentication and authorization plugin | [Auth spike](SPIKE-AUTH.md) |
|
|
74
|
-
| Read the design for the administration extension that manages users | [Admin spike](SPIKE-ADMIN.md) |
|
|
75
|
-
| Read the design for the shared template kit every extension renders with | [UI kit spike](SPIKE-UI.md) |
|
|
76
|
-
| Read the review of the extension model, its precedents and alignment | [Extension model review](SPIKE-EXTENSION-MODEL.md) |
|
|
77
62
|
| Read the design for compiling function routes into per-route Lambdas | [Lambda compile spike](SPIKE-LAMBDA-COMPILE.md) |
|
|
78
63
|
| Verify a running deployment matches the project | [Deployment checks](DEPLOYMENT-CHECKS.md) |
|
|
79
64
|
| Inspect target support | [Capabilities and normalized representation](CAPABILITIES.md) |
|
|
@@ -81,29 +66,23 @@ boundary and the license. Use documentation pinned to your runtime revision;
|
|
|
81
66
|
| Watch a deployment | [Monitoring](MONITORING.md), [observability](OBSERVABILITY.md) |
|
|
82
67
|
| Estimate concurrency and memory | [Capacity and limits](CAPACITY.md), [measurements](PERFORMANCE.md), [load testing](LOAD-TESTING.md) |
|
|
83
68
|
| Prepare for overload, DDoS and recovery | [Resilience playbook](RESILIENCE.md) |
|
|
84
|
-
| Manage private credentials and audit | [Management security](MANAGEMENT-SECURITY.md) |
|
|
85
69
|
|
|
86
|
-
##
|
|
70
|
+
## Direction and evidence
|
|
87
71
|
|
|
88
|
-
|
|
89
|
-
|
|
72
|
+
Start with [principles and open decisions](OPEN-DECISIONS.md) for a plain-language
|
|
73
|
+
review and [the roadmap](../ROADMAP.md) for next work. Current behavior belongs
|
|
74
|
+
in the guides above and the [specification](SPECIFICATION.md).
|
|
90
75
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
| [Release security](RELEASE-SECURITY.md) | Candidate signing and publication process |
|
|
102
|
-
| [Extension model review](SPIKE-EXTENSION-MODEL.md) | Why extensions are shaped this way, with framework precedents |
|
|
103
|
-
| [Extensions spike](SPIKE-EXTENSIONS.md) | The design behind policies and plugins; implemented |
|
|
104
|
-
| [Lambda compile spike](SPIKE-LAMBDA-COMPILE.md) | Proposal: per-route Lambdas for functions; not implemented |
|
|
105
|
-
| Auth, admin and UI spikes | Live in their repositories: [auth](https://github.com/jimhoyd-com/urlcode-auth/blob/main/docs/SPIKE-AUTH.md), [admin](https://github.com/jimhoyd-com/urlcode-admin/blob/main/docs/SPIKE-ADMIN.md), [ui](https://github.com/jimhoyd-com/urlcode-ui/blob/main/docs/SPIKE-UI.md) |
|
|
106
|
-
| [Roadmap](../ROADMAP.md) | Implemented versus planned |
|
|
76
|
+
- [Release readiness](RELEASE-READINESS.md), [security audit](SECURITY-AUDIT.md),
|
|
77
|
+
[sandbox review](SANDBOX-REVIEW.md) and [provider evidence](PROVIDER-VERIFICATION.md)
|
|
78
|
+
distinguish implementation from evidence still missing.
|
|
79
|
+
- [Version alignment](VERSION-ALIGNMENT.md) and [release security](RELEASE-SECURITY.md)
|
|
80
|
+
describe peer compatibility and publication.
|
|
81
|
+
- Open proposals: [middleware layering](SPIKE-CORE-LAYERING.md),
|
|
82
|
+
[Lambda compilation](SPIKE-LAMBDA-COMPILE.md),
|
|
83
|
+
[agent benchmark](SPIKE-AI-FRAMEWORK-BENCHMARK.md), and
|
|
84
|
+
[business suite](SPIKE-BUSINESS-SUITE.md). None is an implementation promise.
|
|
85
|
+
- [Historical plans and reviews](archive/README.md) are archived separately.
|
|
107
86
|
|
|
108
|
-
Examples are educational unless backed by
|
|
109
|
-
|
|
87
|
+
Examples are educational unless backed by runnable fixtures. Infrastructure
|
|
88
|
+
limits are deployment settings, not fields to invent in route YAML.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Coordinated 0.4.0-alpha.3 release
|
|
2
|
+
|
|
3
|
+
This release prepares core, UI, auth and admin at `0.4.0-alpha.3`, as explicitly
|
|
4
|
+
selected by the maintainer. The shared number identifies this tested package
|
|
5
|
+
set; it does not enable permanent fixed versioning or leave the alpha channel.
|
|
6
|
+
Existing versions, tags, and npm `latest` channels are preserved.
|
|
7
|
+
|
|
8
|
+
## Included changes
|
|
9
|
+
|
|
10
|
+
Core includes the monorepo consolidation, corrected Windows npm invocation,
|
|
11
|
+
current trust-by-default authoring guidance, and support for a TypeScript module
|
|
12
|
+
shared by trusted and sandboxed routes without weakening the sandbox checks.
|
|
13
|
+
The CLI and MCP report the new runtime version. The runtime remains independent
|
|
14
|
+
of the extension implementations.
|
|
15
|
+
|
|
16
|
+
Auth includes deterministic worker cleanup on rejected initialization and
|
|
17
|
+
Windows backup flushing. Auth/admin refresh a lifecycle hook's entry module on
|
|
18
|
+
each activation; changes to the entry module's own imports still require restart.
|
|
19
|
+
The extension changelogs record their package-specific changes.
|
|
20
|
+
|
|
21
|
+
All four packages use the shared release coordinator, immutable release tags,
|
|
22
|
+
exact-commit full verification, retained retry artifacts and trusted npm
|
|
23
|
+
publication. The candidate rehearsal installs their tarballs together outside
|
|
24
|
+
the workspace and checks peers, public imports and scaffolding.
|
|
25
|
+
|
|
26
|
+
## Installation and compatibility
|
|
27
|
+
|
|
28
|
+
Once publication has completed, install an exact, coordinated set in the
|
|
29
|
+
consumer application's directory:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install --save-exact @jimhoyd/urlcode@0.4.0-alpha.3 @jimhoyd/urlcode-ui@0.4.0-alpha.3 @jimhoyd/urlcode-auth@0.4.0-alpha.3 @jimhoyd/urlcode-admin@0.4.0-alpha.3
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Applications only need the extensions they actually use; admin requires auth
|
|
36
|
+
and UI, and auth requires UI. Auth/admin peer floors for this release are
|
|
37
|
+
`>=0.4.0-alpha.3 <0.5.0`. Update their dependencies together when crossing from
|
|
38
|
+
the former `0.1.x` extension line. Commit the resulting lockfile and use `npm ci`
|
|
39
|
+
in deployment. This release changes package peer compatibility intentionally;
|
|
40
|
+
it does not imply all previously mixed versions are supported.
|
|
41
|
+
|
|
42
|
+
Publication order is core, UI, auth, admin. A partial release stops before the
|
|
43
|
+
next package; diagnose and rerun its original workflow without moving tags.
|
|
44
|
+
The standalone template remains an exact core consumer and is updated through
|
|
45
|
+
its own PR after core is published. Archived extension repositories are not
|
|
46
|
+
publication targets.
|
|
47
|
+
|
|
48
|
+
CI and candidate success are not independent security assessment, live-provider
|
|
49
|
+
acceptance, or operational recovery proof. The intermittent Windows startup
|
|
50
|
+
timeout remains tracked in #202.
|
|
@@ -1,42 +1,59 @@
|
|
|
1
1
|
# Release readiness
|
|
2
2
|
|
|
3
|
-
Status: `0.4.0-alpha.
|
|
4
|
-
top of the `0.3.0` self-hosted release.
|
|
3
|
+
Status: `0.4.0-alpha.2` (`package.json`) alpha of the extension contract and
|
|
4
|
+
agent tooling on top of the `0.3.0` self-hosted release; `0.4.0-alpha.1` is the
|
|
5
|
+
most recent alpha actually published; the npm dist-tags for `@jimhoyd/urlcode`
|
|
6
|
+
were `latest` = `0.3.0` and `alpha` = `0.4.0-alpha.1` when checked against the
|
|
7
|
+
registry on 2026-09-19, so the repository's `0.4.0-alpha.2` is unpublished (see
|
|
8
|
+
"Packaging" below). Production approval remains specific to
|
|
5
9
|
the workload and deployment environment.
|
|
6
10
|
This register describes the current public runtime, not future promises.
|
|
7
11
|
Use the contract and docs from the same pinned commit as your installed runtime.
|
|
8
12
|
|
|
9
13
|
## What is aligned
|
|
10
14
|
|
|
11
|
-
- One portable YAML project, explicit includes, one handler per route (redirect, respond, page, static, download, function,
|
|
15
|
+
- One portable YAML project, explicit includes, one handler per route (redirect, respond, page, static, download, function, proxy, conditional or extension),
|
|
12
16
|
per-route middleware and consistent request/response validation.
|
|
13
17
|
- One starter with a function route first and an ordinary redirect second.
|
|
14
18
|
Clone urlcode-template or use `urlcode init`; neither requires a database.
|
|
15
19
|
- Native handlers avoid user-code execution unless middleware is attached.
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
- Functions/middleware run trusted and unsandboxed by default (in-process,
|
|
21
|
+
full Node access); `sandbox: true` opts a route into isolated QuickJS/WASM
|
|
22
|
+
with no ambient filesystem, network or Node APIs (docs/SPIKE-DEFAULT-TRUST-MODEL.md).
|
|
23
|
+
Host bindings require external revision-pinned approval either way.
|
|
20
24
|
- The runtime is released under Apache-2.0.
|
|
21
25
|
|
|
22
26
|
## Regression evidence
|
|
23
27
|
|
|
24
28
|
`npm run verify` is the lint, syntax/schema-reference and unit/HTTP regression gate.
|
|
25
29
|
`npm run test:package` installs the packed artifact and exercises initialized apps,
|
|
26
|
-
route audits, bounded benchmarks
|
|
27
|
-
Linux/macOS/Windows and tests the container
|
|
30
|
+
route audits, bounded benchmarks and assets. On a push to `main`, CI runs Node
|
|
31
|
+
22/24/26 on Linux/macOS/Windows (nine combinations) and tests the container
|
|
32
|
+
under resource restrictions; a pull request runs the same Node versions on
|
|
33
|
+
Linux only (`.github/workflows/ci.yml`'s matrix), with the macOS/Windows legs
|
|
34
|
+
deferred to the post-merge run.
|
|
28
35
|
|
|
29
36
|
| Area | Covered behavior | Practical limit |
|
|
30
37
|
|---|---|---|
|
|
31
38
|
| Routing and HTTP | Exact/parameter/static precedence, methods, inputs, assets, middleware and response assertions | Stable 0.1 contract; unsupported semantics reject rather than emulate |
|
|
32
|
-
| Isolation |
|
|
33
|
-
| Overload | Function
|
|
34
|
-
| Worker replacement | Repeated guest deadlines shed load and the pool returns to service after backoff, rather than latching off for the life of the process |
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
| Isolation | `sandbox: true` capability/permission boundaries, deadlines, memory and invalid outputs; the trusted default's grant scoping | Not an independent security assessment or multi-tenant service certification; trusted-route code safety is the project's own call |
|
|
40
|
+
| Overload | Function pool queue caps; HTTP admission saturation, separate bounded probe budget, health availability and recovery after upload completion/disconnect | 64 application requests default; no fairness, upstream DDoS protection or end-to-end deadline |
|
|
41
|
+
| Worker replacement | Repeated guest deadlines shed load and the pool returns to service after backoff, rather than latching off for the life of the process | Bounded by the configured worker count; no cross-process load balancing |
|
|
42
|
+
| Shutdown | New work rejects; repeated close shares completion | Existing deadlines can still fail during shutdown |
|
|
43
|
+
| Activation/recovery | Invalid reload retains last-good snapshot; corrupt revision metadata rejects activation | No deployment orchestration |
|
|
44
|
+
| Packaging | Packed installation and starter examples tested; sensitive files excluded | `0.3.0` and `0.4.0-alpha.1` are published to npm as `@jimhoyd/urlcode` (`latest` and `alpha` dist-tags respectively; dist-tags verified against the npm registry on 2026-09-19, when the repository stood at the unpublished `0.4.0-alpha.2`). Published extension packages on the same date: `@jimhoyd/urlcode-auth@0.1.0-alpha.2`, `@jimhoyd/urlcode-admin@0.1.0-alpha.2`, `@jimhoyd/urlcode-ui@0.1.0-alpha.4`. (`@jimhoyd/urlcode-short@0.1.0-alpha.1`, `@jimhoyd/urlcode-dynamic-link@0.1.0-alpha.1` and `@jimhoyd/urlcode-middleware@0.1.0-alpha.2` were also published on that date, then retired and unpublished later the same day; all three repositories were deleted. Middleware's withdrawal removed no capability — per-route middleware is native to core.) Observed in passing on that date: auth's dist-tags were split — `alpha` at `0.1.0-alpha.2` while `latest` lagged at `0.1.0-alpha.1`, so a plain `npm install @jimhoyd/urlcode-auth` resolved a build below admin's declared floor. That is resolved: auth and admin both read `latest` = `alpha` = `0.1.0-alpha.3`. `@jimhoyd/urlcode-ui` now carries a split of its own — `alpha` = `0.1.0-alpha.6`, `latest` = `0.1.0-alpha.5` — which is deliberate rather than drift, and safe only because admin's ui floor is exactly `>=0.1.0-alpha.5`. See [VERSION-ALIGNMENT.md](VERSION-ALIGNMENT.md). GitHub Releases attach a Homebrew formula (`urlcode.rb`) for manual copy into a tap, not an automated Homebrew Core/tap publish. No provider adapter guarantee. |
|
|
45
|
+
|
|
46
|
+
`npm run check:downstream-skills` is a manual, advisory report worth running
|
|
47
|
+
before a release: it diffs core's `.claude/skills/` copies against copies
|
|
48
|
+
vendored by downstream repositories (currently `urlcode-template`) when that
|
|
49
|
+
repository is cloned as a sibling checkout, and prints how many lines differ
|
|
50
|
+
per skill. It never fails and never asserts which side is correct -- a
|
|
51
|
+
downstream repo commonly pins an older published core version, and
|
|
52
|
+
divergence from core's current `main` can be the *correct* reflection of
|
|
53
|
+
that pin rather than staleness (see issue #155). It is not part of `check`
|
|
54
|
+
or `verify` because it depends on an out-of-repo sibling checkout that
|
|
55
|
+
normal CI does not have; it is a prompt to review the diff against the
|
|
56
|
+
downstream pin, not a pass/fail gate.
|
|
40
57
|
|
|
41
58
|
`npm audit --omit=dev` now runs in CI and fails the build on any runtime advisory;
|
|
42
59
|
development-only advisories are reported without blocking. Dependabot proposes npm,
|
|
@@ -50,22 +67,20 @@ These remain open. Record workload, runtime/app/image revisions, environment,
|
|
|
50
67
|
commands, results and owner for each exercise; do not convert a passing local
|
|
51
68
|
benchmark into a universal throughput claim.
|
|
52
69
|
|
|
53
|
-
1. Independent review of host/sandbox boundaries
|
|
70
|
+
1. Independent review of host/sandbox boundaries.
|
|
54
71
|
2. Sustained load and soak on intended hardware, through the actual TLS/proxy
|
|
55
72
|
path: successful throughput, tail latency, 503/504 rate, RSS and recovery.
|
|
56
73
|
`urlcode benchmark --target` measures a running deployment through its real
|
|
57
74
|
path and separates shed responses from transport errors; see
|
|
58
75
|
[load testing](LOAD-TESTING.md). The tool is GET/HEAD only and caps at 300
|
|
59
76
|
seconds, so it does not by itself close this gate.
|
|
60
|
-
Include mixed native/function
|
|
61
|
-
3.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
4.
|
|
65
|
-
exercises with the chosen supervisor, ingress and persistent storage.
|
|
66
|
-
5. Alerting and ownership for sustained errors, latency, readiness, dropped logs,
|
|
77
|
+
Include mixed native/function workloads and slow peers.
|
|
78
|
+
3. Kill/restart, resource exhaustion and rolling deployment/rollback
|
|
79
|
+
exercises with the chosen supervisor and ingress. A future durable-state
|
|
80
|
+
extension needs its own backup/restore drill; core has no durable store.
|
|
81
|
+
4. Alerting and ownership for sustained errors, latency, readiness, dropped logs,
|
|
67
82
|
disk space, restarts and backups. Pick service objectives for the actual app.
|
|
68
|
-
|
|
83
|
+
5. Stable-release support commitments before packaging/public reuse claims.
|
|
69
84
|
Private security reporting and the current support baseline are documented in
|
|
70
85
|
SECURITY.md.
|
|
71
86
|
|
|
@@ -78,7 +93,7 @@ local recipes, TypeScript authoring, bounded self-hosted proxy/signals and read-
|
|
|
78
93
|
MCP. Local AWS/Vercel/Cloudflare adapter tests and deployment probe tooling exist,
|
|
79
94
|
but actual provider deployments remain unverified. Node process/container hosting
|
|
80
95
|
remains the reference execution target. Guest networking, durable signals and
|
|
81
|
-
realtime capabilities are not provided. See [implementation status](NEXT-PHASE-PLAN.md)
|
|
96
|
+
realtime capabilities are not provided. See [implementation status](archive/2026-09-19/NEXT-PHASE-PLAN.md)
|
|
82
97
|
and [roadmap](../ROADMAP.md); these additions do not close the operational gates above.
|
|
83
98
|
|
|
84
99
|
The [internal security audit](SECURITY-AUDIT.md) records reproduced findings, fixes
|
|
@@ -88,9 +103,14 @@ independent assessment or real deployment exercises.
|
|
|
88
103
|
## Hardening follow-up
|
|
89
104
|
|
|
90
105
|
Implemented: bounded YAML workers and aggregate source budgets, cooperative route
|
|
91
|
-
compilation deadline,
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
compilation deadline, scoped/expiring/revocable operator credentials for host
|
|
107
|
+
bindings, executable local/CI operational drills, and a main-only candidate
|
|
108
|
+
signing/SBOM workflow. The loopback-only management API and its atomic SQLite
|
|
109
|
+
mutation audits were part of the `link`/`dynamicLinks` store that PR #126
|
|
110
|
+
removed from core; that functionality moved to the `urlcode-dynamic-link`
|
|
111
|
+
extension (docs/EXTENSIONS.md), which was retired and unpublished on
|
|
112
|
+
2026-09-19. No supported stored-link package ships today, and this runtime does
|
|
113
|
+
not provide one: a project needing a durable link store owns it itself.
|
|
94
114
|
|
|
95
115
|
Still required: [independent review](SANDBOX-REVIEW.md), [actual deployment proof](OPERATIONAL-PROOF.md),
|
|
96
116
|
and publication/support arrangements. The Apache-2.0 license and the 0.3.0 self-hosted
|
package/docs/RELEASE-SECURITY.md
CHANGED
|
@@ -1,95 +1,81 @@
|
|
|
1
|
-
# Candidate and release security
|
|
1
|
+
# Candidate and release security
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The [development pipeline](DEVELOPMENT-PIPELINE.md) is the operational runbook
|
|
4
|
+
for CI selection, release planning, tags, publication and recovery. The
|
|
5
|
+
[September 19 audit](CI-RELEASE-AUDIT-2026-09-19.md) explains the changes;
|
|
6
|
+
[the prior process and failure history](archive/2026-09-19/RELEASE-SECURITY.md)
|
|
7
|
+
is retained as a historical record, not current instructions.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- `release.yml` runs on a `v*` tag whose commit is already on main, and publishes
|
|
11
|
-
a GitHub release. Publication to npm and GHCR is opt-in per repository variable
|
|
12
|
-
(`PUBLISH_NPM`, `PUBLISH_CONTAINER`), so a release can be artifacts-only.
|
|
9
|
+
The license remains Apache-2.0. A successful release is not an independent
|
|
10
|
+
security assessment, hostile multi-tenant readiness claim or deployment proof.
|
|
11
|
+
See [release readiness](RELEASE-READINESS.md) and [security](../SECURITY.md).
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
[release readiness](RELEASE-READINESS.md).
|
|
13
|
+
## Source and validation
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
A release must name the checked-out commit, already on main, with successful
|
|
16
|
+
full verification of that exact SHA and CodeQL analysis. Full verification
|
|
17
|
+
means a successful nightly or manual `ci.yml` run across every supported OS/Node
|
|
18
|
+
combination; the compact push/PR matrix alone does not authorize publication. Package manifests,
|
|
19
|
+
lockfile versions and tag names must agree. Published peer floors must exist and
|
|
20
|
+
extension tests must resolve the published packages, not workspace source.
|
|
21
|
+
The manual core candidate and tagged core release use the same preparation
|
|
22
|
+
script with the digest-pinned Node image from Dockerfile. Locked dependencies,
|
|
23
|
+
verification, runtime audit, package installation tests and local drills precede
|
|
24
|
+
packing. Build commands in that container receive no GitHub token.
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`@jimhoyd/urlcode >=0.4.0-alpha.1 <0.5.0` and must resolve the core alpha.
|
|
26
|
+
The candidate workflow stores artifacts without publishing. A tagged release
|
|
27
|
+
publishes npm only when `PUBLISH_NPM=true` and core images only when
|
|
28
|
+
`PUBLISH_CONTAINER=true`. Preparation retains original artifacts for 90 days
|
|
29
|
+
before publication so reruns of the same run reuse them. Manual candidates retain
|
|
30
|
+
their existing 30-day retention. Keep independent last-good artifacts and
|
|
31
|
+
rehearse deployment rollback; Actions retention is not an archival guarantee.
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
The maintainer triages impact, confirms affected exact revisions, coordinates a
|
|
29
|
-
fix/retest privately, and publishes an advisory with upgrade guidance when safe.
|
|
30
|
-
Current reviewed main is the security support baseline; no guaranteed SLA/backports.
|
|
31
|
-
2. Change dependencies through protected PRs. Review upstream provenance/advisories,
|
|
32
|
-
lockfile integrity and tests. Direct dependencies are exact, npm installs use
|
|
33
|
-
`npm ci`, CI actions use full commit SHAs, and container bases use SHA-256 digests.
|
|
34
|
-
Dependabot proposes updates; it does not authorize merging. Never silently
|
|
35
|
-
refresh dependencies during a candidate build.
|
|
36
|
-
3. After protected main checks pass, a maintainer manually dispatches
|
|
37
|
-
`.github/workflows/candidate.yml` **on main**, or pushes a `v<version>` tag to
|
|
38
|
-
run `.github/workflows/release.yml`. The release workflow refuses a tag whose
|
|
39
|
-
commit is not an ancestor of main, refuses a tag that disagrees with
|
|
40
|
-
`package.json`, and refuses to build a private or unlicensed package. It reads and validates the digest-pinned Node image directly from Dockerfile,
|
|
41
|
-
installs without lifecycle scripts, verifies, package-tests and runs local drills.
|
|
42
|
-
It packs the runtime and creates a CycloneDX dependency SBOM plus a manifest
|
|
43
|
-
recording source commit, lockfile hash, engine versions and artifact hashes.
|
|
44
|
-
The package contains `dist/`, produced inside that build from the tagged
|
|
45
|
-
TypeScript sources by Node's type stripping (`scripts/build.ts`); `dist` is
|
|
46
|
-
never committed. The manifest records the Node version that stripped it, the
|
|
47
|
-
locked TypeScript version and a SHA-256 per emitted file
|
|
48
|
-
(`dist/BUILD-MANIFEST.json`), so a download can be verified by running
|
|
49
|
-
`npm run build` on the tagged commit with that Node version and comparing its
|
|
50
|
-
`dist/` file by file. The build strips types and rewrites specifier
|
|
51
|
-
extensions; it never bundles, minifies or transforms syntax, so every line of
|
|
52
|
-
`dist/x.js` is the corresponding line of `src/x.ts`. CI's `build-fidelity`
|
|
53
|
-
job builds twice and diffs the trees, so the transform is known to be
|
|
54
|
-
deterministic before a tag is cut.
|
|
55
|
-
4. The pinned official `actions/attest` action signs provenance for the package,
|
|
56
|
-
SBOM and manifest using short-lived GitHub OIDC/Sigstore credentials. No long-lived
|
|
57
|
-
signing key is stored. Signing permissions exist only in this manual job; build
|
|
58
|
-
commands run in a container without passing GitHub tokens. Candidate files are
|
|
59
|
-
retained as GitHub Actions artifacts for 30 days. A release additionally attaches
|
|
60
|
-
them to the GitHub release, and publishes to npm and to GHCR when those
|
|
61
|
-
repository variables are enabled.
|
|
33
|
+
## Identity and provenance
|
|
62
34
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this package's name. Provenance is generated on that same identity, so
|
|
69
|
-
`--provenance` is not passed and its absence is not a downgrade.
|
|
35
|
+
The four per-package workflow filenames are stable npm trusted-publisher
|
|
36
|
+
identities. npm publishing uses OIDC, npm 11.5.1 and a supported Node version,
|
|
37
|
+
with no long-lived npm token. Renaming a workflow or changing the repository
|
|
38
|
+
requires a reviewed registry trust migration. Successful preparation does not
|
|
39
|
+
prove the registry-side identity permits direct publication.
|
|
70
40
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`gh attestation verify jimhoyd-urlcode-0.3.0.tgz --repo jimhoyd-com/urlcode --signer-workflow jimhoyd-com/urlcode/.github/workflows/candidate.yml --source-ref refs/heads/main --source-digest APPROVED_COMMIT_SHA`
|
|
77
|
-
(use `release.yml` as the signer workflow for a tagged release).
|
|
78
|
-
Check the verified provenance's source commit against the approved commit, and
|
|
79
|
-
compare package/SBOM hashes with the signed manifest. A signature establishes
|
|
80
|
-
provenance, not safety, reproducible bytes or production approval. See
|
|
81
|
-
[GitHub verification](https://cli.github.com/manual/gh_attestation_verify) and
|
|
82
|
-
[the official attestation action](https://github.com/actions/attest).
|
|
83
|
-
6. Before registry publication, assign patch/release ownership and retention, and
|
|
84
|
-
document version/support policy. Before claiming hostile multi-tenant or
|
|
85
|
-
deployment-specific readiness, close independent-review and deployment gates. Keep last-good verified artifacts and compatible policies;
|
|
86
|
-
rehearse rollback. Never overwrite a published artifact/version or downgrade a
|
|
87
|
-
management writer past its audit/security baseline.
|
|
41
|
+
`actions/attest` signs the candidate files with GitHub OIDC/Sigstore provenance.
|
|
42
|
+
Core includes its package archive, dependency SBOM, build manifest, checksums,
|
|
43
|
+
and, for a release, Homebrew formula. Extensions include their archive and
|
|
44
|
+
checksums. The core manifest records source SHA, lockfile hash, Node and
|
|
45
|
+
TypeScript versions and emitted-file hashes. `dist/` is built, never committed.
|
|
88
46
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
47
|
+
Verify an artifact with `gh attestation verify <tarball> --repo
|
|
48
|
+
jimhoyd-com/urlcode`, and constrain verification to the expected workflow,
|
|
49
|
+
source ref and source digest for the selected release. Compare the source and
|
|
50
|
+
artifact hashes to the intended release, rather than accepting any signed file.
|
|
51
|
+
A signature establishes provenance, not safety or reproducibility. The npm SBOM
|
|
52
|
+
is not a complete OS/container SBOM; hosted runners remain platform-controlled.
|
|
53
|
+
|
|
54
|
+
## Immutability and channels
|
|
55
|
+
|
|
56
|
+
Never delete/recreate or move a version tag to repair a workflow. A source fix
|
|
57
|
+
requires a new version. Repeating publication of an existing npm version requires
|
|
58
|
+
identical SHA-512 integrity. GitHub assets are compared and missing assets added;
|
|
59
|
+
existing unequal assets are never clobbered. Transient registry errors fail
|
|
60
|
+
closed rather than count as an unpublished version.
|
|
61
|
+
|
|
62
|
+
Alpha versions use npm/GHCR `alpha` and GitHub prerelease classification. New
|
|
63
|
+
GitHub releases are not automatically promoted to GitHub `latest`. Mutable npm
|
|
64
|
+
and container channels cannot regress to an older version. Existing core image
|
|
65
|
+
versions are reused only with matching source labels; unlabeled historical
|
|
66
|
+
images require a reviewed migration rather than an inferred identity.
|
|
67
|
+
|
|
68
|
+
The coordinator creates one package tag at a time and waits for success before
|
|
69
|
+
releasing dependents. Shared publication concurrency avoids cross-version races.
|
|
70
|
+
The active immutable-tag rule blocks release tag updates/deletions with no
|
|
71
|
+
bypass actors; its configuration is in `.github/rulesets/release-tags.json`. No automation needs permission to bypass main checks or approve
|
|
72
|
+
its own PR. A repository-scoped GitHub App is the preferred eventual automation
|
|
73
|
+
identity; a narrowly scoped fine-grained PAT can support a maintainer script.
|
|
74
|
+
|
|
75
|
+
## Remaining validation
|
|
76
|
+
|
|
77
|
+
Keep full supported-OS/Node coverage and archive-install tests green. The actual
|
|
78
|
+
publish path, OIDC trust for every package, tag protection, GHCR behavior and
|
|
79
|
+
partial-failure recovery must be verified on an authorized release; local tests
|
|
80
|
+
and workflow inspection cannot prove them. The release helpers do not alter
|
|
81
|
+
historical npm channels, GitHub flags, tags or registry artifacts.
|
package/docs/RESILIENCE.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# DDoS, overload and recovery playbook
|
|
2
2
|
|
|
3
3
|
This is an operator plan for the current self-hosted release, not a claim of built-in DDoS
|
|
4
|
-
protection, managed failover or tested high availability. URLCode's
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
protection, managed failover or tested high availability. URLCode's resource
|
|
5
|
+
limits — the HTTP admission cap either way, plus the worker pool's own
|
|
6
|
+
deadline/queue-less ceiling for a `sandbox: true` route — reduce some failure
|
|
7
|
+
modes; they cannot protect a saturated network link. Keep the public origin
|
|
8
|
+
behind your existing protected ingress.
|
|
7
9
|
|
|
8
10
|
## Defense responsibilities
|
|
9
11
|
|
|
@@ -11,8 +13,8 @@ network link. Keep the public origin behind your existing protected ingress.
|
|
|
11
13
|
|---|---|---|
|
|
12
14
|
| Upstream network | Hosting/CDN DDoS mitigation and an escalation contact; protect bandwidth before it reaches the origin | No network-level mitigation service |
|
|
13
15
|
| Edge/proxy | TLS, per-client and aggregate request/connection budgets, header/body/time limits; restrict direct origin access | Private bind default; no automatic TLS/WAF. Optional per-instance [`throttle` and `agents` policies](POLICIES.md) as a second layer behind the edge, with `--trusted-proxies` naming the hops allowed to set `X-Forwarded-For` |
|
|
14
|
-
| Application | Validate inputs, bound expensive work, authenticate sensitive operations | Strict route/body validation; sandbox deadlines and no execution queue |
|
|
15
|
-
| Process/container | CPU/RAM/PID limits, restart backoff, least privilege, read-only reviewed app | Worker isolation, bounded worker replacement, health and request logs |
|
|
16
|
+
| Application | Validate inputs, bound expensive work, authenticate sensitive operations | Strict route/body validation; a `sandbox: true` route gets worker deadlines and no execution queue, a trusted (default) route shares the HTTP admission cap with no worker ceiling |
|
|
17
|
+
| Process/container | CPU/RAM/PID limits, restart backoff, least privilege, read-only reviewed app | Worker isolation for `sandbox: true` routes, bounded worker replacement, health and request logs |
|
|
16
18
|
| Release/recovery | Known-good artifacts, candidate verification, traffic switching, rollback drills | Local validation/tests/audit; explicit snapshot reload; no orchestration |
|
|
17
19
|
|
|
18
20
|
NGINX provides request-rate controls and connection controls keyed by values such
|
|
@@ -30,7 +32,8 @@ forwarded headers to construct its public URL; set `--origin` explicitly.
|
|
|
30
32
|
|
|
31
33
|
The optional [`throttle` policy](policies/throttle.md) adds a per-client budget
|
|
32
34
|
inside the runtime, and the [`agents` policy](policies/agents.md) refuses listed
|
|
33
|
-
User-Agents before a body is read or the
|
|
35
|
+
User-Agents before a body is read or the function/middleware call starts,
|
|
36
|
+
trusted or sandboxed. Both are a second
|
|
34
37
|
layer behind the edge, not a replacement for it: counters are per instance,
|
|
35
38
|
the socket and admission limits still apply first, and a flood still costs
|
|
36
39
|
connections. The client identity is the socket peer unless
|
|
@@ -50,8 +53,8 @@ is not implemented; adding a reverse proxy does not bypass runtime execution.
|
|
|
50
53
|
| Failure or traffic pattern | Current consequence | Mitigation / recovery |
|
|
51
54
|
|---|---|---|
|
|
52
55
|
| High-rate ordinary requests | Event-loop, logging, bandwidth or socket exhaustion | Filter/rate-limit upstream; scale only within measured resource/cost budgets |
|
|
53
|
-
| Flood of functions or middleware | Two default worker slots fill; further calls receive 503 | Bound programmable traffic before the origin; isolate heavy workloads |
|
|
54
|
-
| Infinite/slow application code | Shared invocation deadline returns 504; worker terminated/replaced | Identify bad release/route with protected diagnostics; roll back or block route at ingress |
|
|
56
|
+
| Flood of functions or middleware | Two default worker slots fill for `sandbox: true` routes; further calls receive 503. Trusted (default) routes shed load through the in-flight admission cap instead | Bound programmable traffic before the origin; isolate heavy workloads |
|
|
57
|
+
| Infinite/slow application code | Shared invocation deadline returns 504; a `sandbox: true` worker is terminated/replaced, while a trusted route blocking the event loop synchronously cannot be preempted ([capacity](CAPACITY.md)) | Identify bad release/route with protected diagnostics; roll back or block route at ingress |
|
|
55
58
|
| Guest invalid response or failure | Generic 502 | Compare with last deployment; run fixture on a private candidate |
|
|
56
59
|
| Repeated worker exits | Replacement backs off (250 ms doubling to 30 s) and keeps retrying; readiness stays 503 until every slot serves | Contain the cause; load is shed meanwhile. Replacement never stops, because a guest deadline is reachable from ordinary request input and must not disable functions until an operator restarts |
|
|
57
60
|
| Large/slow requests | 64 admitted application requests, body/header limits and receipt timeouts; copies still consume memory | Smaller proxy/body budgets and connection admission limits |
|
|
@@ -120,8 +123,8 @@ Choose RTO (acceptable recovery time) and RPO (acceptable data loss) per deploym
|
|
|
120
123
|
URLCode does not promise values. A stateless YAML deployment can be recreated
|
|
121
124
|
from retained immutable artifacts, subject to recovery of DNS/ingress and secret
|
|
122
125
|
access. Log loss is possible under pressure and has a separate retention target.
|
|
123
|
-
|
|
124
|
-
verification; Git route configuration does not back up runtime data.
|
|
126
|
+
Future app-owned or extension-owned durable state needs its own backups and
|
|
127
|
+
restore verification; Git route configuration does not back up runtime data.
|
|
125
128
|
|
|
126
129
|
A rollback needs the previous app/runtime and its matching policy and compatible
|
|
127
130
|
secret bindings. The health version combines configuration and asset digests;
|
|
@@ -153,8 +156,6 @@ admission/fairness, production metrics/exporters, dedicated slow-reader protecti
|
|
|
153
156
|
provider-level mitigation validation and sustained failure/soak testing. These are
|
|
154
157
|
free-runtime/operator requirements.
|
|
155
158
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
reloading/restarting. An uncertain mutation may have committed. See
|
|
160
|
-
[dynamic-link recovery](DYNAMIC-LINKS.md).
|
|
159
|
+
Core has no durable store of its own to recover; a durable-state extension is
|
|
160
|
+
responsible for its own management listener, backup and recovery procedure. No
|
|
161
|
+
such extension ships today — `urlcode-dynamic-link` has been retired.
|
package/docs/ROUTING.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Route matching
|
|
1
|
+
# Route matching
|
|
2
2
|
|
|
3
3
|
## Supported path patterns
|
|
4
4
|
|
|
@@ -49,7 +49,7 @@ route returning 405, 404, 410 or 400 does not fall through to another route.
|
|
|
49
49
|
Likewise, a missing file in the longest selected static mount does not fall back
|
|
50
50
|
to a shorter mount. See [HTTP](HTTP.md) and [the contract](SPECIFICATION.md).
|
|
51
51
|
|
|
52
|
-
## Adding a configured
|
|
52
|
+
## Adding a configured redirect today
|
|
53
53
|
|
|
54
54
|
```sh
|
|
55
55
|
urlcode add https://example.com/new-page --alias new-link --project ./my-links
|
|
@@ -83,13 +83,10 @@ and needs no route rebuild or service restart. The same distinction applies to
|
|
|
83
83
|
any per-visitor session record. Git owns route behavior and code; user-created records have
|
|
84
84
|
their own persistence, backup and export lifecycle.
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
Core has no native handler for this today: the `link` handler that implemented
|
|
87
|
+
it was removed. The `urlcode-dynamic-link` extension package that replaced it
|
|
88
|
+
has been retired and unpublished, so a project needing stored short links owns
|
|
89
|
+
that storage itself.
|
|
90
90
|
|
|
91
91
|
Functions still cannot access databases, the filesystem or network directly.
|
|
92
|
-
|
|
93
|
-
successful redirect. General application state and realtime sessions remain
|
|
94
|
-
future work. SQLite is optional and supports local same-host processes; a
|
|
95
|
-
multi-host deployment needs a different adapter. A cache is not the durable store.
|
|
92
|
+
General application state and realtime sessions remain future work.
|