@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/ASSETS.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# Pages, static files and downloads
|
|
2
|
-
|
|
3
|
-
Native file handlers are implemented in 0.1.0-alpha.3. They work in the local
|
|
4
|
-
Node runtime and self-hosted process/container. Provider adapters remain planned.
|
|
5
|
-
They do not run user functions or expose filesystem APIs to guest code, trusted
|
|
6
|
-
or sandboxed.
|
|
7
|
-
|
|
8
|
-
```yaml
|
|
9
|
-
version: "1"
|
|
10
|
-
routes:
|
|
11
|
-
/about:
|
|
12
|
-
page:
|
|
13
|
-
file: public/about.html
|
|
14
|
-
/assets/*:
|
|
15
|
-
static:
|
|
16
|
-
directory: public/assets
|
|
17
|
-
index: index.html
|
|
18
|
-
cacheControl: public, max-age=3600
|
|
19
|
-
/guide:
|
|
20
|
-
download:
|
|
21
|
-
file: public/guide.pdf
|
|
22
|
-
filename: getting-started.pdf
|
|
23
|
-
contentType: application/pdf
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Create all files/directories before validation or startup. Paths are relative to
|
|
27
|
-
the project root. `page` sends one file inline; `download` sends one file as an
|
|
28
|
-
attachment; `static` publishes a dedicated directory tree. There is no remote
|
|
29
|
-
fetch/proxy, directory listing, automatic trailing-slash redirect, framework
|
|
30
|
-
server, SPA fallback or runtime template evaluation. Use prebuilt assets;
|
|
31
|
-
[prerendering](PRERENDER.md) is the tested recipe for building them from
|
|
32
|
-
function and middleware routes.
|
|
33
|
-
|
|
34
|
-
## Complete handler options
|
|
35
|
-
|
|
36
|
-
| Handler | Required | Optional |
|
|
37
|
-
|---|---|---|
|
|
38
|
-
| `page` | `file` | `contentType`, `cacheControl` |
|
|
39
|
-
| `download` | `file` | `filename`, `contentType`, `cacheControl` |
|
|
40
|
-
| `static` | `directory` | `index`, `contentType`, `cacheControl` |
|
|
41
|
-
|
|
42
|
-
`index` is opt-in, a plain `.html` basename such as `index.html`, served only
|
|
43
|
-
when the requested path ends in `/`. A mount `/assets/*` matches `/assets/` and
|
|
44
|
-
its descendants, not `/assets`. Missing files return 404. Exact routes precede
|
|
45
|
-
parameterized routes; mounts follow, longest prefix first. No fallback between
|
|
46
|
-
mounts. Asset routes accept only GET/HEAD (both default); normal enabled/expiry
|
|
47
|
-
and declared input validation still apply. Choose exactly one handler per route.
|
|
48
|
-
|
|
49
|
-
MIME detection uses the filename extension through `mime-types`; it does not
|
|
50
|
-
sniff file bytes. Unknown extensions use `application/octet-stream`. An explicit
|
|
51
|
-
`contentType` is a MIME essence such as `text/plain` (no parameters). Known text
|
|
52
|
-
charsets are added automatically. On a static mount an override applies to all
|
|
53
|
-
its files; normally leave it unset for mixed assets. Responses use `nosniff`.
|
|
54
|
-
Download names default to the source basename. Unicode names use a standards-based
|
|
55
|
-
Content-Disposition attachment header with UTF-8 encoding and fallback filename.
|
|
56
|
-
Path separators and control characters in names are rejected.
|
|
57
|
-
|
|
58
|
-
Allowed `cacheControl` values in this release:
|
|
59
|
-
|
|
60
|
-
- `no-cache` (default): clients may store but must revalidate.
|
|
61
|
-
- `no-store`: clients should not store the response.
|
|
62
|
-
- `public, max-age=3600`: one-hour public caching.
|
|
63
|
-
- `public, max-age=31536000, immutable`: only for content-versioned URLs you never overwrite.
|
|
64
|
-
|
|
65
|
-
Strong content/representation ETags and Last-Modified are emitted. If-Match and
|
|
66
|
-
If-Unmodified-Since enforce preconditions (412); If-None-Match and
|
|
67
|
-
If-Modified-Since permit 304. ETag conditions take precedence over date conditions.
|
|
68
|
-
HEAD returns metadata and the full Content-Length with no body. GET supports a
|
|
69
|
-
single byte range, including suffix/open-ended ranges (206); unsatisfiable ranges
|
|
70
|
-
return 416 with `Content-Range: bytes */size`. Multiple, malformed or unsupported
|
|
71
|
-
ranges are ignored and return the full 200 response. If-Range works with an exact
|
|
72
|
-
strong ETag; dates and mismatches return the full representation. Range is ignored
|
|
73
|
-
for HEAD and evaluated after preconditions.
|
|
74
|
-
|
|
75
|
-
## Publishing boundary and resource limits
|
|
76
|
-
|
|
77
|
-
Assets are an explicit publication surface. Review the files before running an
|
|
78
|
-
untrusted project; no filename filter can identify every secret. Keep a dedicated
|
|
79
|
-
public directory. Asset declarations reject absolute paths, traversal, dot/hidden
|
|
80
|
-
segments, symlinks (including internal ones), hardlinked files and nonregular
|
|
81
|
-
files. Static trees skip hidden entries, `node_modules`, `urlcode.yaml/yml`,
|
|
82
|
-
`package.json`, `package-lock.json` and `.pem/.key/.p12/.pfx/.env` files. Explicit
|
|
83
|
-
references to those names fail. Do not put credentials or private data under
|
|
84
|
-
innocent filenames in a public directory. HTML/JavaScript assets are active browser
|
|
85
|
-
content; only publish reviewed content on an origin that you control.
|
|
86
|
-
|
|
87
|
-
Startup validates and snapshots bytes in memory: **16 MiB per file, 64 MiB total
|
|
88
|
-
unique file contents, 10,000 traversed static entries and 20 directory levels**.
|
|
89
|
-
These are implementation resource budgets. This is
|
|
90
|
-
bounded buffered serving, not arbitrary-size streaming. For larger collections
|
|
91
|
-
use an external asset service and redirect, pending provider asset adapters.
|
|
92
|
-
Reload can temporarily hold both old and new snapshots; allow memory headroom.
|
|
93
|
-
|
|
94
|
-
Requests never open asset paths. Files changed after activation stay unchanged
|
|
95
|
-
until a valid reload/restart, preventing request-time path substitution. Keep the
|
|
96
|
-
deployment tree operator-owned and stable during compilation; protection against
|
|
97
|
-
another host process racing directory changes is not a filesystem sandbox.
|
|
98
|
-
`dev` watches declared asset metadata and applies additions, edits and deletions
|
|
99
|
-
through validated reloads. A missing required file or invalid tree keeps the last
|
|
100
|
-
good snapshot. `serve` is fixed until restart. Function grants remain pinned to
|
|
101
|
-
configuration/source, not asset bytes; an asset-only edit does not authorize new
|
|
102
|
-
code or new bindings. Asset changes do update the health version and ETags.
|
|
103
|
-
|
|
104
|
-
The runnable [asset example](../examples/assets/urlcode.yaml) includes page,
|
|
105
|
-
static and download routes with local HTTP assertions. HTTP semantics follow
|
|
106
|
-
[RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html); MIME mappings use
|
|
107
|
-
[mime-types](https://github.com/jshttp/mime-types).
|
package/docs/AUTH-BACKUP.md
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Auth backup and restore platform guarantees
|
|
2
|
-
|
|
3
|
-
`createBackup({database,destination,projectRoot})` and
|
|
4
|
-
`restoreBackup({backup,destination,projectRoot})` use SQLite's online backup API
|
|
5
|
-
in a bounded worker. They include committed WAL pages, validate integrity and
|
|
6
|
-
foreign keys, and publish to a new path without overwriting an existing file.
|
|
7
|
-
Both source and destination must remain outside the served project. See the
|
|
8
|
-
[auth operator commands](../packages/auth/README.md#operations-and-recovery).
|
|
9
|
-
|
|
10
|
-
The completed snapshot is flushed through a writable file handle before it is
|
|
11
|
-
linked into its destination. Windows requires write access for this flush;
|
|
12
|
-
opening the snapshot read-only fails with `EPERM`. File flush errors fail the
|
|
13
|
-
operation rather than being ignored.
|
|
14
|
-
|
|
15
|
-
On POSIX systems the containing directory is also flushed after publication.
|
|
16
|
-
Node's filesystem API does not provide the equivalent directory-handle flush
|
|
17
|
-
used here on Windows, so Windows does not receive that extra directory-entry
|
|
18
|
-
crash-durability guarantee. A successful Windows backup verifies and flushes
|
|
19
|
-
file contents; it is not proof that the new filename survives abrupt power
|
|
20
|
-
loss. Verify the backup exists and perform an isolated restore rehearsal before
|
|
21
|
-
depending on it. CI does not simulate power loss.
|
|
22
|
-
|
|
23
|
-
POSIX directory/file modes are checked where supported. Windows operators must
|
|
24
|
-
restrict the operator data and backup directories with filesystem ACLs; POSIX
|
|
25
|
-
mode bits cannot establish Windows privacy. Keep encryption and CSRF keys and
|
|
26
|
-
reviewed configuration separately backed up. Restore to an isolated new path,
|
|
27
|
-
and review restored sessions and revocation state before reopening traffic.
|
|
28
|
-
|
|
29
|
-
A failed auth service initialization waits for its SQLite worker to terminate
|
|
30
|
-
before rejecting. After a configuration rejection, callers can retry or clean up
|
|
31
|
-
the database without racing that failed opener's file handle. Configuration
|
|
32
|
-
identity checks and their error codes are unchanged.
|
package/docs/AWS.md
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# Deploying to AWS Lambda
|
|
2
|
-
|
|
3
|
-
The AWS adapter runs a URLCode project as a Lambda function behind a **Function
|
|
4
|
-
URL** or an **API Gateway HTTP API**. The same `urlcode.yaml` that runs locally
|
|
5
|
-
or in a container serves the deployment.
|
|
6
|
-
|
|
7
|
-
**This adapter serves native handlers only** — redirects, validated responses,
|
|
8
|
-
pages, static assets and downloads — for the same reasons as
|
|
9
|
-
[the Vercel adapter](VERCEL.md): `function` and `middleware` routes need the
|
|
10
|
-
self-hosted Node lifecycle, and a `sandbox: true` route would pay worker and
|
|
11
|
-
WASM startup on every cold start. Both are refused at activation with the route
|
|
12
|
-
named, never per request, trusted or sandboxed alike.
|
|
13
|
-
|
|
14
|
-
That refusal is a settled position, not a gap awaiting an adapter: per-route
|
|
15
|
-
Lambda compilation was considered and declined
|
|
16
|
-
([the decision](OPEN-DECISIONS.md#accepted-one-node-deployment-per-project),
|
|
17
|
-
[the analysis behind it](archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md)). A project that uses
|
|
18
|
-
`function` or `middleware` deploys instead as one trusted Node process — a
|
|
19
|
-
container or a VM running the project as it runs locally — which supports every
|
|
20
|
-
route type today. That process can run on AWS: ECS, EC2 and App Runner all
|
|
21
|
-
serve it. The decision is about the execution model, not about avoiding AWS.
|
|
22
|
-
|
|
23
|
-
A working project is in [`examples/aws/`](../examples/aws/).
|
|
24
|
-
|
|
25
|
-
## Set it up
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
// handler.mjs
|
|
29
|
-
import { createLambdaHandler } from '@jimhoyd/urlcode/aws';
|
|
30
|
-
|
|
31
|
-
export const handler = createLambdaHandler({ project: process.env.LAMBDA_TASK_ROOT });
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
The deployment package must contain every file the project reads: the entry
|
|
35
|
-
YAML, any `includes`, and every page, download and static directory. They are
|
|
36
|
-
read at activation, so a missing one fails the deployment rather than one route.
|
|
37
|
-
Node 22.13 or newer.
|
|
38
|
-
|
|
39
|
-
## Payload format 2.0 only
|
|
40
|
-
|
|
41
|
-
Function URLs and API Gateway **HTTP APIs** send payload format 2.0, which
|
|
42
|
-
carries `rawPath` and `rawQueryString` — the request as it arrived.
|
|
43
|
-
|
|
44
|
-
A **REST API** sends format 1.0, which supplies the path and query already
|
|
45
|
-
decoded. The original bytes cannot be recovered from them, and this runtime
|
|
46
|
-
rejects ambiguous encoding deliberately: rebuilding a target from decoded parts
|
|
47
|
-
would either re-encode differently than the client sent or quietly accept what
|
|
48
|
-
the runtime refuses. Rather than guess, the adapter refuses a 1.0 event and says
|
|
49
|
-
why. Front the function with an HTTP API, or run the container image with
|
|
50
|
-
`urlcode serve`.
|
|
51
|
-
|
|
52
|
-
## Bindings and origin
|
|
53
|
-
|
|
54
|
-
`URLCODE_POLICY` carries the same grant document the operator policy file holds,
|
|
55
|
-
validated identically including the `projectSha256` pin — see
|
|
56
|
-
[the Vercel guide](VERCEL.md#bindings), which describes the same mechanism.
|
|
57
|
-
Store it in the function's environment, or fetch it from Secrets Manager and set
|
|
58
|
-
it before the handler is created.
|
|
59
|
-
|
|
60
|
-
`URLCODE_PUBLIC_HOST` sets the public hostname for generated URLs. Lambda has no
|
|
61
|
-
platform variable naming your domain, so unlike Vercel there is nothing to infer
|
|
62
|
-
from: set it when a custom domain or an API Gateway stage prefix is in play.
|
|
63
|
-
Forwarded headers stay untrusted.
|
|
64
|
-
|
|
65
|
-
## Limits worth knowing before you deploy
|
|
66
|
-
|
|
67
|
-
| Limit | Consequence |
|
|
68
|
-
|---|---|
|
|
69
|
-
| Lambda response payload is 6 MB | A larger asset cannot be returned. The runtime allows 16 MB per asset, so a project valid self-hosted can exceed what Lambda can send. Keep large files in object storage and redirect to them. |
|
|
70
|
-
| Response bodies are base64-encoded | Guessing whether a body is text is how binary assets get corrupted, so every response is encoded. Base64 inflates by about a third, against that 6 MB ceiling. |
|
|
71
|
-
| Each execution environment activates independently | Parsing, asset snapshotting and route compilation happen per cold start, and the [capacity limits](CAPACITY.md) apply per instance: a 64 MiB snapshot is 64 MiB in every concurrent one. |
|
|
72
|
-
| No reload | A deployment serves the revision it was packaged from. Ship a change by deploying. |
|
|
73
|
-
| No `/_urlcode/health` or `/_urlcode/ready` | Those describe a long-lived process. Use Lambda's own metrics; the [monitoring recipes](MONITORING.md) that parse stdout records need adapting for CloudWatch, though the record fields are the same. |
|
|
74
|
-
|
|
75
|
-
## Verification status
|
|
76
|
-
|
|
77
|
-
The adapter is tested against the self-hosted runtime for identical status, body
|
|
78
|
-
and headers across redirects, parameters, responses, pages, static files and
|
|
79
|
-
misses; for format 1.0 and malformed events being refused; for base64 request
|
|
80
|
-
bodies and route body policy; for cookies arriving and leaving through the
|
|
81
|
-
format 2.0 array; and for the policy pin.
|
|
82
|
-
|
|
83
|
-
**It has not been deployed to AWS.** The tests drive the real handler with real
|
|
84
|
-
payload format 2.0 events, but no invocation on Lambda has happened. Treat
|
|
85
|
-
package contents, cold-start latency, API Gateway's own header handling and the
|
|
86
|
-
6 MB ceiling as unverified until you deploy the example and see it work.
|
package/docs/BEST-PRACTICES.md
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
# Organization and readability
|
|
2
|
-
|
|
3
|
-
These are conventions for URLCode applications, not extra schema requirements.
|
|
4
|
-
Choose the smallest structure that makes a route easy to find, understand and
|
|
5
|
-
test. Preserve an existing project's conventions unless there is a clear reason
|
|
6
|
-
to change them. See [file composition](ORGANIZATION.md) for enforced rules and
|
|
7
|
-
[the YAML guide](YAML-GUIDE.md) for supported features.
|
|
8
|
-
|
|
9
|
-
## Start small, split by responsibility
|
|
10
|
-
|
|
11
|
-
The default starter's two routes do not need a framework or many abstraction
|
|
12
|
-
layers. A small project can keep all definitions in `urlcode.yaml`:
|
|
13
|
-
|
|
14
|
-
```text
|
|
15
|
-
my-links/
|
|
16
|
-
urlcode.yaml
|
|
17
|
-
functions/
|
|
18
|
-
welcome.mjs
|
|
19
|
-
middleware/
|
|
20
|
-
response-headers.mjs
|
|
21
|
-
public/
|
|
22
|
-
guide.txt
|
|
23
|
-
tests/
|
|
24
|
-
requests.json
|
|
25
|
-
README.md
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Create only the folders you use. When navigation or ownership becomes difficult,
|
|
29
|
-
group by feature, audience or campaign, rather than creating one YAML file per
|
|
30
|
-
short link. There is no universal file-size threshold; split when a reviewer can
|
|
31
|
-
no longer follow the changes comfortably. Thousands of redirects usually belong
|
|
32
|
-
in a few meaningful collections, not thousands of include entries.
|
|
33
|
-
|
|
34
|
-
For a growing application, colocating feature-specific code is often clearer:
|
|
35
|
-
|
|
36
|
-
```text
|
|
37
|
-
my-links/
|
|
38
|
-
urlcode.yaml
|
|
39
|
-
features/
|
|
40
|
-
welcome/
|
|
41
|
-
routes.yaml
|
|
42
|
-
welcome.mjs
|
|
43
|
-
greeting.mjs
|
|
44
|
-
campaigns/
|
|
45
|
-
routes.yaml
|
|
46
|
-
middleware/
|
|
47
|
-
response-headers.mjs
|
|
48
|
-
public/
|
|
49
|
-
guide.txt
|
|
50
|
-
tests/
|
|
51
|
-
requests.json
|
|
52
|
-
README.md
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
The root remains a short explicit table of contents:
|
|
56
|
-
|
|
57
|
-
```yaml
|
|
58
|
-
version: "1"
|
|
59
|
-
includes:
|
|
60
|
-
- features/welcome/routes.yaml
|
|
61
|
-
- features/campaigns/routes.yaml
|
|
62
|
-
routes: {}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Each included file has its own `version: "1"` and `routes`. Do not add recursive
|
|
66
|
-
includes, glob patterns or inherited defaults. Folder names never change public
|
|
67
|
-
URLs. Keep the two styles available: folders by file type for small apps, or by
|
|
68
|
-
feature when it improves ownership. Neither requires forking the runtime.
|
|
69
|
-
|
|
70
|
-
## Make a route readable from top to bottom
|
|
71
|
-
|
|
72
|
-
Use two spaces, no tabs, and one consistent key order. A useful order is:
|
|
73
|
-
`description`, lifecycle (`enabled`/`expires`), `methods`, `parameters`,
|
|
74
|
-
`request`, bindings (`env`/`secrets`), `middleware`, the handler, then `response`.
|
|
75
|
-
This is visual organization, not an execution-order declaration.
|
|
76
|
-
|
|
77
|
-
Use block style for nested behavior. Short scalar lists such as `[GET, HEAD]`
|
|
78
|
-
and small leaf schemas such as `{type: string}` can stay inline. Omit ordinary
|
|
79
|
-
defaults unless making them explicit clarifies a decision. Quote timestamps and
|
|
80
|
-
numeric-looking header values. Avoid unrelated reformatting when changing a route.
|
|
81
|
-
|
|
82
|
-
Example `features/welcome/routes.yaml`:
|
|
83
|
-
|
|
84
|
-
```yaml
|
|
85
|
-
version: "1"
|
|
86
|
-
routes:
|
|
87
|
-
/welcome/{name}:
|
|
88
|
-
description: A personalized welcome message with a consistent response header
|
|
89
|
-
parameters:
|
|
90
|
-
- name: name
|
|
91
|
-
in: path
|
|
92
|
-
required: true
|
|
93
|
-
schema:
|
|
94
|
-
type: string
|
|
95
|
-
minLength: 1
|
|
96
|
-
maxLength: 80
|
|
97
|
-
middleware:
|
|
98
|
-
- source: middleware/response-headers.mjs
|
|
99
|
-
function:
|
|
100
|
-
source: features/welcome/welcome.mjs
|
|
101
|
-
args:
|
|
102
|
-
name: {from: path, name: name}
|
|
103
|
-
response:
|
|
104
|
-
headers:
|
|
105
|
-
Cache-Control: no-store
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Example `features/campaigns/routes.yaml`:
|
|
109
|
-
|
|
110
|
-
```yaml
|
|
111
|
-
version: "1"
|
|
112
|
-
routes:
|
|
113
|
-
/guide:
|
|
114
|
-
# Keep this temporary so a campaign destination can change later.
|
|
115
|
-
redirect:
|
|
116
|
-
url: https://example.com/guide
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Use comments for the reason behind a choice, migration notes or a business rule.
|
|
120
|
-
Do not narrate obvious syntax or include secrets, private customer details or
|
|
121
|
-
stale deployment instructions. `description` is useful authoring metadata; do
|
|
122
|
-
not invent `owner`, `tags` or other unsupported YAML fields. Record ownership in
|
|
123
|
-
the README or repository tooling instead.
|
|
124
|
-
|
|
125
|
-
Order routes consistently within each collection, such as alphabetically or by
|
|
126
|
-
business flow. Do not rely on file order for precedence: exact routes win before
|
|
127
|
-
parameter routes, then static mounts. Avoid ambiguous overlaps; see [routing](ROUTING.md).
|
|
128
|
-
|
|
129
|
-
## Keep handlers short and name their job
|
|
130
|
-
|
|
131
|
-
Name files for behavior (`welcome.mjs`, `select-destination.mjs`) rather than
|
|
132
|
-
`utils2.mjs` or `handler-final.mjs`. Name exports clearly even when using a default
|
|
133
|
-
export. Use descriptive variables and early returns for error cases. Separate
|
|
134
|
-
business transformations from Request/Response handling when that improves clarity.
|
|
135
|
-
Do not extract a one-line helper merely to create more files.
|
|
136
|
-
|
|
137
|
-
`features/welcome/welcome.mjs`:
|
|
138
|
-
|
|
139
|
-
```js
|
|
140
|
-
import {formatGreeting} from './greeting.mjs';
|
|
141
|
-
|
|
142
|
-
export default function welcome(request, {args}) {
|
|
143
|
-
return Response.json({message: formatGreeting(args.name)});
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
`features/welcome/greeting.mjs`:
|
|
148
|
-
|
|
149
|
-
```js
|
|
150
|
-
export function formatGreeting(name) {
|
|
151
|
-
return `Hello, ${name}!`;
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
YAML `source` paths are project-root relative. JavaScript imports are relative to
|
|
156
|
-
the importing module. Explicit `.mjs` filenames make that distinction clear.
|
|
157
|
-
Only relative project JavaScript imports are supported; do not introduce npm,
|
|
158
|
-
Node, remote imports or a transpilation requirement accidentally. There is a
|
|
159
|
-
project-wide module/source budget; excessive fragmentation has a real limit.
|
|
160
|
-
|
|
161
|
-
Use validated `args` and `inputs` instead of parsing query strings again. Return
|
|
162
|
-
JSON through `Response.json`; escape user data explicitly when producing HTML.
|
|
163
|
-
For dynamic redirects, map a validated enum to known destinations rather than
|
|
164
|
-
accepting any user-controlled URL. Keep modules free of top-level work other than
|
|
165
|
-
simple definitions: initialization runs during validation and fresh invocations.
|
|
166
|
-
|
|
167
|
-
Prefer pure helpers with explicit inputs and outputs. Module globals are not a
|
|
168
|
-
cache, database, session store or rate limiter: guest state resets per request
|
|
169
|
-
regardless of trust mode. If a route declares `sandbox: true`, review
|
|
170
|
-
[sandbox constraints](FUNCTION-SECURITY.md) before choosing dependencies —
|
|
171
|
-
trusted (default) routes have ordinary Node module access instead.
|
|
172
|
-
|
|
173
|
-
## Middleware should have one clear responsibility
|
|
174
|
-
|
|
175
|
-
`middleware/response-headers.mjs`:
|
|
176
|
-
|
|
177
|
-
```js
|
|
178
|
-
export default async function responseHeaders(request, context, next) {
|
|
179
|
-
const response = await next();
|
|
180
|
-
response.headers.set('x-app', 'my-links');
|
|
181
|
-
return response;
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Use middleware for reusable behavior around a handler, not to conceal the entire
|
|
186
|
-
application flow. Prefer YAML headers for fixed route-specific headers; this
|
|
187
|
-
example demonstrates a shared wrapper, but native YAML avoids any
|
|
188
|
-
function/middleware invocation overhead when no custom code is needed —
|
|
189
|
-
including the extra cost of `sandbox: true` where that is declared. Keep
|
|
190
|
-
middleware order explicit in each route.
|
|
191
|
-
|
|
192
|
-
Always return a Response. Call `await next()` once when continuing, or return
|
|
193
|
-
an early Response when intentionally stopping. Do not launch unawaited work or
|
|
194
|
-
assume background tasks will survive. A body read consumes the request body;
|
|
195
|
-
if downstream code needs parsed data, agree on a documented `context.state` field.
|
|
196
|
-
Use specific field names to avoid collisions among middleware.
|
|
197
|
-
|
|
198
|
-
Catch only errors you can handle meaningfully. Do not turn every failure into a
|
|
199
|
-
200 response or include secrets in errors. Keep native body/status/header
|
|
200
|
-
preservation rules visible in code review. All middleware share the route's
|
|
201
|
-
bindings and execution budget; splitting modules does not create privilege
|
|
202
|
-
separation. See [middleware semantics](MIDDLEWARE.md).
|
|
203
|
-
|
|
204
|
-
## Organize tests around observable behavior
|
|
205
|
-
|
|
206
|
-
Keep runnable HTTP assertions in `tests/requests.json`, currently the single file
|
|
207
|
-
read by the CLI. Group adjacent cases by route: ordinary success, HEAD, boundary
|
|
208
|
-
inputs, invalid input, wrong method and relevant early responses. Add meaningful
|
|
209
|
-
body/header checks instead of relying only on status codes.
|
|
210
|
-
|
|
211
|
-
For the two-route feature layout above:
|
|
212
|
-
|
|
213
|
-
```json
|
|
214
|
-
[
|
|
215
|
-
{"path":"/welcome/Ada","status":200,"expectBody":"{\"message\":\"Hello, Ada!\"}","expectHeaders":{"x-app":"my-links"}},
|
|
216
|
-
{"path":"/welcome/Ada","method":"HEAD","status":200,"expectBody":"","expectHeaders":{"x-app":"my-links"}},
|
|
217
|
-
{"path":"/welcome/Ada","method":"POST","status":405,"expectHeaders":{"allow":"GET, HEAD"}},
|
|
218
|
-
{"path":"/guide","status":302,"expectHeaders":{"location":"https://example.com/guide"}},
|
|
219
|
-
{"path":"/guide","method":"HEAD","status":302,"expectBody":"","expectHeaders":{"location":"https://example.com/guide"}}
|
|
220
|
-
]
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Additional ordinary JavaScript unit tests for pure helpers are your project's
|
|
224
|
-
choice. Unit tests alone do not verify runtime compatibility — including the
|
|
225
|
-
guest API restrictions of a route declaring `sandbox: true` — or HTTP framing:
|
|
226
|
-
always exercise HTTP behavior through URLCode too. Keep large fixture generation explicit and
|
|
227
|
-
deterministic if you add your own tooling; nested test directories and JSON
|
|
228
|
-
fragments are not automatically discovered or merged by URLCode.
|
|
229
|
-
|
|
230
|
-
Assert observable contracts, not incidental timings or internal variable names.
|
|
231
|
-
Avoid checking generated request IDs, current Date values or performance numbers
|
|
232
|
-
as fixed functional outputs. Test cache/range semantics with controlled assets.
|
|
233
|
-
Update expected route counts deliberately when adding or removing a route.
|
|
234
|
-
|
|
235
|
-
## Keep configuration, code, assets and operations separate
|
|
236
|
-
|
|
237
|
-
- Git owns behavior and reviewed code. Keep the runtime as a pinned dependency;
|
|
238
|
-
upgrading it should not regenerate or overwrite application files.
|
|
239
|
-
- Publish only intentionally public files in `public/`. File filters cannot
|
|
240
|
-
recognize every secret. A harmless filename is not proof of public content.
|
|
241
|
-
- Put local secrets in ignored `.env.local`; production values come from the
|
|
242
|
-
operator. Keep operator grants outside the application checkout. Never use
|
|
243
|
-
YAML anchors, shell expansion or generated credentials for convenience.
|
|
244
|
-
- Deployment limits, TLS, DNS, DDoS filters and worker tuning belong to operations,
|
|
245
|
-
not invented route fields. Document them separately from portable behavior.
|
|
246
|
-
- Live short-code records need durable storage core does not have. The
|
|
247
|
-
`urlcode-dynamic-link` extension provided it and has been retired; its
|
|
248
|
-
published `0.1.0-alpha.1` pins core `0.4.0-alpha.1` exactly and so cannot be
|
|
249
|
-
installed beside `0.4.0-alpha.2`. Treat stored short links as unsupported
|
|
250
|
-
until that work lands somewhere else. General session/application storage
|
|
251
|
-
remains future work.
|
|
252
|
-
|
|
253
|
-
## Refactor without changing the public contract
|
|
254
|
-
|
|
255
|
-
Move one feature at a time. Update explicit includes and project-root source/asset
|
|
256
|
-
paths, then check relative JavaScript imports. Keep public route paths, methods,
|
|
257
|
-
headers and bodies stable unless the change is intentional. Avoid mixing URL
|
|
258
|
-
renames, dependency upgrades and folder rearrangement in one review.
|
|
259
|
-
|
|
260
|
-
Run validate, HTTP tests and the expected-count audit before and after moving
|
|
261
|
-
files. Re-review operator grants: code/config changes invalidate the digest even
|
|
262
|
-
when intended behavior is unchanged. A successful dev reload is not a production
|
|
263
|
-
deployment. Record activation/rollback steps in the project README.
|
|
264
|
-
|
|
265
|
-
## A useful project README
|
|
266
|
-
|
|
267
|
-
Document how to install the pinned runtime, start locally, run tests/audit, and
|
|
268
|
-
activate a release. Include a small folder map, the owner of each major feature,
|
|
269
|
-
public route behavior and required external binding names (never values). State
|
|
270
|
-
supported Node/runtime versions and link to matching URLCode docs. Explain any
|
|
271
|
-
middleware ordering or surprising defaults that a new maintainer might miss.
|
|
272
|
-
|
|
273
|
-
For AI-generated changes, require the assistant to follow existing conventions,
|
|
274
|
-
keep diffs focused, add response assertions and report checks actually run. Reject
|
|
275
|
-
invented YAML keys, hidden side effects and unnecessary abstractions. The
|
|
276
|
-
[AI authoring guide](AI-AUTHORING.md) provides a reusable prompt and capability list.
|
package/docs/BULK.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Bulk redirect projects
|
|
2
|
-
|
|
3
|
-
Bulk import converts CSV, JSON or YAML redirect rows into an ordinary Git-owned
|
|
4
|
-
URLCode project. It delegates semantics and row diagnostics to the strict
|
|
5
|
-
[redirect interchange](INTERCHANGE.md) converter. Only literal paths and
|
|
6
|
-
absolute HTTP(S) redirect destinations are accepted; unsupported behavior and
|
|
7
|
-
duplicate paths fail rather than being discarded or overwritten.
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
urlcode bulk-import csv redirects.csv --out ./imported --dry-run
|
|
11
|
-
urlcode bulk-import csv redirects.csv --out ./imported
|
|
12
|
-
urlcode validate --local --project ./imported
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
CSV requires the header `path,url,status`; status can be empty for 302. JSON and
|
|
16
|
-
YAML are arrays of `{path, url, status?}` rows. Input is limited to 32 MiB and
|
|
17
|
-
100,000 routes. This command is for data import, not arbitrary provider config.
|
|
18
|
-
Use explicit provider interchange commands when migrating provider files.
|
|
19
|
-
|
|
20
|
-
The SDK provides
|
|
21
|
-
`importBulkProject(text, format, output, {dryRun, source})`. `format` is `csv`,
|
|
22
|
-
`json` or `yaml`. The report includes `ok`, `routeCount`, source/row diagnostics,
|
|
23
|
-
a SHA-256 fingerprint of the exact input text, and a bounded output-file plan.
|
|
24
|
-
Invalid input returns `ok: false` without writing files. Filesystem/output
|
|
25
|
-
refusals throw. `source` is a caller-supplied provenance label, not a file to read.
|
|
26
|
-
|
|
27
|
-
Routes are sorted by literal path and divided into include files with at most
|
|
28
|
-
1,000 routes each. At 100,000 routes this produces 100 include files. The entry
|
|
29
|
-
`urlcode.yaml` holds the include list and empty `routes`. `provenance.json`
|
|
30
|
-
records the source label, input fingerprint, counts and each shard's first/last
|
|
31
|
-
path. It does not embed the original input or claim exact source line mappings
|
|
32
|
-
for successful output rows; retain the original file in version control if that
|
|
33
|
-
traceability is needed. Invalid row diagnostics preserve their source positions.
|
|
34
|
-
|
|
35
|
-
Dry-run performs conversion and output planning without writing the requested
|
|
36
|
-
destination. Import requires a new output directory under an existing parent;
|
|
37
|
-
there is no implicit merge or overwrite mode. As with recipes, dependencies are
|
|
38
|
-
written first and a rename publishes the completed entry YAML last. Failed
|
|
39
|
-
writes clean up the directory created by that invocation. Source data is never
|
|
40
|
-
interpreted as shell code. The caller must control the output parent while
|
|
41
|
-
publishing.
|
|
42
|
-
|
|
43
|
-
## Local scale evidence
|
|
44
|
-
|
|
45
|
-
Run each dataset in a fresh process, sequentially, without concurrent builds:
|
|
46
|
-
|
|
47
|
-
```sh
|
|
48
|
-
node benchmarks/bulk.ts 1000
|
|
49
|
-
node benchmarks/bulk.ts 10000
|
|
50
|
-
node benchmarks/bulk.ts 100000
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Observed on 2026-09-17 against the final integrated next-phase working tree,
|
|
54
|
-
with the merged TypeScript 6.0.3 dependency lock, Node v26.8.2, macOS arm64,
|
|
55
|
-
Apple M4 Pro and 48 GiB system memory. These measurements include the final
|
|
56
|
-
capability, revision-pin and egress activation paths. Synthetic routes redirect `/rN` to `https://example.com/items/N`.
|
|
57
|
-
Conversion includes input validation, semantic compilation and sharded output
|
|
58
|
-
publication; activation uses the normal `createRuntime` loader and compiler.
|
|
59
|
-
Lookup measures 5,000 `Runtime.handle` requests at concurrency one after 100
|
|
60
|
-
warm-up requests, validating each status and Location. It excludes socket/TLS
|
|
61
|
-
transport. Memory is sampled process RSS/heap after phases, not peak memory or
|
|
62
|
-
an isolated worker measurement.
|
|
63
|
-
|
|
64
|
-
| Routes | Includes | Conversion ms | Activation ms | RSS after activation MiB | Heap MiB | Lookup p95 ms |
|
|
65
|
-
| ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
66
|
-
| 1,000 | 1 | 56 | 139 | 180 | 27 | 0.002292 |
|
|
67
|
-
| 10,000 | 10 | 272 | 373 | 288 | 46 | 0.002916 |
|
|
68
|
-
| 100,000 | 100 | 5,530 | 8,838 | 537 | 214 | 0.003791 |
|
|
69
|
-
|
|
70
|
-
All three sequential fresh-process datasets activated and returned the expected
|
|
71
|
-
redirects. These are single observations, not a repeated-run statistical study;
|
|
72
|
-
background host load can change startup and memory measurements. Unlike the
|
|
73
|
-
previous single-document 100,000-route routing benchmark, the sharded project
|
|
74
|
-
fits the existing configuration worker's 256 MiB heap and 10-second deadline.
|
|
75
|
-
No loader, route-count, compiler deadline or runtime safety limit was increased.
|
|
76
|
-
This local result does not establish cross-platform capacity, provider
|
|
77
|
-
performance, peak-memory bounds, concurrency/soak behavior or production SLOs.
|
|
78
|
-
The benchmark reports failure phase and error if a limit is reached on another
|
|
79
|
-
machine; it does not retry with relaxed limits.
|