@jimhoyd/urlcode 0.4.8 → 0.5.5
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/README.md +18 -18
- package/dist/BUILD-MANIFEST.json +27 -23
- package/dist/agents-guide.js +8 -4
- package/dist/authoring.js +81 -7
- package/dist/build-cloudflare.js +1 -0
- package/dist/build-static.js +1 -0
- package/dist/cli.js +39 -14
- package/dist/config.js +7 -1
- package/dist/context.js +32 -4
- package/dist/ecosystem-cli.js +6 -0
- package/dist/explain-cli.js +1 -1
- package/dist/explain.js +2 -2
- package/dist/extension-artifacts.js +28 -34
- package/dist/extension-bundles.js +62 -0
- package/dist/extension-transport.js +41 -0
- package/dist/extensions.js +4 -0
- package/dist/feature-plan.js +99 -0
- package/dist/functions.js +2 -1
- package/dist/index.js +4 -2
- package/dist/init-with.js +55 -23
- package/dist/interchange.js +1 -1
- package/dist/match.js +23 -5
- package/dist/mcp.js +6 -2
- package/dist/readiness.js +2 -2
- package/dist/review.js +206 -0
- package/dist/router.js +35 -10
- package/dist/runtime.js +1 -0
- package/dist/tooling.js +4 -0
- package/dist/types/agents-guide.d.ts +6 -1
- package/dist/types/authoring.d.ts +3 -1
- package/dist/types/context.d.ts +12 -0
- package/dist/types/explain.d.ts +3 -0
- package/dist/types/extension-artifacts.d.ts +15 -4
- package/dist/types/extension-bundles.d.ts +49 -0
- package/dist/types/extension-transport.d.ts +31 -0
- package/dist/types/extensions.d.ts +4 -0
- package/dist/types/feature-plan.d.ts +67 -0
- package/dist/types/functions.d.ts +4 -0
- package/dist/types/index.d.ts +4 -2
- package/dist/types/init-with.d.ts +6 -1
- package/dist/types/match.d.ts +1 -0
- package/dist/types/review.d.ts +30 -0
- package/dist/types/tooling.d.ts +4 -0
- package/dist/types/types.d.ts +10 -1
- package/dist/types.js +10 -3
- package/docs/AI-AUTHORING.md +466 -0
- package/docs/FUNCTION-SECURITY.md +251 -0
- package/docs/README.md +96 -0
- package/docs/TOOLING.md +422 -0
- package/docs/YAML-REFERENCE.md +473 -0
- package/llms-full.txt +190 -83
- package/llms.txt +73 -128
- package/package.json +15 -4
- package/recipes/redirect/README.md +2 -2
- package/recipes/store-crud/README.md +9 -10
- package/recipes/store-crud/recipe.yaml +1 -1
- package/schemas/urlcode.schema.json +3 -0
- package/starters/default/AGENTS.md +2 -2
package/llms.txt
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
> A portable runtime for programmable URL behavior, and the framework that grows
|
|
5
5
|
> from it: routes in YAML, functions and middleware, then accounts, administration and
|
|
6
6
|
> stored links as operator-installed extensions. Stable project format
|
|
7
|
-
> `version: "1"`. Core is Apache-2.0; this revision is `0.
|
|
7
|
+
> `version: "1"`. Core is Apache-2.0; this revision is `0.5.5`. `function`/`middleware`
|
|
8
8
|
> routes are trusted by default with `sandbox: true` as the per-route opt-in. The
|
|
9
|
-
> auth, admin and
|
|
10
|
-
>
|
|
9
|
+
> auth, admin, ui and store workspace packages are bundle sources. New sites install
|
|
10
|
+
> core from npm and verified executable extensions from an immutable GitHub Release;
|
|
11
|
+
> see package and channel alignment for the supported release pair.
|
|
11
12
|
<!-- urlcode-current-version:end -->
|
|
12
13
|
|
|
13
14
|
Use the schema and docs from the runtime revision you run. Do not assume Node
|
|
@@ -15,132 +16,76 @@ or fetch inside a `sandbox: true` function, regex routes, database access,
|
|
|
15
16
|
global middleware, YAML interpolation, or packages named in YAML. Secrets need external revision-pinned
|
|
16
17
|
grants. Unsupported features fail with the route named; nothing degrades silently.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
[llms-full.txt](llms-full.txt), generated from the documents below (about 50k tokens, estimated).
|
|
19
|
+
## Start here (read only this section for a first attempt)
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`urlcode recipes show redirect` give a runnable starting project.
|
|
21
|
+
1. Run `npx --no --package @jimhoyd/urlcode urlcode context --project DIR` (MCP `get_context`). For redirect-only work run
|
|
22
|
+
`npx --no --package @jimhoyd/urlcode urlcode context --project DIR --task redirects`: supported shapes with exact YAML, gaps
|
|
23
|
+
with their exact validation error, a paste-ready `starter`, and this project's own redirects.
|
|
24
|
+
2. After installing `@jimhoyd/urlcode`, run `npx --no --package @jimhoyd/urlcode urlcode init . --template redirects` (it works in a directory holding only `package.json`, `package-lock.json`, `node_modules` or `.git`, and merges `scripts.start` into your `package.json`): yaml, 404 page, `npm start` honoring `PORT`, fixtures. Otherwise write `urlcode.yaml`, then run `npx --no --package @jimhoyd/urlcode urlcode validate --local --project DIR` and `npx --no --package @jimhoyd/urlcode urlcode test`. `--no` refuses a registry fetch, so it always uses the installed scoped runtime.
|
|
25
|
+
3. Do not read or grep [llms-full.txt](llms-full.txt) (about 60k tokens) for a routine task; it is the
|
|
26
|
+
deliberate fallback when the steps above do not answer the question.
|
|
28
27
|
|
|
29
28
|
| Shape | Supported? | Use |
|
|
30
29
|
|---|---|---|
|
|
31
|
-
| Fixed redirect,
|
|
32
|
-
| Parameterized path (`/users/{id}` to `/profiles/{id}`) | Yes | `{name}`
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
| Host
|
|
39
|
-
|
|
40
|
-
## Declarative-first
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
|
54
|
-
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- [AI authoring contract](docs/AI-AUTHORING.md)
|
|
88
|
-
- [
|
|
89
|
-
- [
|
|
90
|
-
- [
|
|
91
|
-
- [
|
|
92
|
-
- [
|
|
93
|
-
- [Semantics](docs/SPECIFICATION.md): validation, defaults and sandbox API.
|
|
94
|
-
- [Runnable cookbook](examples/cookbook/README.md): 25 routes with HTTP fixtures.
|
|
95
|
-
- [Route matching](docs/ROUTING.md): precedence, non-greedy parameters, updates.
|
|
96
|
-
- [Middleware](docs/MIDDLEWARE.md): next(), state, ordering and native body limits.
|
|
97
|
-
- [Policies](docs/POLICIES.md): optional host-enforced `policies`/`profiles` keys, all off by default: `throttle`, `agents`, `security`, `compression`, `cache`; merge rules and per-target support.
|
|
98
|
-
- [Plugins](docs/PLUGINS.md): host hook API operators pass in code; never named in YAML.
|
|
99
|
-
- [TypeScript](docs/TYPESCRIPT.md): the package ships declarations for every export (`urlcode`, `@jimhoyd/urlcode/plugins`, `@jimhoyd/urlcode/policies`, `@jimhoyd/urlcode/observability`, `@jimhoyd/urlcode/compliance`, `@jimhoyd/urlcode/prerender`, `@jimhoyd/urlcode/sandbox`, `@jimhoyd/urlcode/aws`, `@jimhoyd/urlcode/vercel`, `@jimhoyd/urlcode/cloudflare`); the runtime source is TypeScript, `dist/` is its stripped JavaScript.
|
|
100
|
-
- [HTTP](docs/HTTP.md): methods, request bodies and response headers.
|
|
101
|
-
- [Assets](docs/ASSETS.md): pages, MIME, downloads, cache and ranges.
|
|
102
|
-
- [Site conventions](docs/SITE.md): optional top-level `site` key, all off by default: `robots`, `sitemap`, `favicon`, `securityTxt`, `llms` generate native routes; declared routes win; absolute URLs need `--origin`.
|
|
103
|
-
- [Prerendering](docs/PRERENDER.md): `@jimhoyd/urlcode/prerender` build helper and recipe; render function/middleware routes once into native page routes, no request-time guest code.
|
|
104
|
-
- [Organization](docs/ORGANIZATION.md): entry point and included files.
|
|
105
|
-
|
|
106
|
-
## Start here
|
|
107
|
-
- [The framework](docs/FRAMEWORK.md): four packages, the ladder from redirects to a full app, the composition contract, the rules an agent must follow.
|
|
108
|
-
- [AI authoring contract](docs/AI-AUTHORING.md): workflow, capability matrix, copyable task prompt, checks.
|
|
109
|
-
- [JSON Schema](schemas/urlcode.schema.json) and [field reference](docs/YAML-REFERENCE.md): every accepted field.
|
|
110
|
-
- [YAML guide](docs/YAML-GUIDE.md) and [runnable cookbook](examples/cookbook/README.md): recipes with HTTP fixtures.
|
|
111
|
-
- [Semantics](docs/SPECIFICATION.md): validation, defaults, sandbox API.
|
|
112
|
-
|
|
113
|
-
## Routes and handlers
|
|
114
|
-
- [Routing](docs/ROUTING.md): exact and `{param}` paths, precedence, `/*` only on static and extension mounts.
|
|
115
|
-
- [HTTP](docs/HTTP.md): methods, validated inputs, bodies, response headers, cookies.
|
|
116
|
-
- [Function security](docs/FUNCTION-SECURITY.md): trusted and unsandboxed by default, `sandbox: true` QuickJS/WASM opt-in, Request/Response subset, operator grants.
|
|
117
|
-
- [Middleware](docs/MIDDLEWARE.md) and [examples](docs/MIDDLEWARE-EXAMPLES.md): `next()`, state, ordering; also `urlcode recipes add middleware`.
|
|
118
|
-
- [Assets](docs/ASSETS.md): pages, static, downloads, MIME, ranges. [Prerender](docs/PRERENDER.md): render once, no request-time code.
|
|
119
|
-
- [Conditions](docs/CONDITIONS.md): exact predicates, disjoint redirect/respond cases, no-store.
|
|
120
|
-
- [Egress](docs/EGRESS.md): bounded HTTPS proxy and best-effort signals behind operator grants; self-hosted only.
|
|
121
|
-
- [Policies](docs/POLICIES.md): `throttle`, `agents`, `security`, `compression`, `cache`; all off unless declared. [Site](docs/SITE.md): robots, sitemap, favicon, security.txt, llms.txt.
|
|
122
|
-
- [Organization](docs/ORGANIZATION.md), [best practices](docs/BEST-PRACTICES.md), [scaffolding](docs/SCAFFOLDING.md).
|
|
123
|
-
- [Interchange](docs/INTERCHANGE.md), [bulk import](docs/BULK.md), [recipes](docs/RECIPES.md) (`urlcode recipes search`, `examples search`), [TypeScript guests](docs/TYPESCRIPT-AUTHORING.md).
|
|
124
|
-
|
|
125
|
-
## Extensions (accounts, administration, presentation)
|
|
126
|
-
- [Extensions](docs/EXTENSIONS.md): `extensions.<name>` blocks, mounts, policies, operator registration, the shared trusted hook primitive and its machine-readable hook contracts. UI/auth/admin project hooks run trusted in-process; contract v1 rejects `sandbox: true`.
|
|
127
|
-
- [Signed declarative artifacts](docs/EXTENSIONS.md#signed-declarative-artifacts): project-pinned, attested JSON/Markdown data for offline tooling. MCP `get_extension_artifacts` verifies/inventories a committed lock and `get_extension_artifact` reads one bounded member; neither installs or activates an npm extension.
|
|
128
|
-
- [Composing a site](docs/COMPOSING-A-SITE.md): what `urlcode init site --with ui,auth,admin` wires, which `--with` combinations are supported, the presentation override paths under `ui/`, and per-package lifecycle hook input, verdict, timing and failure semantics. Separates declarative configuration, project functions and the TypeScript a new extension needs.
|
|
129
|
-
- [urlcode-auth](packages/auth): npm: @jimhoyd/urlcode-auth; accounts, sessions, MFA, roles, account page; its own llms.txt. Lives in this repository as a workspace package.
|
|
130
|
-
- [urlcode-admin](packages/admin): npm: @jimhoyd/urlcode-admin; users, sessions, roles, audit, cases; its own llms.txt. Lives in this repository as a workspace package.
|
|
131
|
-
- [urlcode-ui](packages/ui): npm: @jimhoyd/urlcode-ui; escaped templates, shadcn/ui partials, themes, translations; its own llms.txt. Lives in this repository as a workspace package, not in a separate repository.
|
|
132
|
-
- urlcode-middleware (retired): per-route middleware briefly lived here as an extension-seam alternative; the package was unpublished at 0.1.0-alpha.2 and its repository deleted. This is not a gap — per-route middleware is native to core via the `middleware:` array (docs/MIDDLEWARE.md); use that.
|
|
133
|
-
- urlcode-dynamic-link (retired): stored short links briefly lived here as a mount-based extension; the package was unpublished and its repository deleted. Core has no native `link` handler and no supported extension provides stored links — report them as a gap.
|
|
134
|
-
- [Plugins](docs/PLUGINS.md): host hook API in operator code, never named in YAML.
|
|
135
|
-
|
|
136
|
-
## Tooling and API
|
|
137
|
-
- [Tooling SDK and MCP](docs/TOOLING.md): `urlcode mcp`, read-only inspection, validation, conversion previews.
|
|
138
|
-
- [TypeScript](docs/TYPESCRIPT.md): declarations for `@jimhoyd/urlcode` and its `/plugins`, `/policies`, `/observability`, `/compliance`, `/prerender`, `/extensions`, `/sandbox`, `/aws`, `/vercel`, `/cloudflare` entries.
|
|
139
|
-
- [Capabilities](docs/CAPABILITIES.md): per-target support; `urlcode capabilities --target NAME`.
|
|
140
|
-
|
|
141
|
-
## Operations
|
|
142
|
-
- [Operations](docs/OPERATIONS.md), [install](docs/INSTALL.md), [deployment checks](docs/DEPLOYMENT-CHECKS.md), [CI action](docs/CI.md).
|
|
143
|
-
- [Readiness](docs/READINESS.md), [capacity](docs/CAPACITY.md), [resilience](docs/RESILIENCE.md), [observability](docs/OBSERVABILITY.md).
|
|
144
|
-
- [Vercel](docs/VERCEL.md), [AWS](docs/AWS.md), [Cloudflare](docs/CLOUDFLARE.md): adapters with local conformance tests; no provider deployment verified yet.
|
|
145
|
-
- [Static hosting](docs/STATIC.md): `urlcode build --target static` compiles redirects/pages/static/downloads to S3 + CloudFront objects and redirect metadata; no server, so function/middleware/extension/proxy/signals/conditions/parameters/bindings/policies are all refused; GitHub Pages is explicitly out of scope.
|
|
146
|
-
- [Release readiness](docs/RELEASE-READINESS.md), [roadmap](ROADMAP.md): what is proven, what is planned.
|
|
30
|
+
| Fixed redirect, 301/302/303/307/308 (302 default) | Yes | `redirect: {url, status}` |
|
|
31
|
+
| Parameterized path (`/users/{id}` to `/profiles/{id}`) | Yes | `{name}` in `redirect.url`, naming a declared path parameter |
|
|
32
|
+
| Root-relative destination (`/users/{id}` to `/profiles/{id}`) | Yes | `redirect.url: /profiles/{id}`: one leading slash, path only |
|
|
33
|
+
| Wildcard suffix (`/legacy/**` to `/modern/{**}`, any depth) | Yes | terminal `/**` key with a literal prefix; `{**}` is the remaining segments (redirect only; not static or Cloudflare) |
|
|
34
|
+
| Query-string preservation | Yes, opt-in | `redirect.query.pass` / `query.map` |
|
|
35
|
+
| Method-preserving redirect | Yes | `methods` plus `status: 307` or `308` |
|
|
36
|
+
| 404 for unmatched paths | Yes | `site.notFound` (project-relative `.html`) |
|
|
37
|
+
| Host or scheme chosen from the request | No | destination is a literal absolute `https://` URL or a root-relative path; report the gap |
|
|
38
|
+
|
|
39
|
+
## Declarative-first
|
|
40
|
+
|
|
41
|
+
Use the highest-level declarative feature before writing a function or middleware. Custom code
|
|
42
|
+
only when the framework cannot express the requirement; then report the gap. Never invent fields
|
|
43
|
+
or bypass target limits or operator grants ([design principle](https://github.com/jimhoyd-com/urlcode/blob/main/docs/PROJECT-DIRECTION.md#design-principle-declarative-first)).
|
|
44
|
+
|
|
45
|
+
| I need | Use |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Security headers | `policies.security` ([security](https://github.com/jimhoyd-com/urlcode/blob/main/docs/policies/security.md)) |
|
|
48
|
+
| Cache headers / cache strategy | `cacheControl` / `policies.cache` ([assets](https://github.com/jimhoyd-com/urlcode/blob/main/docs/yaml/assets.md), [cache](https://github.com/jimhoyd-com/urlcode/blob/main/docs/policies/cache.md)) |
|
|
49
|
+
| Body size, content type, JSON check | `request.body` ([HTTP](https://github.com/jimhoyd-com/urlcode/blob/main/docs/HTTP.md)) |
|
|
50
|
+
| Restrict HTTP methods | `methods` (default GET/HEAD; 405 with `Allow`) |
|
|
51
|
+
| Rate limiting, bot/AI-crawler blocking, compression | `policies.throttle`, `policies.agents`, `policies.compression` ([policies](https://github.com/jimhoyd-com/urlcode/blob/main/docs/POLICIES.md)) |
|
|
52
|
+
| Fixed JSON/text/headers | `respond` and `response.headers` |
|
|
53
|
+
| robots.txt, sitemap, favicon, security.txt | top-level `site` ([site](https://github.com/jimhoyd-com/urlcode/blob/main/docs/SITE.md)) |
|
|
54
|
+
| Sign-in, roles, protected routes | `extensions.auth`, then `auth: true` ([extensions](https://github.com/jimhoyd-com/urlcode/blob/main/docs/EXTENSIONS.md)) |
|
|
55
|
+
| Persistence | operator-installed store extension, recipe `store-crud`; a database, filtering and per-record ownership beyond it are gaps |
|
|
56
|
+
| Stored short links (create, redirect, click count) | operator-installed store extension's `shortLinks` capability: a collection `key`, an HTTP(S) `destination` field, one `increments` counter, and a public `/go`-style redirect mount; no function needed (`urlcode docs search "shortLinks"`, MCP `search_docs`) |
|
|
57
|
+
|
|
58
|
+
When only code can do it, one function serves one or more routes:
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
/hello/{name}:
|
|
62
|
+
function: functions/hello.mjs # binds args.name; context.route.pattern is "/hello/{name}"
|
|
63
|
+
```
|
|
64
|
+
```js
|
|
65
|
+
export default (request, { args, route }) => Response.json({ hello: args.name });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Function handler shape: a module whose `export default` is `(request, { args, env, route })` and returns a
|
|
69
|
+
`Response` (or a promise of one). `args` holds the route's declared path inputs; the string form
|
|
70
|
+
`function: functions/hello.mjs` and the long form `function: {source: ...}` both bind every declared path input
|
|
71
|
+
(write `args: {}` to bind none). `sandbox: true` is a separate route option. `route.pattern` is the matched pattern; `env` holds route-scoped values only.
|
|
72
|
+
Search the docs with bounded output using `npx --no --package @jimhoyd/urlcode urlcode docs search "TEXT"` (MCP `search_docs`)
|
|
73
|
+
rather than grepping llms-full.txt.
|
|
74
|
+
|
|
75
|
+
Handler for the response: fixed text or JSON is `respond`; one HTML file is `page`; a directory is
|
|
76
|
+
`static`; an attachment is `download`; a short HTML snippet is `respond` `text` with a
|
|
77
|
+
`Content-Type: text/html; charset=utf-8` header. Functions are trusted by default; add
|
|
78
|
+
`sandbox: true` to opt a route in ([function security](https://github.com/jimhoyd-com/urlcode/blob/main/docs/FUNCTION-SECURITY.md)).
|
|
79
|
+
|
|
80
|
+
After a real attempt, draft feedback only for a capability gap, repeated workaround, documentation
|
|
81
|
+
gap or suspected defect, with sanitized YAML and validation evidence. Search existing issues first;
|
|
82
|
+
never publish or comment without the user's approval.
|
|
83
|
+
|
|
84
|
+
## Reference (load one only when needed)
|
|
85
|
+
|
|
86
|
+
- Authoring: [AI authoring contract](https://github.com/jimhoyd-com/urlcode/blob/main/docs/AI-AUTHORING.md), [YAML guide](https://github.com/jimhoyd-com/urlcode/blob/main/docs/YAML-GUIDE.md), [field reference](https://github.com/jimhoyd-com/urlcode/blob/main/docs/YAML-REFERENCE.md), [JSON Schema](schemas/urlcode.schema.json), [semantics](https://github.com/jimhoyd-com/urlcode/blob/main/docs/SPECIFICATION.md), [cookbook](examples/cookbook/README.md), [recipes](https://github.com/jimhoyd-com/urlcode/blob/main/docs/RECIPES.md).
|
|
87
|
+
- Skills: [authoring](.claude/skills/urlcode-authoring/SKILL.md), [operations](.claude/skills/urlcode-operations/SKILL.md).
|
|
88
|
+
- Routes and handlers: [routing](https://github.com/jimhoyd-com/urlcode/blob/main/docs/ROUTING.md), [HTTP](https://github.com/jimhoyd-com/urlcode/blob/main/docs/HTTP.md), [middleware](https://github.com/jimhoyd-com/urlcode/blob/main/docs/MIDDLEWARE.md), [assets](https://github.com/jimhoyd-com/urlcode/blob/main/docs/ASSETS.md), [conditions](https://github.com/jimhoyd-com/urlcode/blob/main/docs/CONDITIONS.md), [egress](https://github.com/jimhoyd-com/urlcode/blob/main/docs/EGRESS.md), [prerender](https://github.com/jimhoyd-com/urlcode/blob/main/docs/PRERENDER.md), [site](https://github.com/jimhoyd-com/urlcode/blob/main/docs/SITE.md), [organization](https://github.com/jimhoyd-com/urlcode/blob/main/docs/ORGANIZATION.md).
|
|
89
|
+
- Extensions: [extensions](https://github.com/jimhoyd-com/urlcode/blob/main/docs/EXTENSIONS.md) (including [signed declarative artifacts](https://github.com/jimhoyd-com/urlcode/blob/main/docs/EXTENSIONS.md#signed-declarative-artifacts); MCP `get_extension_artifacts`), [composing a site](https://github.com/jimhoyd-com/urlcode/blob/main/docs/COMPOSING-A-SITE.md), [package and channel alignment](https://github.com/jimhoyd-com/urlcode/blob/main/docs/VERSION-ALIGNMENT.md). New first-party executable extension installs use an attested `extension-bundles@v…` GitHub Release and an explicit host; do not add deprecated extension npm packages to a new project. [urlcode-auth](https://github.com/jimhoyd-com/urlcode/tree/main/packages/auth), [urlcode-admin](https://github.com/jimhoyd-com/urlcode/tree/main/packages/admin), [urlcode-ui](https://github.com/jimhoyd-com/urlcode/tree/main/packages/ui), [urlcode-store](https://github.com/jimhoyd-com/urlcode/tree/main/packages/store), and [urlcode-forms](https://github.com/jimhoyd-com/urlcode/tree/main/packages/forms) are workspace bundle sources. Per-route middleware is native core (`middleware:` array), not a retired extension; core has no native `link` handler, but the store extension's `shortLinks` capability covers create, invalid-destination, redirect, missing-code and click-count for stored short links without a function — declare it under `extensions.store.config.shortLinks` (`urlcode docs search "shortLinks"`, MCP `search_docs`). Only report a gap for stored-link needs beyond that (custom redirect status, non-HTTP(S) destinations, per-record ownership).
|
|
90
|
+
- Tooling: [tooling and MCP](https://github.com/jimhoyd-com/urlcode/blob/main/docs/TOOLING.md), [TypeScript](https://github.com/jimhoyd-com/urlcode/blob/main/docs/TYPESCRIPT.md), [capabilities](https://github.com/jimhoyd-com/urlcode/blob/main/docs/CAPABILITIES.md), [plugins](https://github.com/jimhoyd-com/urlcode/blob/main/docs/PLUGINS.md), [interchange](https://github.com/jimhoyd-com/urlcode/blob/main/docs/INTERCHANGE.md), [bulk import](https://github.com/jimhoyd-com/urlcode/blob/main/docs/BULK.md).
|
|
91
|
+
- Operations: [operations](https://github.com/jimhoyd-com/urlcode/blob/main/docs/OPERATIONS.md), [install](https://github.com/jimhoyd-com/urlcode/blob/main/docs/INSTALL.md), [deployment checks](https://github.com/jimhoyd-com/urlcode/blob/main/docs/DEPLOYMENT-CHECKS.md), [readiness](https://github.com/jimhoyd-com/urlcode/blob/main/docs/READINESS.md), [capacity](https://github.com/jimhoyd-com/urlcode/blob/main/docs/CAPACITY.md), [resilience](https://github.com/jimhoyd-com/urlcode/blob/main/docs/RESILIENCE.md), [observability](https://github.com/jimhoyd-com/urlcode/blob/main/docs/OBSERVABILITY.md), [Vercel](https://github.com/jimhoyd-com/urlcode/blob/main/docs/VERCEL.md), [AWS](https://github.com/jimhoyd-com/urlcode/blob/main/docs/AWS.md), [Cloudflare](https://github.com/jimhoyd-com/urlcode/blob/main/docs/CLOUDFLARE.md), [static hosting](https://github.com/jimhoyd-com/urlcode/blob/main/docs/STATIC.md), [release readiness](https://github.com/jimhoyd-com/urlcode/blob/main/docs/RELEASE-READINESS.md), [roadmap](https://github.com/jimhoyd-com/urlcode/blob/main/ROADMAP.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jimhoyd/urlcode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "Portable runtime for programmable URL behavior",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -62,6 +62,10 @@
|
|
|
62
62
|
"types": "./dist/types/extensions.d.ts",
|
|
63
63
|
"default": "./dist/extensions.js"
|
|
64
64
|
},
|
|
65
|
+
"./extension-bundles": {
|
|
66
|
+
"types": "./dist/types/extension-bundles.d.ts",
|
|
67
|
+
"default": "./dist/extension-bundles.js"
|
|
68
|
+
},
|
|
65
69
|
"./sandbox": {
|
|
66
70
|
"types": "./dist/types/sandbox.d.ts",
|
|
67
71
|
"default": "./dist/sandbox.js"
|
|
@@ -69,7 +73,7 @@
|
|
|
69
73
|
"./package.json": "./package.json"
|
|
70
74
|
},
|
|
71
75
|
"files": [
|
|
72
|
-
".claude",
|
|
76
|
+
".claude/skills",
|
|
73
77
|
"dist",
|
|
74
78
|
"schemas",
|
|
75
79
|
"data",
|
|
@@ -81,19 +85,25 @@
|
|
|
81
85
|
"llms-full.txt",
|
|
82
86
|
"NOTICE",
|
|
83
87
|
"recipes",
|
|
84
|
-
"skills"
|
|
88
|
+
"skills",
|
|
89
|
+
"docs/AI-AUTHORING.md",
|
|
90
|
+
"docs/YAML-REFERENCE.md",
|
|
91
|
+
"docs/TOOLING.md",
|
|
92
|
+
"docs/FUNCTION-SECURITY.md"
|
|
85
93
|
],
|
|
86
94
|
"scripts": {
|
|
87
95
|
"build": "node --disable-warning=ExperimentalWarning scripts/build.ts",
|
|
96
|
+
"prepare": "node --disable-warning=ExperimentalWarning scripts/build.ts --quiet",
|
|
88
97
|
"typecheck": "tsc -p tsconfig.json",
|
|
89
98
|
"test": "node --conditions=development --test test/*.test.ts",
|
|
99
|
+
"test:shard": "node --conditions=development --test",
|
|
90
100
|
"lint": "eslint .",
|
|
91
101
|
"check": "npm run check:code && npm run check:docs",
|
|
92
102
|
"check:code": "node scripts/check.ts && node scripts/check-release-tags.ts && node scripts/check-workspace-links.ts && node scripts/check-issue-labels.ts && npm run release:check",
|
|
93
103
|
"test:workerd": "node scripts/workerd-parity.ts",
|
|
94
104
|
"verify": "npm run lint && npm run typecheck && npm run check && npm run build && npm test && npm run verify:workspaces",
|
|
95
105
|
"workspace:styles": "npm run styles --workspace @jimhoyd/urlcode-ui",
|
|
96
|
-
"verify:workspaces": "npm run verify --workspace @jimhoyd/urlcode-ui && npm run verify --workspace @jimhoyd/urlcode-auth && npm run verify --workspace @jimhoyd/urlcode-admin && npm run verify --workspace @jimhoyd/urlcode-store && npm run audit:packages && npm run test:workspace-integration",
|
|
106
|
+
"verify:workspaces": "npm run verify --workspace @jimhoyd/urlcode-ui && npm run verify --workspace @jimhoyd/urlcode-auth && npm run verify --workspace @jimhoyd/urlcode-admin && npm run verify --workspace @jimhoyd/urlcode-store && npm run verify --workspace @jimhoyd/urlcode-forms && npm run audit:packages && npm run test:workspace-integration",
|
|
97
107
|
"audit:packages": "node scripts/package-audit.ts --all",
|
|
98
108
|
"test:package": "npm run build && npm run test:package:built",
|
|
99
109
|
"dev": "node src/cli.ts dev --project starters/default",
|
|
@@ -110,6 +120,7 @@
|
|
|
110
120
|
"docs:llms": "node scripts/build-llms-full.ts",
|
|
111
121
|
"docs:cookbook-index": "node scripts/build-cookbook-index.ts",
|
|
112
122
|
"artifacts:prepare": "node --disable-warning=ExperimentalWarning scripts/prepare-extension-artifacts.ts",
|
|
123
|
+
"bundles:prepare": "node --disable-warning=ExperimentalWarning scripts/prepare-extension-bundles.ts",
|
|
113
124
|
"check:downstream-skills": "node scripts/check-downstream-skill-drift.ts",
|
|
114
125
|
"sync:agents": "node scripts/sync-agent-lists.ts",
|
|
115
126
|
"check:docs": "node scripts/check-trust-model-prose.ts && node scripts/check-version-statements.ts && node scripts/check-local-links.ts && node scripts/check-guidance-claims.ts && node scripts/generate-yaml-reference.ts --check && node scripts/build-llms-full.ts --check && node scripts/build-cookbook-index.ts --check && node scripts/generate-claude-plugin.ts --check",
|
|
@@ -14,8 +14,8 @@ Run `urlcode validate --local --project .` and `urlcode serve --project .`.
|
|
|
14
14
|
default). Add top-level `site: {notFound: 404.html}` for a custom 404 page
|
|
15
15
|
instead of the plain default.
|
|
16
16
|
|
|
17
|
-
For the shapes this recipe does not cover — a
|
|
18
|
-
|
|
17
|
+
For the shapes this recipe does not cover — a root-relative or `/**` suffix
|
|
18
|
+
redirect, or a host/scheme-based redirect — run
|
|
19
19
|
`urlcode context --project . --task redirects` (MCP `get_context
|
|
20
20
|
{"task":"redirects"}`) for the exact supported alternative and the exact
|
|
21
21
|
validation error, or see [docs/OPEN-DECISIONS.md](../../docs/OPEN-DECISIONS.md).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Store CRUD
|
|
2
2
|
|
|
3
3
|
`/api/todos/*` is a persistent JSON CRUD API. The project declares one
|
|
4
|
-
collection and its mount; the operator-installed `store` extension
|
|
5
|
-
|
|
4
|
+
collection and its mount; the operator-installed `store` extension serves it
|
|
5
|
+
from a verified bundle and keeps the data in the operator's
|
|
6
6
|
directory. There is no handler code. Full contract, limits and guarantees:
|
|
7
7
|
[docs/STORE.md](../../docs/STORE.md).
|
|
8
8
|
|
|
@@ -10,20 +10,19 @@ directory. There is no handler code. Full contract, limits and guarantees:
|
|
|
10
10
|
|
|
11
11
|
The store is not core and does not activate on its own.
|
|
12
12
|
|
|
13
|
-
- The operator
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
which the core published at the store's first release does not have, so write the host file below by hand until a
|
|
19
|
-
newer core is released.
|
|
13
|
+
- The operator selects the signed `store` bundle release and registers it in a
|
|
14
|
+
host file kept outside the project.
|
|
15
|
+
- `urlcode init --with ui,auth,store --bundle-release extension-bundles@v…`
|
|
16
|
+
scaffolds a protected site from verified bundles. A no-auth `init --with
|
|
17
|
+
store` needs `--ack store:public-write`.
|
|
20
18
|
- The data directory must be outside the project. It is single-writer: one
|
|
21
19
|
server process per directory.
|
|
22
20
|
|
|
23
21
|
```js
|
|
24
22
|
// /operator/host.mjs -- trusted operator code, never part of the project
|
|
25
23
|
import {inspectExtensionRevision} from '@jimhoyd/urlcode/extensions';
|
|
26
|
-
import {
|
|
24
|
+
import {loadExtensionBundle} from '@jimhoyd/urlcode/extension-bundles';
|
|
25
|
+
const {storeExtension} = await loadExtensionBundle(process.env.URLCODE_PROJECT, 'store');
|
|
27
26
|
const projectSha256 = await inspectExtensionRevision(process.env.URLCODE_PROJECT);
|
|
28
27
|
export default {extensions: [storeExtension({directory: '/operator/data/store', projectSha256})]};
|
|
29
28
|
```
|
|
@@ -7,7 +7,7 @@ targets: {self-hosted: conditional, cloudflare: refused, aws: conditional, verce
|
|
|
7
7
|
routes: 1
|
|
8
8
|
services:
|
|
9
9
|
- name: store extension
|
|
10
|
-
description: An operator host file registering
|
|
10
|
+
description: An operator host file registering the verified store bundle, with a data directory outside the project. `urlcode init --with ui,auth,store --bundle-release extension-bundles@v…` scaffolds a protected host, and the README shows a hand-written one.
|
|
11
11
|
grants:
|
|
12
12
|
- kind: extension
|
|
13
13
|
description: The registration pins projectSha256 to this exact revision; editing a collection or the mount needs operator review and a new pin.
|
|
@@ -15,7 +15,7 @@ static serving and authentication. Read this file before changing anything.
|
|
|
15
15
|
(limits; `--target NAME` before promising a provider), `get_schema`,
|
|
16
16
|
`recipes search TEXT`/`search_recipes` then `recipes add NAME --out DIR`,
|
|
17
17
|
`explain` and, with an operator host file, `get_extensions`. Bare
|
|
18
|
-
`capabilities` and `recipes list` are complete catalogs: fallback, not step one.
|
|
18
|
+
`capabilities` and `recipes list` are complete catalogs: fallback, not step one. Do not read or grep `llms-full.txt` or the packaged docs for a routine task.
|
|
19
19
|
4. Use URLCode's highest-level declarative features whenever possible. Generate custom code only when the framework cannot express the requirement. Check supported extensions and recipes first; explain any capability gap.
|
|
20
20
|
|
|
21
21
|
## MCP
|
|
@@ -49,7 +49,7 @@ skill only in a React frontend with `components.json`; start with `shadcn info
|
|
|
49
49
|
A `function`/`middleware` is trusted, in-process Node with only declared
|
|
50
50
|
`args`/`env`/`secrets`. Add `sandbox: true` for code needing isolation, not
|
|
51
51
|
merely untrusted input. The sandbox is text/JSON-only; use `proxy`/a binding and
|
|
52
|
-
record the reason in `sandboxReason`.
|
|
52
|
+
record the reason in `sandboxReason`. Try `redirect` (relative or `/**`) or `respond` first; a function gets `context.route.pattern`.
|
|
53
53
|
|
|
54
54
|
## Checks that count as evidence
|
|
55
55
|
|