@jimhoyd/urlcode 0.4.2 → 0.4.6

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.
Files changed (214) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +57 -14
  2. package/.claude/skills/urlcode-operations/SKILL.md +4 -0
  3. package/README.md +19 -15
  4. package/SECURITY.md +5 -3
  5. package/dist/BUILD-MANIFEST.json +30 -27
  6. package/dist/agent-context.js +82 -0
  7. package/dist/agents-guide.js +42 -42
  8. package/dist/authoring.js +12 -2
  9. package/dist/body-schema.js +159 -0
  10. package/dist/build-cloudflare.js +2 -0
  11. package/dist/capabilities.js +1 -1
  12. package/dist/cli.js +28 -12
  13. package/dist/config.js +74 -6
  14. package/dist/context.js +4 -6
  15. package/dist/errors.js +3 -1
  16. package/dist/examples.js +1 -1
  17. package/dist/extensions.js +60 -2
  18. package/dist/http-policy.js +19 -4
  19. package/dist/http-response.js +2 -2
  20. package/dist/init-with.js +71 -9
  21. package/dist/mcp.js +15 -2
  22. package/dist/pattern-guard.js +32 -0
  23. package/dist/policies/security.js +0 -0
  24. package/dist/project-tests.js +35 -11
  25. package/dist/readiness.js +184 -32
  26. package/dist/recipes.js +1 -1
  27. package/dist/router.js +17 -0
  28. package/dist/runtime.js +26 -3
  29. package/dist/scaffold.js +0 -0
  30. package/dist/server.js +26 -3
  31. package/dist/site.js +0 -0
  32. package/dist/tooling.js +2 -1
  33. package/dist/types/agent-context.d.ts +44 -0
  34. package/dist/types/authoring.d.ts +3 -1
  35. package/dist/types/body-schema.d.ts +58 -0
  36. package/dist/types/config.d.ts +10 -2
  37. package/dist/types/context.d.ts +1 -1
  38. package/dist/types/errors.d.ts +9 -1
  39. package/dist/types/examples.d.ts +1 -1
  40. package/dist/types/extensions.d.ts +47 -2
  41. package/dist/types/http-policy.d.ts +3 -0
  42. package/dist/types/init-with.d.ts +10 -1
  43. package/dist/types/pattern-guard.d.ts +10 -0
  44. package/dist/types/project-tests.d.ts +9 -0
  45. package/dist/types/readiness.d.ts +68 -0
  46. package/dist/types/recipes.d.ts +1 -1
  47. package/dist/types/runtime.d.ts +4 -0
  48. package/dist/types/server.d.ts +9 -1
  49. package/dist/types/tooling.d.ts +1 -0
  50. package/dist/types/types.d.ts +13 -0
  51. package/dist/types.js +10 -2
  52. package/dist/typescript-authoring.js +5 -3
  53. package/dist/verify-deployment.js +16 -10
  54. package/examples/body-validation/README.md +16 -0
  55. package/examples/body-validation/example.yaml +17 -0
  56. package/examples/body-validation/tests/requests.json +15 -0
  57. package/examples/body-validation/urlcode.yaml +34 -0
  58. package/examples/coverage-waiver/README.md +8 -0
  59. package/examples/coverage-waiver/example.yaml +16 -0
  60. package/examples/coverage-waiver/functions/notes.mjs +2 -0
  61. package/examples/coverage-waiver/tests/requests.json +3 -0
  62. package/examples/coverage-waiver/urlcode.yaml +10 -0
  63. package/examples/data-dir/README.md +39 -0
  64. package/examples/data-dir/data/welcome.txt +1 -0
  65. package/examples/data-dir/example.yaml +22 -0
  66. package/examples/data-dir/functions/note.mjs +18 -0
  67. package/examples/data-dir/tests/requests.json +6 -0
  68. package/examples/data-dir/urlcode.yaml +6 -0
  69. package/examples/lifecycle/README.md +15 -0
  70. package/examples/lifecycle/example.yaml +19 -0
  71. package/examples/lifecycle/functions/notes.mjs +29 -0
  72. package/examples/lifecycle/tests/requests.json +12 -0
  73. package/examples/lifecycle/urlcode.yaml +29 -0
  74. package/examples/not-found/README.md +10 -0
  75. package/examples/not-found/example.yaml +17 -0
  76. package/examples/not-found/public/404.html +3 -0
  77. package/examples/not-found/public/index.html +3 -0
  78. package/examples/not-found/tests/requests.json +7 -0
  79. package/examples/not-found/urlcode.yaml +7 -0
  80. package/examples/shared-blocks/README.md +11 -0
  81. package/examples/shared-blocks/example.yaml +17 -0
  82. package/examples/shared-blocks/tests/requests.json +7 -0
  83. package/examples/shared-blocks/urlcode.yaml +37 -0
  84. package/llms-full.txt +364 -49
  85. package/llms.txt +43 -5
  86. package/package.json +15 -22
  87. package/recipes/static-page/README.md +9 -0
  88. package/recipes/static-page/public/index.html +11 -0
  89. package/recipes/static-page/recipe.yaml +21 -0
  90. package/recipes/static-page/tests/requests.json +22 -0
  91. package/recipes/static-page/urlcode.yaml +7 -0
  92. package/recipes/static-plus-api/README.md +6 -0
  93. package/recipes/static-plus-api/urlcode.yaml +4 -0
  94. package/recipes/store-crud/README.md +53 -0
  95. package/recipes/store-crud/recipe.yaml +31 -0
  96. package/recipes/store-crud/tests/requests.json +18 -0
  97. package/recipes/store-crud/urlcode.yaml +18 -0
  98. package/schemas/urlcode.schema.json +125 -60
  99. package/skills/urlcode/SKILL.md +47 -27
  100. package/starters/default/AGENTS.md +43 -43
  101. package/starters/page/README.md +14 -0
  102. package/starters/page/public/index.html +12 -0
  103. package/starters/page/tests/requests.json +17 -0
  104. package/starters/page/urlcode.yaml +6 -0
  105. package/.claude-plugin/marketplace.json +0 -18
  106. package/CONTRIBUTING.md +0 -148
  107. package/ROADMAP.md +0 -70
  108. package/docs/AI-AUTHORING.md +0 -339
  109. package/docs/ASSETS.md +0 -107
  110. package/docs/AUTH-BACKUP.md +0 -32
  111. package/docs/AWS.md +0 -86
  112. package/docs/BEST-PRACTICES.md +0 -276
  113. package/docs/BULK.md +0 -79
  114. package/docs/CAPABILITIES.md +0 -192
  115. package/docs/CAPACITY.md +0 -305
  116. package/docs/CI-FOLLOWUP-2026-09-19.md +0 -97
  117. package/docs/CI-RELEASE-AUDIT-2026-09-19.md +0 -322
  118. package/docs/CI.md +0 -147
  119. package/docs/CLOUDFLARE.md +0 -109
  120. package/docs/CODEBASE-AUDIT-2026-09-20.md +0 -284
  121. package/docs/COMPLIANCE.md +0 -239
  122. package/docs/COMPOSING-A-SITE.md +0 -287
  123. package/docs/CONDITIONS.md +0 -74
  124. package/docs/CONTAINER-PROMOTION.md +0 -74
  125. package/docs/DEPLOYMENT-CHECKS.md +0 -108
  126. package/docs/DEVELOPMENT-PIPELINE.md +0 -304
  127. package/docs/EGRESS.md +0 -125
  128. package/docs/EXTENSIONS.md +0 -403
  129. package/docs/FRAMEWORK.md +0 -217
  130. package/docs/FUNCTION-SECURITY.md +0 -251
  131. package/docs/HTTP.md +0 -129
  132. package/docs/INSTALL.md +0 -128
  133. package/docs/INTERCHANGE.md +0 -134
  134. package/docs/LOAD-TESTING.md +0 -91
  135. package/docs/LOCAL-DEVELOPMENT.md +0 -102
  136. package/docs/MIDDLEWARE-EXAMPLES.md +0 -75
  137. package/docs/MIDDLEWARE.md +0 -102
  138. package/docs/MONITORING.md +0 -115
  139. package/docs/OBSERVABILITY.md +0 -222
  140. package/docs/OPEN-DECISIONS.md +0 -149
  141. package/docs/OPERATIONAL-PROOF.md +0 -41
  142. package/docs/OPERATIONS.md +0 -201
  143. package/docs/ORGANIZATION.md +0 -135
  144. package/docs/PERFORMANCE.md +0 -72
  145. package/docs/PLUGINS.md +0 -271
  146. package/docs/POLICIES.md +0 -211
  147. package/docs/PRERENDER.md +0 -245
  148. package/docs/PROJECT-DIRECTION.md +0 -118
  149. package/docs/PROVIDER-VERIFICATION.md +0 -84
  150. package/docs/READINESS.md +0 -153
  151. package/docs/README.md +0 -93
  152. package/docs/RECIPES.md +0 -99
  153. package/docs/RELEASE-0.4.0-alpha.3.md +0 -50
  154. package/docs/RELEASE-0.4.1.md +0 -73
  155. package/docs/RELEASE-0.4.2.md +0 -30
  156. package/docs/RELEASE-READINESS.md +0 -146
  157. package/docs/RELEASE-SECURITY.md +0 -100
  158. package/docs/RESILIENCE.md +0 -161
  159. package/docs/ROUTING.md +0 -92
  160. package/docs/SANDBOX-REVIEW.md +0 -72
  161. package/docs/SCAFFOLDING.md +0 -70
  162. package/docs/SECURITY-AUDIT.md +0 -164
  163. package/docs/SITE.md +0 -150
  164. package/docs/SPECIFICATION.md +0 -359
  165. package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +0 -288
  166. package/docs/SPIKE-BUSINESS-SUITE.md +0 -1029
  167. package/docs/SPIKE-CORE-LAYERING.md +0 -368
  168. package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +0 -207
  169. package/docs/STANDARDS.md +0 -311
  170. package/docs/STARTERS.md +0 -83
  171. package/docs/STATIC.md +0 -105
  172. package/docs/TOOLING.md +0 -298
  173. package/docs/TUNNELS.md +0 -72
  174. package/docs/TYPESCRIPT-AUTHORING.md +0 -87
  175. package/docs/TYPESCRIPT.md +0 -123
  176. package/docs/VERCEL.md +0 -114
  177. package/docs/VERSION-ALIGNMENT.md +0 -88
  178. package/docs/YAML-GUIDE.md +0 -57
  179. package/docs/YAML-REFERENCE.md +0 -449
  180. package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +0 -68
  181. package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +0 -102
  182. package/docs/archive/2026-09-19/NEXT-PHASE-PLAN.md +0 -108
  183. package/docs/archive/2026-09-19/NEXT-STEPS.md +0 -646
  184. package/docs/archive/2026-09-19/OPEN-DECISIONS.md +0 -277
  185. package/docs/archive/2026-09-19/RELEASE-SECURITY.md +0 -186
  186. package/docs/archive/2026-09-19/ROADMAP.md +0 -387
  187. package/docs/archive/2026-09-19/SPIKE-EXTENSION-MODEL.md +0 -430
  188. package/docs/archive/2026-09-19/SPIKE-EXTENSIONS.md +0 -492
  189. package/docs/archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md +0 -365
  190. package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +0 -778
  191. package/docs/archive/2026-09-19/USABILITY-REVIEW.md +0 -139
  192. package/docs/archive/2026-09-20/OPEN-DECISIONS-COMPLETED.md +0 -116
  193. package/docs/archive/README.md +0 -29
  194. package/docs/policies/agents.md +0 -182
  195. package/docs/policies/cache.md +0 -152
  196. package/docs/policies/compression.md +0 -169
  197. package/docs/policies/contract.md +0 -52
  198. package/docs/policies/hardened.md +0 -56
  199. package/docs/policies/interoperability.md +0 -169
  200. package/docs/policies/operations.md +0 -45
  201. package/docs/policies/security.md +0 -161
  202. package/docs/policies/throttle.md +0 -103
  203. package/docs/yaml/assets.md +0 -36
  204. package/docs/yaml/conditions.md +0 -20
  205. package/docs/yaml/functions.md +0 -168
  206. package/docs/yaml/middleware.md +0 -31
  207. package/docs/yaml/organization.md +0 -74
  208. package/docs/yaml/policies.md +0 -37
  209. package/docs/yaml/redirects.md +0 -64
  210. package/docs/yaml/responses.md +0 -57
  211. package/docs/yaml/site.md +0 -24
  212. package/packaging/claude-plugin/.claude-plugin/plugin.json +0 -19
  213. package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +0 -130
  214. package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +0 -108
@@ -1,164 +0,0 @@
1
- # Security review — 2026-09-18
2
-
3
- Scope: trust-model change (docs/SPIKE-DEFAULT-TRUST-MODEL.md). `function`/
4
- `middleware` routes now run trusted and unsandboxed by default, with
5
- `sandbox: true` as an explicit per-route opt-in to the isolation this document's
6
- earlier entries describe. This is a maintainer-decided policy reversal, not a
7
- finding; it is recorded here because it changes what every earlier entry's
8
- "guest"/"sandbox" language means going forward.
9
-
10
- **What did not change:** the `sandbox: true` execution path — QuickJS/WASM
11
- isolation, module-graph restriction, fresh heap per call, worker deadline —
12
- is byte-for-byte the same as every earlier entry describes; nothing in this
13
- change touched `src/functions.ts`, `src/function-worker.ts` or `src/guest-api.ts`.
14
- Binding grants are unaffected either way: `env`/`secrets` still reach only a
15
- route that explicitly declared them and an operator policy pinned to the
16
- project revision explicitly granted, whether that route is trusted or
17
- sandboxed.
18
-
19
- **What did change, and the resulting residual risk:** a `function`/
20
- `middleware` route with no `sandbox` field (the common case going forward, and
21
- every existing project's routes after an upgrade with no YAML change) now runs
22
- in the host process with full Node access — the isolation earlier entries'
23
- "remaining gaps" language assumed for *all* guest code no longer applies to
24
- it. The residual-risk framing in earlier entries ("before exposing hostile
25
- multi-tenant workloads, obtain independent review of WASM/host boundaries")
26
- is scoped to `sandbox: true` routes specifically; it was never a claim that
27
- covered a route that opts out of the sandbox, and after this change most
28
- routes do exactly that by default. Whether a given project's own function/
29
- middleware code is safe to trust with full host access is now the project's
30
- judgment call, not something this runtime's isolation reviews (past or
31
- future) can speak to. New source review of the dispatch decision itself
32
- (`src/runtime.ts`, `src/trusted-functions.ts`, `src/policy.ts`'s split
33
- grant-hashing) accompanies the change; see the pull request that introduced
34
- `sandbox` for its own description of what was and was not verified.
35
-
36
- # Security review — 2026-09-17
37
-
38
- Scope: follow-up source review of worker/connection replacement, probe admission,
39
- request correlation, operational logging, dependency/release supply chain and the
40
- live-link Node requirement. Regression tests accompany the fixes. Internal review,
41
- not an independent penetration test.
42
-
43
- This is a dated record, not current guidance. The `link` handler, its SQLite
44
- store and the link-store/management findings below were removed from core in
45
- a later change; they describe the runtime as it existed on this date, not the
46
- current one.
47
-
48
- ## Findings fixed in this revision
49
-
50
- | Finding | Impact and evidence | Fix / regression |
51
- |---|---|---|
52
- | Function workers latched off permanently after bounded churn | Availability: replacement stopped after three exits in a minute and was never retried, so eight deadline-exceeded requests — reachable from ordinary request input to any function whose runtime depends on its input — disabled every function route for the life of the process. Reproduced against `serve`, which never reloads: `/fast` and readiness stayed 503 indefinitely | Replacement now backs off (250 ms doubling to a 30-second ceiling) and keeps retrying; a completed invocation clears the backoff. Load is shed while a slot is down, and `function_worker` events record each attempt. Regression drives eight deadlines, then asserts the pool serves and readiness returns to 200 |
53
- | Link-store connections were never replaced | Availability: one operation reaching the five-second deadline, or any abrupt worker exit, terminated the connection with no replacement path, permanently failing that pool while the records themselves were intact on disk | Connections share the same backed-off replacement and emit `link_store_worker` events. Activation still fails closed and is never retried behind the caller. Covered by the existing 22-test live-link suite; the post-activation failure branch has no automated test because the worker could not be crashed deterministically from a test |
54
- | Health probes bypassed admission control | Resource exposure: probes were answered outside the in-flight budget, an unmetered path on a public listener, and report the configuration digest and route count without authentication | Probes keep a separate bounded budget (16 by default) so they stay available under application saturation without being unmetered. Operations documents keeping them internal |
55
- | Request correlation broke at the ingress, and logs could not attribute anything | Operability: `x-request-id` was always regenerated, so traces did not survive a proxy hop, and request records carried no method or route, leaving per-route error rates and abuse (including the exhaustion above) undetectable | Opt-in `--trust-request-id` accepts a single safe upstream value; `--request-log detailed` adds the method and the matched route pattern. Pattern and method come from reviewed configuration, never from request text. Regression asserts a spoofed ID is ignored by default and that path, parameter and query text never reach the log |
56
- | Deployment capacity controls were unreachable from the supported deployment | Availability: workers, deadlines and byte limits existed only in the embedding JS API while the container entrypoint is the CLI, so the supported target was fixed at two function workers with no way to tune | `serve`/`dev` accept `--workers`, `--function-timeout-ms`, `--max-response-bytes`, `--max-body-bytes`, `--max-in-flight` and `--max-in-flight-health`, validated before the listener starts |
57
- | Live-link tests failed rather than skipped on an unpatched Node build | Signal loss: a current Node 22 release bundling SQLite 3.51.2 turned 21 tests red for an environmental reason, hiding real regressions behind expected noise | The suite skips with the detected version named, one CI job asserts the suite actually runs somewhere, `doctor` reports `liveLinks`, and activation names the detected version |
58
- | Release artifacts and dependencies were not gated | Supply chain: advisories were checked by hand on a date, and Actions and the container base image floated on mutable tags | `npm audit --omit=dev` fails CI on runtime advisories, Actions and the base image are pinned by SHA/digest, and Dependabot proposes npm, Actions and image updates weekly |
59
-
60
- Replacement backs off but does not stop. A cause that keeps recurring keeps the
61
- instance shedding load with readiness at 503 rather than recovering silently;
62
- that is an operator signal, not self-healing. Alert on sustained
63
- `function_worker` and `link_store_worker` restart events.
64
-
65
- # Security review — 2026-09-16
66
-
67
- Scope: source review of HTTP serving/management, log handling, filesystem and
68
- configuration loading, sandbox/module/binding boundaries, stored-link pooling,
69
- scaffolding, package/container configuration and current dependency advisories.
70
- Local adversarial regression tests accompany fixes. This is an internal review,
71
- not an independent penetration test or certification. No production systems,
72
- third-party targets or external accounts were attacked.
73
-
74
- ## Findings fixed in this revision
75
-
76
- | Finding | Impact and evidence | Fix / regression |
77
- |---|---|---|
78
- | Asynchronous log sink errors escaped request error handling | Availability: a local Writable reporting an async error terminated the process with an unhandled error event | Shared sink error handling suppresses further writes to a failed sink; synchronous failures also contained. Regression covers both failure modes and listener reuse |
79
- | Management lacked bounded in-flight HTTP admission and socket inactivity enforcement | Resource exposure: connection limits alone did not bound active pipelined work or stalled output; public listener protections were absent here | Default 32 admitted requests through finish/disconnect, 10-second socket inactivity timeout, overload 503 and idempotent shutdown. Regression stalls an authenticated upload, checks overload, waits for disconnect, then verifies recovery |
80
- | Development watcher read entire unrelated JSON/JS/YAML files | Local availability: a repository file outside the validated dependency graph could cause excessive allocations or fail watching solely because its contents were unreadable | Watch fingerprints use file metadata; actual configuration/source loading retains validation. Regression starts dev with an unreadable unrelated JSON file |
81
- | Management had no request-level audit events | Operational visibility: mutations, authentication failures and aborted requests lacked structured records | Redacted events include timestamp, request ID, collection, action, authentication result, status and finish/abort outcome. Tests prove tokens, short codes and destinations are absent |
82
- | Management accepted normalized dot-segment path aliases | Defense-in-depth: URL normalization admitted alternative endpoint spellings that could disagree with upstream path policies; no authorization bypass was demonstrated | Reject raw path normalization before endpoint dispatch; authentication still precedes path handling |
83
-
84
- Management event status 0 means no response headers were sent before disconnect.
85
- An aborted request may have committed a mutation: reconcile record/version before
86
- retrying. These logs are best effort, may be dropped under pressure, identify a configured credential ID (or a legacy shared token), and are not a
87
- tamper-evident journal. Successful store mutations now have separate transactional
88
- audit records; see [management security](archive/2026-09-19/MANAGEMENT-SECURITY.md). A failed sink needs collector/operator recovery;
89
- URLCode cannot report failures reliably through the same broken output stream.
90
-
91
- ## Boundaries checked
92
-
93
- - Guest code stays inside QuickJS/WASM, with fresh invocation state, denied host
94
- APIs, bounded modules/memory/deadlines and no unrestricted fallback. Import
95
- allowlists and external revision-pinned binding grants remain in force.
96
- - Public serving cannot mutate the native link store. Management is a separate
97
- token-protected listener with conditional writes, scoped collection and bounded
98
- bodies. YAML requires explicit live-link opt-in; it cannot grant guest storage.
99
- - SQL uses bound parameters; read/write pools have independent bounded admission,
100
- patched-SQLite checks, read-only serving and commit/version tests.
101
- - Asset/scaffold paths reject traversal and unsafe filesystem references. Static
102
- publication is explicit; sensitive-name filtering is not a secret detector.
103
- - Log output excludes request URLs, bodies, headers, tokens and user exceptions.
104
- Management adds safe operational context without logging stored destinations.
105
- - `npm audit` reported zero known advisories on this date. This does not cover
106
- every Node, SQLite, WASM engine, operating-system or container vulnerability.
107
-
108
- Existing and new automated tests cover these contracts; they do not constitute a
109
- proof that the sandbox engine or complete application is vulnerability-free.
110
-
111
- ## Remaining gaps, prioritized
112
-
113
- **Before exposing hostile multi-tenant workloads:** obtain independent review of
114
- WASM/host boundaries, module loading and resource exhaustion. The
115
- [independent-review package](SANDBOX-REVIEW.md) defines scope and closure evidence.
116
- YAML parsing now has an aggregate source cap and a bounded worker with a hard
117
- wall deadline. Route compilation has a cooperative deadline; process-wide RSS,
118
- individual host operations and overlapping snapshots still require deployment
119
- limits. No anonymous code/config upload service is approved by these changes.
120
-
121
- **Management remains private:** literal loopback binding, external per-credential
122
- collection/action scopes, expiry and hot revocation, plus atomic SQLite mutation
123
- audits are implemented. Legacy shared tokens remain for compatibility. There is
124
- no public user-account system, MFA/SSO, built-in rate limiter, credential issuance
125
- service or external tamper-evident archive. See [management security](archive/2026-09-19/MANAGEMENT-SECURITY.md).
126
-
127
- **Before claiming operational readiness:** execute sustained mixed-workload soak,
128
- backup restoration, disk-full, process-kill, proxy timeout and rollback drills on
129
- the real deployment. Monitor disk/WAL growth, pool failures/rejections, RSS,
130
- readiness, missing logs and restarts. SQLite is single-host; there is no automatic
131
- multi-host failover or server-database adapter. Logging retention/rotation is owned
132
- by the external collector and still needs deployment recipes and verification.
133
-
134
- **Post-0.1 release hardening:** establish a private vulnerability reporting/support
135
- policy and patch response ownership before managed or hostile multi-tenant use.
136
- Release artifacts need immutable image and
137
- dependency identities, upstream vulnerability monitoring and a reviewed update
138
- process. At the audit cutoff, CI actions/base images used mutable version tags. The
139
- repository-governance follow-up pins them and enables dependency maintenance,
140
- secret protection, CodeQL and private reporting; see [governance](../GOVERNANCE.md).
141
- CI now also gates runtime advisories with `npm audit --omit=dev`. A manual main-only
142
- signed candidate/SBOM workflow is now defined; see
143
- [release security](RELEASE-SECURITY.md). A tagged release publishes to npm with provenance. The 0.1.0 release is licensed under
144
- Apache-2.0; the license does not close the independent-review gates.
145
-
146
- **Application responsibility:** HTML/JS assets are active browser content; choose
147
- appropriate CSP, cookie flags, authorization and cache policy. Granted secrets
148
- can intentionally be returned by code receiving them. Filename filters cannot
149
- identify secrets stored under innocent names. Operator directories/volumes must
150
- remain protected from other host processes; filesystem checks do not protect
151
- against a privileged host attacker racing mutations.
152
-
153
- See [release gates](RELEASE-READINESS.md), [function security](FUNCTION-SECURITY.md),
154
- [operations](OPERATIONS.md) and [resilience](RESILIENCE.md). Free-product and
155
- portability boundaries remain unchanged; this audit is not deployment readiness proof.
156
-
157
- Repeatable local/CI drills now cover mixed HTTP load, quiesced backup restoration,
158
- configuration rollback and disposable volume exhaustion/recovery. Real deployment
159
- acceptance remains open; see [operational proof](OPERATIONAL-PROOF.md).
160
-
161
- The hardening CI pass also exposed a failed-store initialization cleanup race on
162
- Windows: rejection could precede worker termination and leave the DB file briefly
163
- locked. Initialization now closes the DB and awaits worker termination before
164
- returning failure. The missing-metadata regression exercises this cleanup path.
package/docs/SITE.md DELETED
@@ -1,150 +0,0 @@
1
- # Site conventions
2
-
3
- The optional top-level `site` block generates the small well-known files a
4
- site is expected to serve. Every key is off unless declared, and each declared
5
- key becomes one ordinary native route (`respond` or `page`) that is merged into
6
- the route table before compilation. Everything downstream is unchanged: the
7
- route appears in `urlcode routes` with `generated: "site.<key>"`, the audit
8
- generates fixtures for it, host policies apply to it and every deployment
9
- target compiles it like a route the project wrote by hand. `site` is accepted
10
- only in the entry `urlcode.yaml`, not in included files.
11
-
12
- ```yaml
13
- version: "1"
14
- site:
15
- robots:
16
- disallow: [ai-crawlers, /admin]
17
- allow: [/admin/public]
18
- sitemap: true
19
- sitemap:
20
- exclude: [/drafts/*]
21
- changefreq: weekly
22
- favicon: public/favicon.svg
23
- securityTxt:
24
- contact: [mailto:security@example.com]
25
- expires: "2027-01-01T00:00:00Z"
26
- policy: [https://example.com/security-policy]
27
- preferredLanguages: [en, fr]
28
- llms: llms.txt
29
- routes:
30
- /: {page: {file: public/index.html}}
31
- ```
32
-
33
- The [cookbook](../examples/cookbook/urlcode.yaml) declares `robots`, `favicon`,
34
- `securityTxt` and `llms` with request fixtures; `sitemap` is exercised by the
35
- unit tests because it needs a public origin (below).
36
-
37
- ## Precedence with declared routes
38
-
39
- A route the project declares at a generated path always wins. The generated
40
- route is dropped and the activation log records
41
- `{"event":"site","key":"robots","path":"/robots.txt","status":"shadowed"}`.
42
- This is how a project keeps a hand-written `robots.txt` while still using
43
- `site.favicon`, or migrates one file at a time.
44
-
45
- ## The public origin
46
-
47
- `robots.txt`'s `Sitemap:` line and every `<loc>` in `sitemap.xml` are absolute
48
- URLs, so the runtime needs to know the origin the site is served from. It
49
- never guesses from a request: a generated file is a fixed response compiled at
50
- activation, and a `Host` header is client-controlled. The origin is the
51
- operator's `--origin https://links.example` flag on `serve`, `dev`,
52
- `validate`, `test`, `routes`, `audit`, `benchmark` and `build`, or the
53
- `origin` option of `startServer`/`createRuntime`/`buildCloudflare`.
54
-
55
- - `site.robots.sitemap: true` without an origin omits the `Sitemap:` line and
56
- logs `{"event":"site","key":"robots","severity":"info",...}` at activation.
57
- - `site.sitemap` without an origin **refuses activation**: a sitemap of relative
58
- URLs is invalid under the protocol, so there is no useful degraded form.
59
-
60
- ## Keys
61
-
62
- ### `robots` → `/robots.txt` (RFC 9309)
63
-
64
- | Field | Meaning |
65
- | --- | --- |
66
- | `disallow` | bundled agent list names (`ai-crawlers`, `crawlers`, `seo`, `monitoring`, the same lists as the [`agents` policy](policies/agents.md)) and/or paths starting with `/` |
67
- | `allow` | the same shapes, emitted as `Allow:` |
68
- | `sitemap` | `true` appends `Sitemap: <origin>/sitemap.xml` when the origin is known |
69
- | `extra` | literal lines appended verbatim (comments, `Crawl-delay`, ...) |
70
-
71
- List names become one group of `User-agent:` lines followed by `Disallow: /`
72
- (or `Allow: /`). Paths go under `User-agent: *`; with no paths that group is
73
- `Allow: /`. A list entry whose name is not usable as a product token (it has
74
- spaces or pattern metacharacters) is skipped and counted in an info log line.
75
- The result is served as `text/plain; charset=utf-8`.
76
-
77
- ```
78
- User-agent: GPTBot
79
- User-agent: ClaudeBot
80
- Disallow: /
81
-
82
- User-agent: *
83
- Disallow: /admin
84
- Allow: /admin/public
85
-
86
- Sitemap: https://links.example/sitemap.xml
87
- ```
88
-
89
- ### `sitemap` → `/sitemap.xml` (sitemaps.org protocol 0.9)
90
-
91
- `true`, or `{ exclude, changefreq, priority }`. The sitemap lists every active
92
- literal GET route that serves HTML: a `page` whose file is `.html`/`.htm` or
93
- whose `contentType` is `text/html`; a `respond` route whose `Content-Type`
94
- response header is `text/html`; and the `.html` files under a `static` mount
95
- (the mount's `index` file is listed as its directory URL). Excluded:
96
- parameterized routes, redirects, functions, downloads and stored links,
97
- disabled or expired routes, `/robots.txt` and `/sitemap.xml`, any route whose
98
- `response.headers` set `X-Robots-Tag` containing `noindex`, and anything an
99
- `exclude` pattern matches (an exact path, or a prefix ending in `/*`).
100
- `lastmod` is the file's modification date for asset routes and omitted
101
- otherwise. URLs are sorted and XML-escaped; the response is
102
- `application/xml; charset=utf-8`.
103
-
104
- More than 50,000 URLs, or a document over the 1 MiB declared-response limit,
105
- refuses activation with a message saying to generate the file at build time
106
- and serve it as a static asset instead; the runtime does not split or index
107
- sitemaps.
108
-
109
- ### `favicon` → `/favicon.ico`
110
-
111
- A project-relative `.ico`, `.svg` or `.png` file, served as a `page` route
112
- with `image/x-icon`, `image/svg+xml` or `image/png` and
113
- `cacheControl: public, max-age=3600` (the closest value in the
114
- [allowed vocabulary](ASSETS.md)). The route has the usual asset semantics:
115
- ETag, Last-Modified, conditional requests and ranges.
116
-
117
- ### `securityTxt` → `/.well-known/security.txt` (RFC 9116)
118
-
119
- | Field | Rule |
120
- | --- | --- |
121
- | `contact` (required) | one or more `mailto:`, `tel:` or `https:` URIs |
122
- | `expires` (required) | UTC ISO timestamp; must be in the future at activation; more than a year away logs a warning (the RFC recommends less than a year) |
123
- | `policy`, `acknowledgments`, `canonical` | `https:` URIs |
124
- | `encryption` | `https:`, `dns:` or `openpgp4fpr:` URIs |
125
- | `preferredLanguages` | language tags, emitted as one comma-separated line |
126
-
127
- Fields are emitted in the RFC's order (Acknowledgments, Canonical, Contact,
128
- Encryption, Expires, Policy, Preferred-Languages), one value per line. The
129
- file is unsigned; add a signed copy as a declared route if you need one. The
130
- `.well-known` segment is an ordinary route segment (only `.` and `..` are
131
- refused).
132
-
133
- ### `llms` → `/llms.txt`
134
-
135
- A project-relative text file served as a `page` route with
136
- `text/plain; charset=utf-8` and the default `no-cache`.
137
-
138
- ## Per-target support
139
-
140
- | Target | `robots`, `sitemap`, `securityTxt` (`respond`) | `favicon`, `llms` (`page`) |
141
- | --- | --- | --- |
142
- | self-hosted, Vercel, AWS | served | served |
143
- | Cloudflare | compiled into the artifact (`build --origin` for absolute URLs) | refused at build time like any `page` route: the target has no asset binding; serve them from the platform's static assets |
144
-
145
- ## Not in this release
146
-
147
- No per-route `noindex` field (use `response.headers: {X-Robots-Tag: noindex}`,
148
- which the sitemap honours), no sitemap index or split files, no `humans.txt`,
149
- no signed `security.txt`, and no project `.json` agent lists in `robots`
150
- (bundled names only).