@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.
- package/.claude/skills/urlcode-authoring/SKILL.md +57 -14
- package/.claude/skills/urlcode-operations/SKILL.md +4 -0
- package/README.md +19 -15
- package/SECURITY.md +5 -3
- package/dist/BUILD-MANIFEST.json +30 -27
- package/dist/agent-context.js +82 -0
- package/dist/agents-guide.js +42 -42
- package/dist/authoring.js +12 -2
- package/dist/body-schema.js +159 -0
- package/dist/build-cloudflare.js +2 -0
- package/dist/capabilities.js +1 -1
- package/dist/cli.js +28 -12
- package/dist/config.js +74 -6
- package/dist/context.js +4 -6
- package/dist/errors.js +3 -1
- package/dist/examples.js +1 -1
- package/dist/extensions.js +60 -2
- package/dist/http-policy.js +19 -4
- package/dist/http-response.js +2 -2
- package/dist/init-with.js +71 -9
- package/dist/mcp.js +15 -2
- package/dist/pattern-guard.js +32 -0
- package/dist/policies/security.js +0 -0
- package/dist/project-tests.js +35 -11
- package/dist/readiness.js +184 -32
- package/dist/recipes.js +1 -1
- package/dist/router.js +17 -0
- package/dist/runtime.js +26 -3
- package/dist/scaffold.js +0 -0
- package/dist/server.js +26 -3
- package/dist/site.js +0 -0
- package/dist/tooling.js +2 -1
- package/dist/types/agent-context.d.ts +44 -0
- package/dist/types/authoring.d.ts +3 -1
- package/dist/types/body-schema.d.ts +58 -0
- package/dist/types/config.d.ts +10 -2
- package/dist/types/context.d.ts +1 -1
- package/dist/types/errors.d.ts +9 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/extensions.d.ts +47 -2
- package/dist/types/http-policy.d.ts +3 -0
- package/dist/types/init-with.d.ts +10 -1
- package/dist/types/pattern-guard.d.ts +10 -0
- package/dist/types/project-tests.d.ts +9 -0
- package/dist/types/readiness.d.ts +68 -0
- package/dist/types/recipes.d.ts +1 -1
- package/dist/types/runtime.d.ts +4 -0
- package/dist/types/server.d.ts +9 -1
- package/dist/types/tooling.d.ts +1 -0
- package/dist/types/types.d.ts +13 -0
- package/dist/types.js +10 -2
- package/dist/typescript-authoring.js +5 -3
- package/dist/verify-deployment.js +16 -10
- package/examples/body-validation/README.md +16 -0
- package/examples/body-validation/example.yaml +17 -0
- package/examples/body-validation/tests/requests.json +15 -0
- package/examples/body-validation/urlcode.yaml +34 -0
- package/examples/coverage-waiver/README.md +8 -0
- package/examples/coverage-waiver/example.yaml +16 -0
- package/examples/coverage-waiver/functions/notes.mjs +2 -0
- package/examples/coverage-waiver/tests/requests.json +3 -0
- package/examples/coverage-waiver/urlcode.yaml +10 -0
- package/examples/data-dir/README.md +39 -0
- package/examples/data-dir/data/welcome.txt +1 -0
- package/examples/data-dir/example.yaml +22 -0
- package/examples/data-dir/functions/note.mjs +18 -0
- package/examples/data-dir/tests/requests.json +6 -0
- package/examples/data-dir/urlcode.yaml +6 -0
- package/examples/lifecycle/README.md +15 -0
- package/examples/lifecycle/example.yaml +19 -0
- package/examples/lifecycle/functions/notes.mjs +29 -0
- package/examples/lifecycle/tests/requests.json +12 -0
- package/examples/lifecycle/urlcode.yaml +29 -0
- package/examples/not-found/README.md +10 -0
- package/examples/not-found/example.yaml +17 -0
- package/examples/not-found/public/404.html +3 -0
- package/examples/not-found/public/index.html +3 -0
- package/examples/not-found/tests/requests.json +7 -0
- package/examples/not-found/urlcode.yaml +7 -0
- package/examples/shared-blocks/README.md +11 -0
- package/examples/shared-blocks/example.yaml +17 -0
- package/examples/shared-blocks/tests/requests.json +7 -0
- package/examples/shared-blocks/urlcode.yaml +37 -0
- package/llms-full.txt +364 -49
- package/llms.txt +43 -5
- package/package.json +15 -22
- package/recipes/static-page/README.md +9 -0
- package/recipes/static-page/public/index.html +11 -0
- package/recipes/static-page/recipe.yaml +21 -0
- package/recipes/static-page/tests/requests.json +22 -0
- package/recipes/static-page/urlcode.yaml +7 -0
- package/recipes/static-plus-api/README.md +6 -0
- package/recipes/static-plus-api/urlcode.yaml +4 -0
- package/recipes/store-crud/README.md +53 -0
- package/recipes/store-crud/recipe.yaml +31 -0
- package/recipes/store-crud/tests/requests.json +18 -0
- package/recipes/store-crud/urlcode.yaml +18 -0
- package/schemas/urlcode.schema.json +125 -60
- package/skills/urlcode/SKILL.md +47 -27
- package/starters/default/AGENTS.md +43 -43
- package/starters/page/README.md +14 -0
- package/starters/page/public/index.html +12 -0
- package/starters/page/tests/requests.json +17 -0
- package/starters/page/urlcode.yaml +6 -0
- package/.claude-plugin/marketplace.json +0 -18
- package/CONTRIBUTING.md +0 -148
- package/ROADMAP.md +0 -70
- package/docs/AI-AUTHORING.md +0 -339
- package/docs/ASSETS.md +0 -107
- package/docs/AUTH-BACKUP.md +0 -32
- package/docs/AWS.md +0 -86
- package/docs/BEST-PRACTICES.md +0 -276
- package/docs/BULK.md +0 -79
- package/docs/CAPABILITIES.md +0 -192
- package/docs/CAPACITY.md +0 -305
- package/docs/CI-FOLLOWUP-2026-09-19.md +0 -97
- package/docs/CI-RELEASE-AUDIT-2026-09-19.md +0 -322
- package/docs/CI.md +0 -147
- package/docs/CLOUDFLARE.md +0 -109
- package/docs/CODEBASE-AUDIT-2026-09-20.md +0 -284
- package/docs/COMPLIANCE.md +0 -239
- package/docs/COMPOSING-A-SITE.md +0 -287
- package/docs/CONDITIONS.md +0 -74
- package/docs/CONTAINER-PROMOTION.md +0 -74
- package/docs/DEPLOYMENT-CHECKS.md +0 -108
- package/docs/DEVELOPMENT-PIPELINE.md +0 -304
- package/docs/EGRESS.md +0 -125
- package/docs/EXTENSIONS.md +0 -403
- package/docs/FRAMEWORK.md +0 -217
- package/docs/FUNCTION-SECURITY.md +0 -251
- package/docs/HTTP.md +0 -129
- package/docs/INSTALL.md +0 -128
- package/docs/INTERCHANGE.md +0 -134
- package/docs/LOAD-TESTING.md +0 -91
- package/docs/LOCAL-DEVELOPMENT.md +0 -102
- package/docs/MIDDLEWARE-EXAMPLES.md +0 -75
- package/docs/MIDDLEWARE.md +0 -102
- package/docs/MONITORING.md +0 -115
- package/docs/OBSERVABILITY.md +0 -222
- package/docs/OPEN-DECISIONS.md +0 -149
- package/docs/OPERATIONAL-PROOF.md +0 -41
- package/docs/OPERATIONS.md +0 -201
- package/docs/ORGANIZATION.md +0 -135
- package/docs/PERFORMANCE.md +0 -72
- package/docs/PLUGINS.md +0 -271
- package/docs/POLICIES.md +0 -211
- package/docs/PRERENDER.md +0 -245
- package/docs/PROJECT-DIRECTION.md +0 -118
- package/docs/PROVIDER-VERIFICATION.md +0 -84
- package/docs/READINESS.md +0 -153
- package/docs/README.md +0 -93
- package/docs/RECIPES.md +0 -99
- package/docs/RELEASE-0.4.0-alpha.3.md +0 -50
- package/docs/RELEASE-0.4.1.md +0 -73
- package/docs/RELEASE-0.4.2.md +0 -30
- package/docs/RELEASE-READINESS.md +0 -146
- package/docs/RELEASE-SECURITY.md +0 -100
- package/docs/RESILIENCE.md +0 -161
- package/docs/ROUTING.md +0 -92
- package/docs/SANDBOX-REVIEW.md +0 -72
- package/docs/SCAFFOLDING.md +0 -70
- package/docs/SECURITY-AUDIT.md +0 -164
- package/docs/SITE.md +0 -150
- package/docs/SPECIFICATION.md +0 -359
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +0 -288
- package/docs/SPIKE-BUSINESS-SUITE.md +0 -1029
- package/docs/SPIKE-CORE-LAYERING.md +0 -368
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +0 -207
- package/docs/STANDARDS.md +0 -311
- package/docs/STARTERS.md +0 -83
- package/docs/STATIC.md +0 -105
- package/docs/TOOLING.md +0 -298
- package/docs/TUNNELS.md +0 -72
- package/docs/TYPESCRIPT-AUTHORING.md +0 -87
- package/docs/TYPESCRIPT.md +0 -123
- package/docs/VERCEL.md +0 -114
- package/docs/VERSION-ALIGNMENT.md +0 -88
- package/docs/YAML-GUIDE.md +0 -57
- package/docs/YAML-REFERENCE.md +0 -449
- package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +0 -68
- package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +0 -102
- package/docs/archive/2026-09-19/NEXT-PHASE-PLAN.md +0 -108
- package/docs/archive/2026-09-19/NEXT-STEPS.md +0 -646
- package/docs/archive/2026-09-19/OPEN-DECISIONS.md +0 -277
- package/docs/archive/2026-09-19/RELEASE-SECURITY.md +0 -186
- package/docs/archive/2026-09-19/ROADMAP.md +0 -387
- package/docs/archive/2026-09-19/SPIKE-EXTENSION-MODEL.md +0 -430
- package/docs/archive/2026-09-19/SPIKE-EXTENSIONS.md +0 -492
- package/docs/archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md +0 -365
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +0 -778
- package/docs/archive/2026-09-19/USABILITY-REVIEW.md +0 -139
- package/docs/archive/2026-09-20/OPEN-DECISIONS-COMPLETED.md +0 -116
- package/docs/archive/README.md +0 -29
- package/docs/policies/agents.md +0 -182
- package/docs/policies/cache.md +0 -152
- package/docs/policies/compression.md +0 -169
- package/docs/policies/contract.md +0 -52
- package/docs/policies/hardened.md +0 -56
- package/docs/policies/interoperability.md +0 -169
- package/docs/policies/operations.md +0 -45
- package/docs/policies/security.md +0 -161
- package/docs/policies/throttle.md +0 -103
- package/docs/yaml/assets.md +0 -36
- package/docs/yaml/conditions.md +0 -20
- package/docs/yaml/functions.md +0 -168
- package/docs/yaml/middleware.md +0 -31
- package/docs/yaml/organization.md +0 -74
- package/docs/yaml/policies.md +0 -37
- package/docs/yaml/redirects.md +0 -64
- package/docs/yaml/responses.md +0 -57
- package/docs/yaml/site.md +0 -24
- package/packaging/claude-plugin/.claude-plugin/plugin.json +0 -19
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +0 -130
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +0 -108
package/docs/SECURITY-AUDIT.md
DELETED
|
@@ -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).
|