@jimhoyd/urlcode 0.4.0-alpha.1 → 0.4.0-alpha.2
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 +24 -8
- package/.claude/skills/urlcode-operations/SKILL.md +10 -16
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +75 -62
- package/ROADMAP.md +61 -16
- package/SECURITY.md +23 -8
- package/dist/BUILD-MANIFEST.json +38 -43
- package/dist/agents-guide.js +18 -18
- package/dist/build-static.js +134 -0
- package/dist/capabilities.js +85 -31
- package/dist/capability-query.js +0 -1
- package/dist/cli.js +23 -31
- package/dist/compliance-rules/baseline.js +2 -10
- package/dist/compliance-rules/privacy.js +5 -16
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance.js +6 -8
- package/dist/config.js +15 -8
- package/dist/context.js +9 -10
- package/dist/examples.js +2 -2
- package/dist/explain-cli.js +3 -3
- package/dist/explain.js +5 -6
- package/dist/extensions.js +61 -2
- package/dist/function-sources.js +34 -2
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +3 -6
- package/dist/manifest.js +5 -7
- package/dist/mcp.js +1 -1
- package/dist/observability.js +1 -21
- package/dist/policies/cache.js +8 -3
- package/dist/policy.js +28 -9
- package/dist/project-tests.js +3 -3
- package/dist/readiness.js +32 -9
- package/dist/router.js +5 -7
- package/dist/runtime.js +77 -58
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/tooling.js +1 -1
- package/dist/trusted-functions.js +210 -0
- package/dist/types/build-static.d.ts +43 -0
- package/dist/types/capabilities.d.ts +14 -5
- package/dist/types/compliance-rules/shared.d.ts +0 -2
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/config.d.ts +2 -1
- package/dist/types/context.d.ts +2 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/extensions.d.ts +55 -0
- package/dist/types/function-sources.d.ts +4 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +3 -6
- package/dist/types/manifest.d.ts +1 -3
- package/dist/types/observability.d.ts +1 -14
- package/dist/types/project-tests.d.ts +1 -2
- package/dist/types/readiness.d.ts +10 -3
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +0 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/server.d.ts +1 -4
- package/dist/types/tooling.d.ts +3 -3
- package/dist/types/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +14 -7
- package/dist/types/verify-deployment.d.ts +2 -2
- package/dist/types.js +17 -4
- package/dist/typescript-authoring.js +55 -17
- package/dist/verify-deployment.js +3 -3
- package/docs/AI-AUTHORING.md +104 -9
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +3 -2
- package/docs/CAPABILITIES.md +29 -16
- package/docs/CAPACITY.md +128 -31
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/COMPLIANCE.md +6 -9
- package/docs/DEPLOYMENT-CHECKS.md +1 -1
- package/docs/EXTENSIONS.md +183 -11
- package/docs/FRAMEWORK.md +35 -19
- package/docs/FUNCTION-SECURITY.md +129 -32
- package/docs/INSTALL.md +0 -5
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/MIDDLEWARE.md +27 -16
- package/docs/MONITORING.md +2 -19
- package/docs/NEXT-PHASE-PLAN.md +12 -4
- package/docs/NEXT-STEPS.md +259 -40
- package/docs/OBSERVABILITY.md +7 -16
- package/docs/OPEN-DECISIONS.md +212 -0
- package/docs/OPERATIONAL-PROOF.md +26 -30
- package/docs/OPERATIONS.md +23 -32
- package/docs/POLICIES.md +15 -4
- package/docs/PRERENDER.md +2 -2
- package/docs/PROJECT-DIRECTION.md +34 -9
- package/docs/README.md +13 -11
- package/docs/RELEASE-READINESS.md +49 -29
- package/docs/RELEASE-SECURITY.md +89 -3
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +8 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +40 -0
- package/docs/SPECIFICATION.md +60 -26
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +8 -0
- package/docs/SPIKE-CORE-LAYERING.md +337 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +2 -2
- package/docs/SPIKE-EXTENSIONS.md +5 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +4 -2
- package/docs/SPIKE-MONOREPO.md +322 -0
- package/docs/STARTERS.md +1 -1
- package/docs/STATIC.md +94 -0
- package/docs/TOOLING.md +13 -9
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +27 -12
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/USABILITY-REVIEW.md +7 -1
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +205 -0
- package/docs/YAML-GUIDE.md +0 -3
- package/docs/YAML-REFERENCE.md +16 -6
- package/docs/policies/cache.md +13 -0
- package/examples/assets/example.yaml +1 -1
- package/examples/aws/example.yaml +1 -1
- package/examples/cloudflare/example.yaml +1 -1
- package/examples/conditions/example.yaml +1 -1
- package/examples/cookbook/example.yaml +1 -1
- package/examples/cookbook/middleware/bucket.mjs +12 -2
- package/examples/cookbook/middleware/locale.mjs +7 -3
- package/examples/egress/example.yaml +1 -1
- package/examples/extensions/example.yaml +1 -1
- package/examples/prerender/README.md +2 -2
- package/examples/prerender/example.yaml +1 -1
- package/examples/provider-conformance/example.yaml +1 -1
- package/examples/vercel/example.yaml +1 -1
- package/llms-full.txt +594 -219
- package/llms.txt +23 -12
- package/package.json +10 -3
- package/packaging/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +24 -8
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +10 -16
- package/recipes/authenticated-json-api/recipe.yaml +1 -1
- package/recipes/contact-form/recipe.yaml +1 -1
- package/recipes/cors-api/recipe.yaml +1 -1
- package/recipes/health-page/recipe.yaml +1 -1
- package/recipes/json-api/recipe.yaml +1 -1
- package/recipes/middleware/middleware/bucket.mjs +12 -2
- package/recipes/middleware/middleware/locale.mjs +7 -3
- package/recipes/middleware/recipe.yaml +1 -1
- package/recipes/protected-download/recipe.yaml +1 -1
- package/recipes/redirect/recipe.yaml +1 -1
- package/recipes/static-plus-api/recipe.yaml +1 -1
- package/recipes/typescript/README.md +2 -1
- package/recipes/typescript/recipe.yaml +1 -1
- package/recipes/webhook-receiver/README.md +5 -1
- package/recipes/webhook-receiver/recipe.yaml +2 -1
- package/recipes/webhook-receiver/urlcode.yaml +7 -0
- package/schemas/recipe.schema.json +4 -3
- package/schemas/urlcode.schema.json +14 -41
- package/skills/urlcode/SKILL.md +29 -8
- package/starters/default/AGENTS.md +18 -18
- package/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -40
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -37
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -8
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -61
- package/docs/MANAGEMENT-SECURITY.md +0 -82
- package/docs/links/cli.md +0 -110
- package/docs/links/limits.md +0 -175
- package/docs/links/management-api.md +0 -80
- package/docs/links/pools.md +0 -75
- package/docs/links/setup.md +0 -135
- package/docs/yaml/links.md +0 -30
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/example.yaml +0 -21
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
package/docs/LOAD-TESTING.md
CHANGED
|
@@ -75,8 +75,8 @@ largest one that makes a number go green.
|
|
|
75
75
|
|
|
76
76
|
## What a passing run does not prove
|
|
77
77
|
|
|
78
|
-
- **GET and HEAD only.** Function routes with request bodies
|
|
79
|
-
|
|
78
|
+
- **GET and HEAD only.** Function routes with request bodies are not exercised.
|
|
79
|
+
`workload` states this in every report.
|
|
80
80
|
- **Redirects are not followed**, so a redirect's destination is never loaded.
|
|
81
81
|
- **One client, one host, no slow peers.** Tail latency under adversarial
|
|
82
82
|
clients, connection churn or packet loss is not measured.
|
|
@@ -87,5 +87,5 @@ largest one that makes a number go green.
|
|
|
87
87
|
runtime and application revisions, host, and command with any figure you keep.
|
|
88
88
|
|
|
89
89
|
`scripts/operational-drills.ts` covers the adjacent ground — mixed
|
|
90
|
-
native/function
|
|
91
|
-
|
|
90
|
+
native/function load, an invalid reload and rollback — as a local proof,
|
|
91
|
+
never a statement about production.
|
package/docs/MIDDLEWARE.md
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Middleware is reusable JavaScript around any route handler. It is optional and
|
|
4
4
|
route-local; plain redirects and assets retain their native fast path when no
|
|
5
|
-
middleware is attached.
|
|
5
|
+
middleware is attached. Middleware runs trusted and unsandboxed by default,
|
|
6
|
+
in-process with full Node access, the same as a `function` route; add
|
|
7
|
+
`sandbox: true` on the route to run the whole chain isolated instead (see
|
|
8
|
+
[trust model and sandbox opt-in](FUNCTION-SECURITY.md)).
|
|
6
9
|
|
|
7
10
|
```yaml
|
|
8
11
|
version: "1"
|
|
@@ -49,37 +52,45 @@ reading one consumes it for downstream code. There is no `clone()` or streaming
|
|
|
49
52
|
API; pass parsed data through `context.state` when needed.
|
|
50
53
|
|
|
51
54
|
Function responses support the existing text/JSON guest API. To transform their
|
|
52
|
-
body, read it and return a new `Response`. Native redirect/respond/
|
|
55
|
+
body, read it and return a new `Response`. Native redirect/respond/page/static/
|
|
53
56
|
download bodies are opaque and cannot be read through `text()` or `json()`.
|
|
54
57
|
Returning the same native response preserves original bytes, including binary
|
|
55
58
|
files, ranges and HEAD lengths. You may add headers, but cannot change its
|
|
56
59
|
original status or existing native headers while preserving that body. To replace
|
|
57
60
|
status, destination or content, return a new `Response` instead. Replacement
|
|
58
|
-
responses follow the normal
|
|
61
|
+
responses follow the normal response size limits, and (on a `sandbox: true`
|
|
62
|
+
route) the guest's text/JSON constraints. To wrap a shared
|
|
59
63
|
template around file content, render it through a function at build time and
|
|
60
64
|
publish the result: see [prerendering](PRERENDER.md).
|
|
61
65
|
|
|
62
66
|
Route selection, enabled/expiry checks, methods and input/body validation run
|
|
63
67
|
before middleware. Their errors do not pass through the chain. A missing file
|
|
64
|
-
inside a selected static mount is a downstream 404 response.
|
|
65
|
-
errors (missing, disabled, expired or unavailable store) precede middleware. YAML
|
|
68
|
+
inside a selected static mount is a downstream 404 response. YAML
|
|
66
69
|
`response.headers` apply last and override matching middleware headers. Runtime
|
|
67
70
|
framing and asset metadata protections still apply.
|
|
68
71
|
|
|
69
|
-
##
|
|
72
|
+
## Trust, isolation and testing
|
|
70
73
|
|
|
71
|
-
The whole chain and handler run
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
The whole chain and handler run as one unit, in one execution mode, chosen by
|
|
75
|
+
the route's `sandbox` field — not a per-middleware-entry choice. By default
|
|
76
|
+
(`sandbox` false/absent) that means trusted, in-process execution with full
|
|
77
|
+
Node access and no fixed worker-pool ceiling. With `sandbox: true` it means
|
|
78
|
+
one fresh QuickJS/WASM guest with one memory budget and one deadline: no
|
|
79
|
+
Node, filesystem, shell, fetch or ambient environment, and modules limited to
|
|
80
|
+
this route's declared dependency graph. Either way, all middleware on a route
|
|
81
|
+
receive that route's approved bindings, so review the whole chain; source
|
|
82
|
+
changes invalidate grants. See [trust model and sandbox opt-in](FUNCTION-SECURITY.md).
|
|
76
83
|
|
|
77
|
-
Invalid responses and repeated `next()` calls fail with 502,
|
|
78
|
-
returns
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
Invalid responses and repeated `next()` calls fail with 502, and the deadline
|
|
85
|
+
returns 504 either way. A `sandbox: true` chain also sheds load with 503 when
|
|
86
|
+
the shared worker pool is exhausted, and cannot extend the deadline or catch
|
|
87
|
+
the outer worker termination; forgotten downstream work is still drained
|
|
88
|
+
within it. A trusted chain has no worker pool to exhaust (see
|
|
89
|
+
[capacity](CAPACITY.md)), but its deadline is a race against the call's own
|
|
90
|
+
promise rather than a forced kill — it cannot preempt code that blocks the
|
|
91
|
+
event loop synchronously.
|
|
81
92
|
|
|
82
93
|
Include explicit request fixtures for middleware-wrapped routes: test success,
|
|
83
94
|
early responses, validation failures and every configured method. Audit will
|
|
84
95
|
report missing coverage instead of assuming native handler behavior. Benchmark
|
|
85
|
-
with middleware enabled to measure its actual
|
|
96
|
+
with middleware enabled to measure its actual overhead, sandboxed or trusted.
|
package/docs/MONITORING.md
CHANGED
|
@@ -19,7 +19,7 @@ analytics from these logs, and adding it would mean logging user data. See
|
|
|
19
19
|
| Endpoint | Meaning | Alert when |
|
|
20
20
|
|---|---|---|
|
|
21
21
|
| `GET /_urlcode/health` | The process is alive and not shutting down. | It fails at all (`UrlcodeDown`). |
|
|
22
|
-
| `GET /_urlcode/ready` | The active snapshot
|
|
22
|
+
| `GET /_urlcode/ready` | The active snapshot and every function worker are available. | It fails for longer than replacement takes (`UrlcodeNotReady`). |
|
|
23
23
|
|
|
24
24
|
Both return `{status, version, routes}`. A third endpoint,
|
|
25
25
|
`GET /_urlcode/metrics`, exists only with `startServer({ metrics: true })` and
|
|
@@ -38,27 +38,10 @@ configuration digest and route count, so keep them internal.
|
|
|
38
38
|
| `reload` | `status` (`ok`/`rejected`); `version` and `routes` on `ok` | A `rejected` reload means the last-good snapshot is still serving and a deploy did not take effect. |
|
|
39
39
|
| `watch` | `status` | Development watcher failure; not used by `serve`. |
|
|
40
40
|
| `function_worker` | `status` (`started`/`restarting`), `slot`; `attempt` and `delayMs` on `restarting` | Sustained `restarting` means a function is failing on real traffic. |
|
|
41
|
-
| `link_store_worker` | `status`, `readOnly`, `attempt`, `delayMs` | The same signal for link-store connections. `status: "restarting"` reports an automatic replacement with its backoff; sustained restarts mean the underlying fault is not recoverable. |
|
|
42
|
-
| `link_observer` | `status` (`failed`/`dropped`/`closed`); `reason` on `failed`; `dropped` on `dropped`; the delivery totals on `closed` | Only when an operator enables `linkEvents`. The link event channel below could not keep up or its collector failed. `dropped` means click records were discarded; like `logs_dropped`, anything built on that channel is incomplete while it fires. |
|
|
43
41
|
| `logs_dropped` | `count` | The logger shed records because the collector fell behind. Every other signal is unreliable while this fires. |
|
|
44
42
|
| `observer` | `status` (`failed`), `name` | An in-process observer threw; the request was unaffected. Written to the log only, never to observers. Sustained failures mean the observer's own sink is broken. |
|
|
45
43
|
| `throttle`, `agents`, `cache` | `route`, `outcome`; `remaining` or `list` | Policy decisions; see [policies](POLICIES.md). `throttle` logs `allowed` only in report mode. |
|
|
46
44
|
| `site` | `key`, `path`, `status` (`generated`/`shadowed`); or `severity` (`info`/`warning`) and `message` | Activation records for [site conventions](SITE.md). `shadowed` means a declared route took the path; an `info`/`warning` line reports an omitted `Sitemap:` line (no `--origin`), skipped list names or a far-future `security.txt` expiry. |
|
|
47
|
-
| `management_request` | `timestamp`, `requestId`, `collection`, `action`, `authenticated`, `principal`, `status`, `outcome`, `durationMs` | Operator activity on the link-management API. `status` 0 means no response headers were sent before the peer disconnected; such a request may still have committed a mutation. |
|
|
48
|
-
|
|
49
|
-
### The link event channel
|
|
50
|
-
|
|
51
|
-
`link_request` is **not** a stdout record. It is delivered to an `observe()`
|
|
52
|
-
function the embedding operator process supplies, after the response is over, so
|
|
53
|
-
it can never change, delay or fail a redirect. It carries `requestId`,
|
|
54
|
-
`collection`, `route`, `method`, `status`, `outcome`
|
|
55
|
-
(`completed`/`aborted`/`missing`/`disabled`/`expired`/`invalid_code`/`invalid_record`/`unavailable`)
|
|
56
|
-
and `durationMs`. The short code is redacted unless `includeCode` is set, because
|
|
57
|
-
a code identifies the link somebody followed.
|
|
58
|
-
|
|
59
|
-
The queue is bounded: under overload it drops events and reports the count
|
|
60
|
-
through `link_observer` rather than growing memory. Alert on those drops if you
|
|
61
|
-
count clicks — a quiet channel and a dropping channel look identical downstream.
|
|
62
45
|
|
|
63
46
|
Startup prints `listening` with the effective `origin`, which is what functions
|
|
64
47
|
and absolute URLs see. Behind a proxy or tunnel this must be your public origin;
|
|
@@ -69,7 +52,7 @@ forwarded headers are deliberately not trusted. See [tunnels](TUNNELS.md).
|
|
|
69
52
|
`startServer({ metrics: true })` serves `GET /_urlcode/metrics` in Prometheus
|
|
70
53
|
text format: requests by status class and by configured route, in-flight
|
|
71
54
|
gauges, shed 503s, reloads, worker restarts and healthy slots, policy
|
|
72
|
-
outcomes,
|
|
55
|
+
outcomes, dropped logs and observer errors, all prefixed
|
|
73
56
|
`urlcode_`. The same numbers are available in process as `app.metrics()`. The
|
|
74
57
|
endpoint shares the probes' admission budget and bind host and is off by
|
|
75
58
|
default; it discloses route patterns and traffic shape, so keep it internal
|
package/docs/NEXT-PHASE-PLAN.md
CHANGED
|
@@ -5,6 +5,13 @@ the capability catalog; the subsequent source work implements the bounded
|
|
|
5
5
|
Phase B–D features below. This describes the source additions after `0.3.0` that ship in
|
|
6
6
|
`0.4.0-alpha.1`, not a claim that provider deployments have been verified.
|
|
7
7
|
|
|
8
|
+
> **Update:** this document describes the `0.4.0-alpha.1` source work as it
|
|
9
|
+
> stood on 2026-09-17, when every `function`/`middleware` route was sandboxed.
|
|
10
|
+
> The default changed in `0.4.0-alpha.2`: those routes now run trusted and
|
|
11
|
+
> unsandboxed in the host process unless the route declares `sandbox: true`,
|
|
12
|
+
> which gives it exactly the QuickJS/WASM execution described below. See
|
|
13
|
+
> [SPIKE-DEFAULT-TRUST-MODEL.md](SPIKE-DEFAULT-TRUST-MODEL.md).
|
|
14
|
+
|
|
8
15
|
## Implementation and evidence
|
|
9
16
|
|
|
10
17
|
| Phase | Implemented source | Evidence and remaining limits |
|
|
@@ -36,10 +43,11 @@ binding resolution and activation and distinguishes implementation support from
|
|
|
36
43
|
actual deployment evidence. Unknown or unsupported targets fail closed.
|
|
37
44
|
|
|
38
45
|
Project YAML describes route behavior. Provider infrastructure and outbound
|
|
39
|
-
origin grants stay in operator configuration.
|
|
40
|
-
QuickJS/WASM guests with no host-code fallback
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
origin grants stay in operator configuration. Through `0.4.0-alpha.1`,
|
|
47
|
+
functions remained untrusted QuickJS/WASM guests with no host-code fallback
|
|
48
|
+
(see the update note above). <!-- trust-model-prose: historical -->
|
|
49
|
+
Existing explicit external bindings and new egress grants remain pinned to the
|
|
50
|
+
exact configuration/source revision. Compilation and conversion do not resolve credentials or manufacture
|
|
43
51
|
grants. File authors publish new projects without overwriting unrelated work.
|
|
44
52
|
|
|
45
53
|
The five policy modules remain the authority for their target-sensitive
|
package/docs/NEXT-STEPS.md
CHANGED
|
@@ -24,14 +24,41 @@ maintain?) and the evidence test (measured repetition, not a feature list).
|
|
|
24
24
|
The order below follows from that. **Prove the thesis before building on
|
|
25
25
|
it.** Phase 0 is the benchmark; if it shows a large saving, the rest is worth
|
|
26
26
|
the work, and if it shows a small one, the abstraction is not doing enough yet
|
|
27
|
-
and the next phases change. Nothing here weakens the security model:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
and the next phases change. Nothing here weakens the security model: a
|
|
28
|
+
`sandbox: true` route's isolation stays exactly as strict, grants stay
|
|
29
|
+
operator-owned regardless of a route's trust setting, agents cannot
|
|
30
|
+
self-authorize, unsupported behavior fails with the route named, and
|
|
31
|
+
inspection tooling never becomes a privilege escalation path.
|
|
32
|
+
|
|
33
|
+
**Status 2026-09-19 (sequence).** Most of Phases 1, 3 and 4 landed before the
|
|
34
|
+
Phase 0 benchmark produced a single model-backed run. The instrument is built
|
|
35
|
+
and tested (`benchmarks/agent/harness.ts`, `benchmarks/agent/count-lines.ts`,
|
|
36
|
+
`benchmarks/agent/adapters/anthropic.ts`), but `benchmarks/agent/runs/` holds
|
|
37
|
+
only `baseline.json`, a stub record, so the application-specific code ratio is
|
|
38
|
+
still unmeasured and the re-prioritization 0.1 describes has never been
|
|
39
|
+
exercised. This is an observation about the order the work happened in, not a
|
|
40
|
+
change of priorities: Phase 0 still owns the evidence, and Phase 5 is still how
|
|
41
|
+
each shipped phase gets measured. Items below are marked from the source at this
|
|
42
|
+
revision.
|
|
31
43
|
|
|
32
44
|
## Phase 0: prove the thesis (M, core `benchmarks/agent/`, before anything else)
|
|
33
45
|
|
|
34
|
-
### 0.1 The agent benchmark
|
|
46
|
+
### 0.1 The agent benchmark — partly done
|
|
47
|
+
|
|
48
|
+
Done 2026-09-19, the instrument only: the runner, the counting rule, the tasks
|
|
49
|
+
and the storage format exist and are tested — `benchmarks/agent/harness.ts`
|
|
50
|
+
(`runArm`, `summarize`, `securityChecklist`, `writeRun`),
|
|
51
|
+
`benchmarks/agent/count-lines.ts` (`classify`, `codeRatio`),
|
|
52
|
+
`benchmarks/agent/adapters.ts` (`selectAdapter`, `stubAdapter`) with
|
|
53
|
+
`benchmarks/agent/adapters/anthropic.ts`, ten task directories under
|
|
54
|
+
`benchmarks/agent/tasks/`, both arm preambles under `benchmarks/agent/prompts/`,
|
|
55
|
+
`npm run benchmark:agent`, and `test/agent-benchmark.test.ts` ("the counting
|
|
56
|
+
rule: functions and declared modules are the idea, everything else is
|
|
57
|
+
plumbing"). The measurement is not done: `benchmarks/agent/runs/` holds only
|
|
58
|
+
`baseline.json`, whose `model` is `stub`, and `benchmarks/agent/README.md`
|
|
59
|
+
states that no number there is evidence until a stored run with a real model
|
|
60
|
+
adapter backs it. Running the tasks in both arms against a real model, storing
|
|
61
|
+
the runs and publishing only what they support remains the work below.
|
|
35
62
|
|
|
36
63
|
Fixes: there is no evidence that URLCode saves agent effort, and the whole
|
|
37
64
|
plan depends on it.
|
|
@@ -61,7 +88,16 @@ plan depends on it.
|
|
|
61
88
|
too small or too hard to discover, and Phases 1, 3 and 4 are re-prioritized
|
|
62
89
|
from what the runs show the agent still had to write.
|
|
63
90
|
|
|
64
|
-
### 0.2 Authoring regression evals (S, once 0.1 exists)
|
|
91
|
+
### 0.2 Authoring regression evals (S, once 0.1 exists) — done
|
|
92
|
+
|
|
93
|
+
Done 2026-09-19: the five prompts are `benchmarks/agent/evals/*.yaml`
|
|
94
|
+
(`add-redirect`, `add-authenticated-endpoint`, `serve-directory`,
|
|
95
|
+
`add-middleware`, `create-webhook-endpoint`), scored against the eight criteria
|
|
96
|
+
by `scoreEval` and `summarizeEvals` in `benchmarks/agent/harness.ts`, gated
|
|
97
|
+
against `benchmarks/agent/runs/baseline.json` by `benchmarks/agent/gate.ts`, and
|
|
98
|
+
run weekly by `.github/workflows/evals.yml`. Caveat: the committed baseline is a
|
|
99
|
+
stub record and the scheduled job skips cleanly when no model key is configured,
|
|
100
|
+
so the recorded pass rate proves the pipeline, not a model's behavior.
|
|
65
101
|
|
|
66
102
|
Prompts for common requests ("add a redirect", "add an authenticated
|
|
67
103
|
endpoint", "serve this directory", "add middleware", "create a webhook
|
|
@@ -80,7 +116,17 @@ read-side tools (`inspectProject`, `validateProject`, `explainRoute`,
|
|
|
80
116
|
Keep all of it. The gap is that an agent still has to read documents to find
|
|
81
117
|
facts the runtime already knows.
|
|
82
118
|
|
|
83
|
-
### 1.1 Application-level `AGENTS.md` from `urlcode init` (S, core)
|
|
119
|
+
### 1.1 Application-level `AGENTS.md` from `urlcode init` (S, core) — done
|
|
120
|
+
|
|
121
|
+
Done 2026-09-19: `renderAgentsGuide` in `src/agents-guide.ts` generates the file
|
|
122
|
+
from the installed capability catalog, `initProject` in `src/authoring.ts`
|
|
123
|
+
writes it, and `initProjectWith` in `src/init-with.ts` calls `initProject`, so
|
|
124
|
+
`init --with` writes it into the project directory too; `renderMcpConfig` writes
|
|
125
|
+
`.mcp.json` beside it. `test/cli.test.ts` asserts the commands, the packaged
|
|
126
|
+
skill path and the MCP tool names the file lists, its length bound, and that the
|
|
127
|
+
committed `starters/default/AGENTS.md` equals what `init` generates from this
|
|
128
|
+
runtime. Caveat: the public `urlcode-template` copy is outside this repository
|
|
129
|
+
and is not checked here; `npm run check:downstream-skills` stays advisory.
|
|
84
130
|
|
|
85
131
|
Fixes: a project made with URLCode is not self-describing to Claude Code,
|
|
86
132
|
Codex or any repository-aware agent. Today's `AGENTS.md` explains how to work
|
|
@@ -97,14 +143,22 @@ on the runtime, not on an application.
|
|
|
97
143
|
- Proof: starter test asserts the file exists and lists the commands; the
|
|
98
144
|
public `urlcode-template` gets the same file.
|
|
99
145
|
|
|
100
|
-
### 1.2 `llms-full.txt` and clean Markdown for the docs site (S, core; S, urlcode-docs)
|
|
146
|
+
### 1.2 `llms-full.txt` and clean Markdown for the docs site (S, core; S, urlcode-docs) — partly done
|
|
147
|
+
|
|
148
|
+
Done 2026-09-19, the core side: `scripts/build-llms-full.ts` generates
|
|
149
|
+
`llms-full.txt` from 15 authoring documents in reading order with a table of
|
|
150
|
+
contents and a token estimate in the file header, `npm run check` runs it with
|
|
151
|
+
`--check`, and `test/llms-full.test.ts` covers determinism, rejection of a stale
|
|
152
|
+
copy and the conservative link rewriting. The docs-site half is not done here:
|
|
153
|
+
serving `/docs/<page>.md` beside `/docs/<page>` belongs to `urlcode-docs` and is
|
|
154
|
+
not verifiable from this repository.
|
|
101
155
|
|
|
102
156
|
Fixes: `llms.txt` must stay a compact index, but an agent that wants complete
|
|
103
157
|
context has to fetch forty files.
|
|
104
158
|
|
|
105
159
|
- Work: `scripts/build-llms-full.ts` concatenates the authoring documents
|
|
106
160
|
(framework, AI authoring, YAML guide, field reference, specification,
|
|
107
|
-
routing, HTTP, middleware, assets,
|
|
161
|
+
routing, HTTP, middleware, assets, policies, extensions) in
|
|
108
162
|
reading order with a table of contents; checked in `npm run check` for
|
|
109
163
|
staleness like the field reference. The docs site serves `/docs/<page>.md`
|
|
110
164
|
beside `/docs/<page>` so agents never parse HTML. Do not adopt `agents.txt`
|
|
@@ -112,7 +166,16 @@ context has to fetch forty files.
|
|
|
112
166
|
- Proof: `npm run check` fails on a stale `llms-full.txt`; token estimate
|
|
113
167
|
recorded in the file header.
|
|
114
168
|
|
|
115
|
-
### 1.3 `urlcode context` with a token budget (M, core)
|
|
169
|
+
### 1.3 `urlcode context` with a token budget (M, core) — done
|
|
170
|
+
|
|
171
|
+
Done 2026-09-19: `urlcode context [--project] [--budget] [--json] [--stats]` in
|
|
172
|
+
`src/cli.ts` over `buildContext`, `renderContext`, `estimateTokens` and
|
|
173
|
+
`documentationTokens` in `src/context.ts`, derived from the compiled project and
|
|
174
|
+
the capability catalog; `--stats` writes the estimate to stderr so stdout stays
|
|
175
|
+
parseable. `test/context.test.ts` covers the cookbook and starter summaries,
|
|
176
|
+
byte-identical output across runs, the fixed budget drop order with the estimate
|
|
177
|
+
never exceeded, the CLI's YAML and JSON forms, and MCP `get_context`
|
|
178
|
+
(`src/mcp.ts`) returning the same data read-only.
|
|
116
179
|
|
|
117
180
|
Fixes: the central gap. An agent needs a handful of facts about this project
|
|
118
181
|
and this runtime and spends tens of thousands of tokens reading documentation
|
|
@@ -136,7 +199,17 @@ to get them.
|
|
|
136
199
|
same project yields byte-identical output twice; budget test that output
|
|
137
200
|
never exceeds the estimate; MCP tool `get_context` returns the same data.
|
|
138
201
|
|
|
139
|
-
### 1.4 Capability and schema fragment queries (M, core)
|
|
202
|
+
### 1.4 Capability and schema fragment queries (M, core) — done
|
|
203
|
+
|
|
204
|
+
Done 2026-09-19: `urlcode capabilities <name>` and `urlcode schema <path>` in
|
|
205
|
+
`src/cli.ts` over `getCapability` in `src/capability-query.ts` and
|
|
206
|
+
`getSchemaFragment`/`schemaPathNames` in `src/schema-query.ts`, both re-exported
|
|
207
|
+
from `src/tooling.ts` and served as MCP `get_capability` and `get_schema`
|
|
208
|
+
(`src/mcp.ts`). `test/capability-query.test.ts` asserts that every catalog name
|
|
209
|
+
resolves with a valid, size-bounded fragment, that every schema path yields a
|
|
210
|
+
valid inline fragment and an unknown path lists the valid names, that entries
|
|
211
|
+
report bundled usage, grants and refusals from existing data, and that the CLI
|
|
212
|
+
fails closed on unknown names.
|
|
140
213
|
|
|
141
214
|
Fixes: `urlcode capabilities` reports target support per handler; an agent
|
|
142
215
|
cannot ask "what does `throttle` accept, where does it run, which recipe
|
|
@@ -152,7 +225,15 @@ shows it" or "give me only the schema for `redirect`".
|
|
|
152
225
|
- Proof: a test that every capability name resolves and every fragment is
|
|
153
226
|
valid JSON Schema; a size test that no fragment exceeds a fixed byte cap.
|
|
154
227
|
|
|
155
|
-
### 1.5 The URLCode agent skill (S, core `skills/urlcode/`)
|
|
228
|
+
### 1.5 The URLCode agent skill (S, core `skills/urlcode/`) — done
|
|
229
|
+
|
|
230
|
+
Done 2026-09-19: `skills/urlcode/SKILL.md` is 104 lines, ships in the package,
|
|
231
|
+
and is named by the generated `AGENTS.md` through `skillPath` in
|
|
232
|
+
`src/agents-guide.ts`; `test/cli.test.ts` asserts the reference and
|
|
233
|
+
`test/release.test.ts` asserts the packaged starter copy. Caveat: the
|
|
234
|
+
with-and-without comparison in the proof line waits on 0.1 — the URLCode arm
|
|
235
|
+
preamble (`benchmarks/agent/prompts/urlcode.md`) assumes the skill, and no model
|
|
236
|
+
run has been stored to compare against.
|
|
156
237
|
|
|
157
238
|
Fixes: agents that support skills have no packaged instruction for URLCode.
|
|
158
239
|
|
|
@@ -170,7 +251,7 @@ Fixes: agents that support skills have no packaged instruction for URLCode.
|
|
|
170
251
|
### 2.1 Publish the three extension packages (decision, S) — done
|
|
171
252
|
|
|
172
253
|
Done 2026-09-18: `@jimhoyd/urlcode-ui`, `-auth` and `-admin` are on npm as
|
|
173
|
-
`0.1.0-alpha.
|
|
254
|
+
`0.1.0-alpha.x` against core `0.4.0-alpha.1`. The alpha caveat stays: source
|
|
174
255
|
complete, independent review, deployment evidence and accessibility
|
|
175
256
|
assessment pending ([issue 58](https://github.com/jimhoyd-com/urlcode/issues/58)).
|
|
176
257
|
|
|
@@ -198,9 +279,22 @@ Fixes: three disagreeing lists of verified peer commits (the CI workflows,
|
|
|
198
279
|
- Work: `peers.json` in auth and admin; the workflows read it; the pack
|
|
199
280
|
script defaults from it; `ACCEPTANCE.md` links to it. 2.1 has shipped, so
|
|
200
281
|
the published versions (`@jimhoyd/urlcode@0.4.0-alpha.1`,
|
|
201
|
-
`@jimhoyd/urlcode-ui@0.1.0-alpha.
|
|
202
|
-
|
|
203
|
-
### 2.3 `urlcode init --with auth,admin,ui` (M, core plus each extension)
|
|
282
|
+
`@jimhoyd/urlcode-ui@0.1.0-alpha.4`) replace the SHAs and the file can go.
|
|
283
|
+
|
|
284
|
+
### 2.3 `urlcode init --with auth,admin,ui` (M, core plus each extension) — done
|
|
285
|
+
|
|
286
|
+
Done 2026-09-19: `--with` is parsed in `src/cli.ts` and implemented by
|
|
287
|
+
`parseWithNames`, `loadScaffold` and `initProjectWith` in `src/init-with.ts`,
|
|
288
|
+
which resolves `@jimhoyd/urlcode-<name>` from the invoking directory, refuses a
|
|
289
|
+
missing package or one without a `scaffold` export before writing anything,
|
|
290
|
+
merges the fragments into the starter through a last include, and writes one
|
|
291
|
+
`host.mjs` (`renderHost`), one `README.md` (`renderReadme`), `.mcp.json` and the
|
|
292
|
+
`AGENTS.md` from 1.1, printing the `inspectExtensionRevision` digest for
|
|
293
|
+
pinning. `test/init-with.test.ts` uses a fake `@jimhoyd/urlcode-<name>` package
|
|
294
|
+
in a temporary `node_modules` and, when companion checkouts are present,
|
|
295
|
+
composes the real auth and admin scaffolds. Caveat: each extension's own
|
|
296
|
+
`scaffold` export and admin's clean-project acceptance live in those
|
|
297
|
+
repositories and are not verified here.
|
|
204
298
|
|
|
205
299
|
Fixes: three initializers with three directory conventions; no single command
|
|
206
300
|
produces the layered project the framework page describes.
|
|
@@ -217,7 +311,20 @@ produces the layered project the framework page describes.
|
|
|
217
311
|
`node_modules`; each extension tests that its `scaffold` output validates
|
|
218
312
|
with core; admin's clean-project acceptance uses the new command.
|
|
219
313
|
|
|
220
|
-
### 2.4 Print extension schemas: `urlcode extensions` (M, core)
|
|
314
|
+
### 2.4 Print extension schemas: `urlcode extensions` (M, core) — partly done
|
|
315
|
+
|
|
316
|
+
Done 2026-09-19, the command and the MCP tool: `urlcode extensions
|
|
317
|
+
[--host-file] [--json]` in `src/cli.ts` over `describeExtensions` in
|
|
318
|
+
`src/tooling.ts` prints each registration's name, version, targets,
|
|
319
|
+
configuration schema, policy schema, mounts, policy routes and revision-pin
|
|
320
|
+
verdict, and without a host file names the declared extensions and says schemas
|
|
321
|
+
need one. The same function is exported from `src/index.ts` and served as MCP
|
|
322
|
+
`get_extensions`, offered only when the operator started the server with a host
|
|
323
|
+
file, which `test/extensions.test.ts` asserts against the
|
|
324
|
+
`examples/extensions` registry. Not done: the fold-in. `urlcode context
|
|
325
|
+
--host-file` reports host extension names and a plugin count rather than their
|
|
326
|
+
schemas (`buildContext` in `src/context.ts`), and `urlcode capabilities auth`
|
|
327
|
+
takes no host file, so registered contracts are not part of either view.
|
|
221
328
|
|
|
222
329
|
Fixes: an agent cannot discover what `extensions.auth.config` accepts without
|
|
223
330
|
reading auth's source; `urlcode mcp` cannot serve it.
|
|
@@ -231,7 +338,21 @@ reading auth's source; `urlcode mcp` cannot serve it.
|
|
|
231
338
|
|
|
232
339
|
## Phase 3: retrieval instead of reading (M each, core)
|
|
233
340
|
|
|
234
|
-
### 3.1 Recipes as the vocabulary of common behavior
|
|
341
|
+
### 3.1 Recipes as the vocabulary of common behavior — done
|
|
342
|
+
|
|
343
|
+
Done 2026-09-19: every bundled recipe carries `recipe.yaml`, and the catalog is
|
|
344
|
+
now ten — `authenticated-json-api`, `contact-form`, `cors-api`, `health-page`,
|
|
345
|
+
`json-api`, `middleware`, `protected-download`, `static-plus-api`, `typescript`
|
|
346
|
+
and `webhook-receiver` — which covers the seven this item names.
|
|
347
|
+
`urlcode recipes search|show|add` runs through `src/ecosystem-cli.ts` over
|
|
348
|
+
`searchRecipes` and `showRecipe` in `src/recipes.ts`, matching id, description,
|
|
349
|
+
tags and capabilities locally with no service, and MCP gained `search_recipes`.
|
|
350
|
+
`npm run check` validates the metadata and requires its derived fields to equal
|
|
351
|
+
the capability preflight (`checkCatalog` and `derivedDifferences` in
|
|
352
|
+
`scripts/check.ts`), and `test/recipes.test.ts` asserts a search hit per recipe
|
|
353
|
+
and that every recipe validates, passes its fixtures and audits with its
|
|
354
|
+
declared route count. Growing the catalog from the Phase 6 repetition log has
|
|
355
|
+
not started; the current ten are the seed list above.
|
|
235
356
|
|
|
236
357
|
Fixes: four bundled recipes with a README each and no metadata; an agent
|
|
237
358
|
cannot search them, and nothing tells it to look before generating.
|
|
@@ -248,14 +369,33 @@ cannot search them, and nothing tells it to look before generating.
|
|
|
248
369
|
- Proof: schema for `recipe.yaml` checked in `npm run check`; a search test
|
|
249
370
|
per recipe; every recipe still validates, tests and audits.
|
|
250
371
|
|
|
251
|
-
### 3.2 Examples become searchable the same way
|
|
372
|
+
### 3.2 Examples become searchable the same way — done
|
|
373
|
+
|
|
374
|
+
Done 2026-09-19: each example carries `example.yaml` in the recipe metadata
|
|
375
|
+
shape, `urlcode examples search <text>` runs through `src/ecosystem-cli.ts` over
|
|
376
|
+
`searchExamples` in `src/examples.ts` and names the smallest runnable match with
|
|
377
|
+
its route, and the cookbook's per-route tags are generated into
|
|
378
|
+
`examples/cookbook/route-index.json` by `scripts/build-cookbook-index.ts`,
|
|
379
|
+
checked by `npm run check`. `scripts/check.ts` holds example metadata to the
|
|
380
|
+
same preflight as recipes, and `test/recipes.test.ts` ("examples carry the same
|
|
381
|
+
metadata shape and search returns the smallest runnable match with its route")
|
|
382
|
+
is the search test.
|
|
252
383
|
|
|
253
384
|
- Work: `examples/*/example.yaml` with the same metadata shape; `urlcode
|
|
254
385
|
examples search <text>` returns the smallest matching runnable example and
|
|
255
386
|
its route. The cookbook's forty routes get per-route tags in one index file.
|
|
256
387
|
- Proof: search test; count audit unchanged.
|
|
257
388
|
|
|
258
|
-
### 3.3 `urlcode explain` from compiled semantics
|
|
389
|
+
### 3.3 `urlcode explain` from compiled semantics — done
|
|
390
|
+
|
|
391
|
+
Done 2026-09-19: `urlcode explain [/route] [--json]` in `src/cli.ts` over
|
|
392
|
+
`runExplainCommand` in `src/explain-cli.ts` and `explainRoute`/`explainProject`
|
|
393
|
+
in `src/explain.ts`, derived from the compiled IR, including extension policy
|
|
394
|
+
requirements when a host file is supplied. `test/explain.test.ts` covers the
|
|
395
|
+
project table and route detail through the CLI, the sandbox boolean, the
|
|
396
|
+
extension-protected route with a host registry, the nearest-route miss that
|
|
397
|
+
never carries binding values, and that explain agrees with the runtime on
|
|
398
|
+
methods and policies for every route.
|
|
259
399
|
|
|
260
400
|
Fixes: `explainRoute` exists in the SDK and MCP; there is no CLI, and the
|
|
261
401
|
output repeats matching rather than effective behavior.
|
|
@@ -268,7 +408,15 @@ output repeats matching rather than effective behavior.
|
|
|
268
408
|
- Proof: snapshot tests on the cookbook; a test that `explain` and the
|
|
269
409
|
runtime agree on methods and policies for every route.
|
|
270
410
|
|
|
271
|
-
### 3.4 A generated semantic manifest
|
|
411
|
+
### 3.4 A generated semantic manifest — done
|
|
412
|
+
|
|
413
|
+
Done 2026-09-19: `urlcode manifest [--json]` shares the `src/explain-cli.ts`
|
|
414
|
+
entry and runs `buildManifest` in `src/manifest.ts`; `build` writes
|
|
415
|
+
`manifest.json` beside the artifact and MCP offers `get_manifest`.
|
|
416
|
+
`test/manifest.test.ts` asserts determinism, that the revision equals the
|
|
417
|
+
extension revision digest, that external requirements and recipe provenance are
|
|
418
|
+
listed by name and never by value, and that the CLI prints the bytes the build
|
|
419
|
+
writes.
|
|
272
420
|
|
|
273
421
|
- Work: `urlcode manifest [--json]` (also written by `build` and offered by
|
|
274
422
|
MCP as `get_manifest`) emits routes, capabilities, recipe provenance,
|
|
@@ -278,7 +426,17 @@ output repeats matching rather than effective behavior.
|
|
|
278
426
|
- Proof: manifest equals `inspectProject` output for the same project;
|
|
279
427
|
digest equals `inspectExtensionRevision`.
|
|
280
428
|
|
|
281
|
-
### 3.5 MCP authoring layer, separately authorized (M, core)
|
|
429
|
+
### 3.5 MCP authoring layer, separately authorized (M, core) — done
|
|
430
|
+
|
|
431
|
+
Done 2026-09-19: `src/mcp-authoring.ts` adds `create_route`, `add_recipe` and
|
|
432
|
+
`scaffold_feature` plus the `run_validate`, `run_test` and `run_audit` runners,
|
|
433
|
+
enabled only by `--allow-authoring` on the operator's command line, which
|
|
434
|
+
`src/cli.ts` refuses for any other command and which no tool argument or
|
|
435
|
+
environment variable can set (`src/mcp.ts`). Every write is validated before it
|
|
436
|
+
lands and returns the verdict. `test/mcp-authoring.test.ts` asserts the tools
|
|
437
|
+
are absent without the flag, that absolute, parent, symlinked, dotenv, git and
|
|
438
|
+
operator paths are refused, and that a create is followed by validation in one
|
|
439
|
+
call.
|
|
282
440
|
|
|
283
441
|
Fixes: MCP is read-only by design; an agent that wants to add a recipe or a
|
|
284
442
|
route still has to write files by hand.
|
|
@@ -297,7 +455,20 @@ route still has to write files by hand.
|
|
|
297
455
|
|
|
298
456
|
## Phase 4: fewer lines for the common case (schema additions, `version: "1"` stays valid)
|
|
299
457
|
|
|
300
|
-
### 4.1 Short form for function routes (M, core)
|
|
458
|
+
### 4.1 Short form for function routes (M, core) — done
|
|
459
|
+
|
|
460
|
+
Done 2026-09-19: `normalizeRoute` in `src/config.ts` expands
|
|
461
|
+
`function: functions/x.mjs` into `{source, args}` with an argument per `{param}`
|
|
462
|
+
and a required bounded path parameter for any the route does not declare itself
|
|
463
|
+
(`SHORT_FORM_PATH_SCHEMA`), and a string `middleware` entry into `{source}`; the
|
|
464
|
+
long form stays the IR. Both shapes are in
|
|
465
|
+
`schemas/urlcode.schema.json` (`$defs.route.properties.function` and
|
|
466
|
+
`.middleware`) and the generated field reference lists them as options.
|
|
467
|
+
`test/config.test.ts` ("function and middleware short forms normalize to the
|
|
468
|
+
long form the long form compiles to") asserts identical output, that a declared
|
|
469
|
+
parameter keeps its schema, and that a bad short-form string is refused with the
|
|
470
|
+
route named; the cookbook uses the short form in
|
|
471
|
+
`examples/cookbook/routes/middleware.yaml`.
|
|
301
472
|
|
|
302
473
|
Fixes: the smallest function route is ten lines.
|
|
303
474
|
|
|
@@ -308,7 +479,21 @@ Fixes: the smallest function route is ten lines.
|
|
|
308
479
|
- Proof: generated reference updated; cookbook gains a short-form route with
|
|
309
480
|
fixtures; a test that short and long forms compile to identical IR.
|
|
310
481
|
|
|
311
|
-
### 4.2 Route-level `auth` as the semantic form (M, core plus auth)
|
|
482
|
+
### 4.2 Route-level `auth` as the semantic form (M, core plus auth) — done
|
|
483
|
+
|
|
484
|
+
Done 2026-09-19: the route-level `auth` key is in the schema
|
|
485
|
+
(`$defs.route.properties.auth` over `$defs.routeAuth` in
|
|
486
|
+
`schemas/urlcode.schema.json`) and expanded by `normalizeRouteAuth` in
|
|
487
|
+
`src/config.ts`, which refuses a route that declares `auth` without an
|
|
488
|
+
`extensions.auth` declaration, alongside `policies.extensions.auth`, or with
|
|
489
|
+
`policies.extensions: false`; `required: false` documents intent and emits
|
|
490
|
+
nothing. The type is documented in `src/types.ts`, and `test/recipes.test.ts`
|
|
491
|
+
("the authenticated recipes use the auth short form and never let credentials
|
|
492
|
+
reach the guest") covers both `auth: true` and a role requirement. The `cache`
|
|
493
|
+
short form this item defers to later shipped with it:
|
|
494
|
+
`$defs.route.properties.cache` and the cache branch of `normalizeRoute`, refused
|
|
495
|
+
alongside `policies.cache`. Caveat: the auth repository's HTTP tests are outside
|
|
496
|
+
this repository and were not run here.
|
|
312
497
|
|
|
313
498
|
Fixes: protecting a route today is `policies: { extensions: { auth: {} } }`,
|
|
314
499
|
which is the mechanism, not the intent. The form an agent should write is
|
|
@@ -365,7 +550,15 @@ whether links become a collection. Decide after review; build nothing first.
|
|
|
365
550
|
`hiddenField`, `postForm`, `withDeadline` in the ui main entry; auth and
|
|
366
551
|
admin drop their copies (`admin-markup.ts`, `admin-deadline.ts`).
|
|
367
552
|
|
|
368
|
-
### 7.2 Auth and admin render through the kit (L)
|
|
553
|
+
### 7.2 Auth and admin render through the kit (L) — partly done
|
|
554
|
+
|
|
555
|
+
Done 2026-09-19, the core prerequisite only: the immutable-cache exception for
|
|
556
|
+
hashed extension assets shipped. `ExtensionImmutableAssets` and
|
|
557
|
+
`validateAssetPrefix` in `src/extensions.ts` bound a declared prefix to literal
|
|
558
|
+
segments under the extension's mounts, and `immutableAssetResponse` is what
|
|
559
|
+
lets such a response carry an asset cache-control instead of `no-store`. The
|
|
560
|
+
rendering work itself is in the auth, admin and ui repositories and is not
|
|
561
|
+
verified from here.
|
|
369
562
|
|
|
370
563
|
Auth exports its catalogue and templates with view models, takes an optional
|
|
371
564
|
`ui` from the host, and renders with `ui.kit.page` when present; admin the
|
|
@@ -388,28 +581,54 @@ walkthrough. Retire the `presentation` option one minor version later.
|
|
|
388
581
|
## Phase 9: hardening left from the audit (core, S each)
|
|
389
582
|
|
|
390
583
|
- Direct tests for the sandbox pool, worker crash recovery and timeout kill
|
|
391
|
-
path (`src/functions.ts`, `src/function-worker.ts`, `src/guest-api.ts`)
|
|
392
|
-
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
584
|
+
path (`src/functions.ts`, `src/function-worker.ts`, `src/guest-api.ts`) —
|
|
585
|
+
done 2026-09-19: `test/sandbox-pool.test.ts` covers load shedding with slot
|
|
586
|
+
reuse, parallel workers with per-slot heaps, the 250 ms-to-30 s respawn
|
|
587
|
+
backoff, the deadline kill with slot replacement, an abrupt worker exit
|
|
588
|
+
failing the in-flight invocation, startup failure and close, and the guest
|
|
589
|
+
`Request`/`Response`/context surface.
|
|
590
|
+
- Re-verify the remaining line-number rows in `STANDARDS.md`; cite symbols —
|
|
591
|
+
done 2026-09-19: `docs/STANDARDS.md` records that every row was re-verified
|
|
592
|
+
at `8d7dd01` and now cites the implementing function or constant rather than
|
|
593
|
+
a line number, names the test that proves it, and says "unverified at
|
|
594
|
+
8d7dd01" where a row could not be re-checked; no line-number citation
|
|
595
|
+
remains in the file.
|
|
596
|
+
- Split the longest reference documents (YAML guide, policies) into task pages
|
|
597
|
+
under 200 lines, so retrieval returns one page — done 2026-09-19:
|
|
598
|
+
`docs/yaml/` holds nine pages (largest `functions.md`, 160 lines) and
|
|
599
|
+
`docs/policies/` nine (largest `agents.md`, 182 lines), with
|
|
600
|
+
`docs/YAML-GUIDE.md` down to 57 lines. Caveat: `docs/POLICIES.md` is still
|
|
601
|
+
203 lines as the index page.
|
|
396
602
|
- A pre-test check in the extension repos that fails fast with the SQLite
|
|
397
|
-
requirement named.
|
|
603
|
+
requirement named. Not verifiable from this repository.
|
|
398
604
|
|
|
399
605
|
## Sequence at a glance
|
|
400
606
|
|
|
607
|
+
What remains, as of 2026-09-19:
|
|
608
|
+
|
|
401
609
|
```
|
|
402
|
-
Phase 0
|
|
403
|
-
|
|
404
|
-
Phase
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
Phase
|
|
408
|
-
|
|
409
|
-
|
|
610
|
+
Phase 0 instrument built and tested; no model-backed run stored, so the
|
|
611
|
+
code-ratio evidence is still missing. Evals (0.2) run weekly.
|
|
612
|
+
Phase 1 done: AGENTS.md from init, llms-full, urlcode context,
|
|
613
|
+
capability/schema queries, the skill
|
|
614
|
+
left: the docs site's /docs/<page>.md (urlcode-docs)
|
|
615
|
+
Phase 2 done: published alphas, init --with, urlcode extensions + get_extensions
|
|
616
|
+
left: peers.json (auth, admin); extension schemas folded into
|
|
617
|
+
urlcode context and capabilities <name>
|
|
618
|
+
Phase 3 done: recipe metadata + search, examples search, explain, manifest,
|
|
619
|
+
MCP authoring behind --allow-authoring
|
|
620
|
+
Phase 4 done: short-form function and middleware routes, route-level auth,
|
|
621
|
+
the cache short form; 4.3 stays a standing rule for new fields
|
|
622
|
+
Phase 5 waits on a Phase 0 run with a real model
|
|
623
|
+
Phase 6 not started: no docs/REPETITION-LOG.md, no docs/SPIKE-COLLECTIONS.md
|
|
624
|
+
Phase 7 extension repos; the core immutable-asset exception 7.2 needs is done
|
|
410
625
|
Phase 8 proof gaps, in parallel, as people and environments allow
|
|
411
|
-
Phase 9
|
|
626
|
+
Phase 9 done: sandbox pool tests, STANDARDS symbol citations, split reference
|
|
627
|
+
pages; left: the extension repos' SQLite pre-test check
|
|
412
628
|
```
|
|
413
629
|
|
|
414
630
|
Phase 0 decides whether the rest is worth doing and in what order. Phases 1
|
|
415
631
|
and 3 are what an agent meets first; the rest makes that cheaper or proves it.
|
|
632
|
+
Because Phases 1, 3 and 4 landed ahead of the first model-backed run, that run
|
|
633
|
+
now measures what shipped rather than choosing it; Phase 5's re-runs are where
|
|
634
|
+
the choosing role returns.
|