@jimhoyd/urlcode 0.4.0-alpha.2 → 0.4.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +17 -19
  2. package/.claude/skills/urlcode-operations/SKILL.md +9 -9
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CONTRIBUTING.md +20 -16
  5. package/README.md +44 -54
  6. package/ROADMAP.md +61 -376
  7. package/dist/BUILD-MANIFEST.json +15 -15
  8. package/dist/agents-guide.js +6 -6
  9. package/dist/build-static.js +2 -0
  10. package/dist/cli.js +3 -3
  11. package/dist/explain-cli.js +4 -2
  12. package/dist/explain.js +7 -1
  13. package/dist/extensions.js +1 -1
  14. package/dist/manifest.js +7 -1
  15. package/dist/mcp-authoring.js +2 -2
  16. package/dist/mcp.js +1 -1
  17. package/dist/policies.js +3 -1
  18. package/dist/prerender.js +4 -0
  19. package/dist/readiness.js +3 -0
  20. package/dist/route-diff.js +12 -5
  21. package/dist/types/explain.d.ts +6 -0
  22. package/dist/types/extensions.d.ts +1 -1
  23. package/dist/types/manifest.d.ts +5 -1
  24. package/dist/types/readiness.d.ts +2 -0
  25. package/dist/types/types.d.ts +8 -1
  26. package/dist/types.js +8 -1
  27. package/dist/typescript-authoring.js +18 -7
  28. package/docs/AI-AUTHORING.md +10 -6
  29. package/docs/ASSETS.md +2 -1
  30. package/docs/AUTH-BACKUP.md +32 -0
  31. package/docs/BEST-PRACTICES.md +17 -9
  32. package/docs/CAPABILITIES.md +1 -1
  33. package/docs/CI-FOLLOWUP-2026-09-19.md +97 -0
  34. package/docs/CI-RELEASE-AUDIT-2026-09-19.md +322 -0
  35. package/docs/CI.md +8 -3
  36. package/docs/CODEBASE-AUDIT-2026-09-20.md +278 -0
  37. package/docs/DEVELOPMENT-PIPELINE.md +181 -0
  38. package/docs/EXTENSIONS.md +15 -5
  39. package/docs/FRAMEWORK.md +22 -18
  40. package/docs/FUNCTION-SECURITY.md +44 -0
  41. package/docs/LOCAL-DEVELOPMENT.md +3 -0
  42. package/docs/OPEN-DECISIONS.md +184 -212
  43. package/docs/OPERATIONAL-PROOF.md +3 -3
  44. package/docs/OPERATIONS.md +3 -3
  45. package/docs/POLICIES.md +13 -5
  46. package/docs/PRERENDER.md +23 -11
  47. package/docs/PROJECT-DIRECTION.md +3 -3
  48. package/docs/READINESS.md +6 -2
  49. package/docs/README.md +18 -41
  50. package/docs/RELEASE-0.4.0-alpha.3.md +50 -0
  51. package/docs/RELEASE-READINESS.md +6 -6
  52. package/docs/RELEASE-SECURITY.md +68 -168
  53. package/docs/RESILIENCE.md +3 -3
  54. package/docs/ROUTING.md +3 -4
  55. package/docs/SECURITY-AUDIT.md +2 -2
  56. package/docs/SPECIFICATION.md +7 -5
  57. package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +6 -5
  58. package/docs/SPIKE-BUSINESS-SUITE.md +14 -6
  59. package/docs/SPIKE-CORE-LAYERING.md +48 -17
  60. package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +7 -5
  61. package/docs/SPIKE-LAMBDA-COMPILE.md +8 -0
  62. package/docs/STATIC.md +14 -3
  63. package/docs/TOOLING.md +4 -3
  64. package/docs/TYPESCRIPT-AUTHORING.md +6 -1
  65. package/docs/VERSION-ALIGNMENT.md +46 -205
  66. package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +68 -0
  67. package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +102 -0
  68. package/docs/{NEXT-PHASE-PLAN.md → archive/2026-09-19/NEXT-PHASE-PLAN.md} +15 -5
  69. package/docs/{NEXT-STEPS.md → archive/2026-09-19/NEXT-STEPS.md} +15 -3
  70. package/docs/archive/2026-09-19/OPEN-DECISIONS.md +277 -0
  71. package/docs/archive/2026-09-19/RELEASE-SECURITY.md +186 -0
  72. package/docs/archive/2026-09-19/ROADMAP.md +386 -0
  73. package/docs/{SPIKE-EXTENSION-MODEL.md → archive/2026-09-19/SPIKE-EXTENSION-MODEL.md} +10 -0
  74. package/docs/{SPIKE-EXTENSIONS.md → archive/2026-09-19/SPIKE-EXTENSIONS.md} +25 -14
  75. package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +776 -0
  76. package/docs/{USABILITY-REVIEW.md → archive/2026-09-19/USABILITY-REVIEW.md} +12 -2
  77. package/docs/archive/README.md +27 -0
  78. package/docs/policies/agents.md +1 -1
  79. package/docs/policies/compression.md +3 -2
  80. package/docs/policies/security.md +3 -2
  81. package/examples/assets/example.yaml +1 -1
  82. package/examples/cookbook/route-index.json +1 -1
  83. package/examples/cookbook/routes/middleware.yaml +1 -1
  84. package/examples/prerender/README.md +14 -6
  85. package/examples/prerender/functions/page.mjs +4 -2
  86. package/examples/prerender/middleware/template.mjs +1 -1
  87. package/examples/prerender/prerender.mjs +1 -1
  88. package/examples/prerender/urlcode.yaml +8 -4
  89. package/llms-full.txt +117 -45
  90. package/llms.txt +5 -4
  91. package/package.json +24 -4
  92. package/packaging/claude-plugin/.claude-plugin/plugin.json +2 -2
  93. package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +17 -19
  94. package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +9 -9
  95. package/recipes/authenticated-json-api/README.md +4 -3
  96. package/recipes/authenticated-json-api/functions/profile.mjs +2 -1
  97. package/recipes/authenticated-json-api/recipe.yaml +1 -1
  98. package/recipes/contact-form/functions/contact.mjs +2 -1
  99. package/recipes/contact-form/recipe.yaml +2 -2
  100. package/recipes/cors-api/README.md +2 -2
  101. package/recipes/cors-api/recipe.yaml +1 -1
  102. package/recipes/health-page/README.md +1 -1
  103. package/recipes/json-api/README.md +1 -1
  104. package/recipes/json-api/recipe.yaml +3 -3
  105. package/recipes/middleware/README.md +8 -4
  106. package/recipes/protected-download/README.md +1 -1
  107. package/recipes/protected-download/recipe.yaml +1 -1
  108. package/recipes/static-plus-api/README.md +2 -2
  109. package/recipes/static-plus-api/public/index.html +1 -1
  110. package/recipes/static-plus-api/recipe.yaml +1 -1
  111. package/recipes/static-plus-api/urlcode.yaml +1 -1
  112. package/recipes/typescript/recipe.yaml +4 -4
  113. package/skills/urlcode/SKILL.md +6 -6
  114. package/starters/default/AGENTS.md +6 -6
  115. package/docs/SPIKE-MONOREPO.md +0 -322
package/docs/READINESS.md CHANGED
@@ -17,14 +17,18 @@ printed, and no remote load-test target is accepted.
17
17
 
18
18
  ## Inventory and count reconciliation
19
19
 
20
- `routes` reports each configured route's pattern, handler, exact allowed methods
20
+ `routes` reports each configured route's pattern, handler, exact allowed methods,
21
+ execution mode (`sandbox`, with `sandboxReason` when the route declares one)
21
22
  and active/disabled/expired state. It includes routes from YAML includes. A
22
23
  parameter pattern is one route; its possible URLs are not a finite route count.
23
24
  A static mount is one route, even when it contains many files.
24
25
 
25
26
  `routes --compare previous.json` diffs the current inventory against a saved
26
27
  `routes` report: added, removed and changed routes (handler, methods, state,
27
- middleware count, policies, generated marker and the policy description). It
28
+ execution mode and its reason, middleware count, policies, generated marker and
29
+ the policy description). A route that flips between trusted and sandboxed
30
+ execution is a change, including when its handler is native and only its
31
+ middleware runs project code. It
28
32
  prints JSON, or Markdown tables with `--format markdown`, and always exits 0;
29
33
  it reports, it does not judge. The [GitHub action](CI.md) posts this diff on
30
34
  pull requests.
package/docs/README.md CHANGED
@@ -1,15 +1,5 @@
1
1
  # URLCode documentation
2
2
 
3
- > **Public documentation is authored in a separate `urlcode-docs` repository,
4
- > not generated from this tree.** New reader-facing pages belong there; `docs/`
5
- > here keeps contributor and maintainer material (local development, CI, release
6
- > process, reviews, spikes, plans and the generated field reference). The
7
- > reader-facing pages still listed below are being migrated.
8
- >
9
- > `urlcode-docs` is currently private, so it isn't publicly browsable yet —
10
- > until it is, this file and this repository's README are the practical
11
- > reference.
12
-
13
3
  Start with [the framework](FRAMEWORK.md): the four packages, the ladder from
14
4
  redirects to a full application, the composition contract and the rules an AI
15
5
  agent must follow. [Project direction](PROJECT-DIRECTION.md) states the
@@ -26,8 +16,6 @@ boundary and the license. Use documentation pinned to your runtime revision;
26
16
  | Let an AI build routes | [AI authoring guide](AI-AUTHORING.md), [llms.txt](../llms.txt) |
27
17
  | Load authoring/operations rules into an agent | [Authoring skill](../.claude/skills/urlcode-authoring/SKILL.md), [operations skill](../.claude/skills/urlcode-operations/SKILL.md), [how they are distributed](AI-AUTHORING.md#agent-skills) |
28
18
  | Run examples | [25-route cookbook](../examples/cookbook/README.md), [prerender recipe](../examples/prerender/README.md), [small starter](STARTERS.md) |
29
- | Explore a standalone application | [URLCode Short demo](https://github.com/jimhoyd-com/urlcode-short), [build retrospective](https://github.com/jimhoyd-com/urlcode-short/blob/main/docs/BUILD-RETROSPECTIVE.md) |
30
- | Explore a static docs-site integration | URLCode Docs project (private repository; not yet publicly browsable) |
31
19
  | Understand exact behavior | [Specification](SPECIFICATION.md), [routing](ROUTING.md), [HTTP](HTTP.md) |
32
20
  | Run examples | [40-route cookbook](../examples/cookbook/README.md), [prerender recipe](../examples/prerender/README.md), [small starter](STARTERS.md) |
33
21
  | Let an AI build routes | [The framework](FRAMEWORK.md), [AI authoring guide](AI-AUTHORING.md), [llms.txt](../llms.txt), [SDK and read-only MCP](TOOLING.md) |
@@ -53,8 +41,9 @@ boundary and the license. Use documentation pinned to your runtime revision;
53
41
  |---|---|
54
42
  | Add accounts, sign-in and protected routes | [urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth#readme) |
55
43
  | Manage users, sessions, roles and audit | [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin#readme) |
56
- | Restyle every extension page and translate copy | [urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui#readme), [ui contract](https://github.com/jimhoyd-com/urlcode-ui/blob/main/CONTRACT.md) |
44
+ | Restyle every extension page and translate copy | [urlcode-ui](../packages/ui#readme), [ui contract](../packages/ui/CONTRACT.md) |
57
45
  | Write or install a versioned extension | [Extensions](EXTENSIONS.md), [example fixture](../examples/extensions/README.md) |
46
+ | Follow implementation of the auth, admin and UI extensions | [Extension implementation sequence](archive/2026-09-19/EXTENSION-IMPLEMENTATION.md) |
58
47
  | Know which core version an extension package supports, and how it says so | [Core version alignment](VERSION-ALIGNMENT.md) |
59
48
  | Add host behavior in operator code | [Plugins](PLUGINS.md) |
60
49
  | Use the API from TypeScript | [TypeScript: shipped declarations, exports, build and fidelity](TYPESCRIPT.md) |
@@ -70,11 +59,6 @@ boundary and the license. Use documentation pinned to your runtime revision;
70
59
  | Review security findings and gaps | [Internal security audit](SECURITY-AUDIT.md) |
71
60
  | Assess release readiness | [Evidence and open gates](RELEASE-READINESS.md) |
72
61
  | See unfinished work | [Roadmap](../ROADMAP.md) |
73
- | Read the design behind policies, plugins and templates | [Extensions spike](SPIKE-EXTENSIONS.md) |
74
- | Read the design for an authentication and authorization plugin | [Auth spike](SPIKE-AUTH.md) |
75
- | Read the design for the administration extension that manages users | [Admin spike](SPIKE-ADMIN.md) |
76
- | Read the design for the shared template kit every extension renders with | [UI kit spike](SPIKE-UI.md) |
77
- | Read the review of the extension model, its precedents and alignment | [Extension model review](SPIKE-EXTENSION-MODEL.md) |
78
62
  | Read the design for compiling function routes into per-route Lambdas | [Lambda compile spike](SPIKE-LAMBDA-COMPILE.md) |
79
63
  | Verify a running deployment matches the project | [Deployment checks](DEPLOYMENT-CHECKS.md) |
80
64
  | Inspect target support | [Capabilities and normalized representation](CAPABILITIES.md) |
@@ -83,29 +67,22 @@ boundary and the license. Use documentation pinned to your runtime revision;
83
67
  | Estimate concurrency and memory | [Capacity and limits](CAPACITY.md), [measurements](PERFORMANCE.md), [load testing](LOAD-TESTING.md) |
84
68
  | Prepare for overload, DDoS and recovery | [Resilience playbook](RESILIENCE.md) |
85
69
 
86
- ## Evidence, reviews and design records
70
+ ## Direction and evidence
87
71
 
88
- These are dated records, not guides. They say what has been checked and what
89
- has not, and why the design is the way it is.
72
+ Start with [principles and open decisions](OPEN-DECISIONS.md) for a plain-language
73
+ review and [the roadmap](../ROADMAP.md) for next work. Current behavior belongs
74
+ in the guides above and the [specification](SPECIFICATION.md).
90
75
 
91
- | Record | What it is |
92
- |---|---|
93
- | [Release readiness](RELEASE-READINESS.md) | Verified safeguards, open gates, supported scope |
94
- | [Usability review](USABILITY-REVIEW.md) | Where the framework is easier or harder than the tools it replaces, and ranked changes |
95
- | [Next steps](NEXT-STEPS.md) | The phased plan: agent discovery, context compression, retrieval, the ladder, benchmarks and the remaining proof gaps |
96
- | [AI-first framework benchmark spike](SPIKE-AI-FRAMEWORK-BENCHMARK.md) | Proposed research-first, independent-agent application and runtime benchmark with a verified issue/improvement loop |
97
- | [Next-phase implementation status](NEXT-PHASE-PLAN.md) | Source additions after 0.3.0 shipped in 0.4.0-alpha.1, and their evidence limits |
98
- | [Security review](SECURITY-AUDIT.md) | Internal findings and fixes; not an independent test |
99
- | [Standards audit](STANDARDS.md) | How the runtime conforms to the RFCs it touches |
100
- | [Sandbox review package](SANDBOX-REVIEW.md) | What an independent reviewer needs; assessment not yet performed |
101
- | [Operational drills](OPERATIONAL-PROOF.md) | Deployment acceptance drills CI runs |
102
- | [Release security](RELEASE-SECURITY.md) | Candidate signing and publication process |
103
- | [Core version alignment](VERSION-ALIGNMENT.md) | The supported core floor for each downstream repository, how it is declared, and the publish-then-raise-then-regenerate order |
104
- | [Extension model review](SPIKE-EXTENSION-MODEL.md) | Why extensions are shaped this way, with framework precedents |
105
- | [Extensions spike](SPIKE-EXTENSIONS.md) | The design behind policies and plugins; implemented |
106
- | [Lambda compile spike](SPIKE-LAMBDA-COMPILE.md) | Proposal: per-route Lambdas for functions; not implemented |
107
- | Auth, admin and UI spikes | Live in their repositories: [auth](https://github.com/jimhoyd-com/urlcode-auth/blob/main/docs/SPIKE-AUTH.md), [admin](https://github.com/jimhoyd-com/urlcode-admin/blob/main/docs/SPIKE-ADMIN.md), [ui](https://github.com/jimhoyd-com/urlcode-ui/blob/main/docs/SPIKE-UI.md) |
108
- | [Roadmap](../ROADMAP.md) | Implemented versus planned |
76
+ - [Release readiness](RELEASE-READINESS.md), [security audit](SECURITY-AUDIT.md),
77
+ [sandbox review](SANDBOX-REVIEW.md) and [provider evidence](PROVIDER-VERIFICATION.md)
78
+ distinguish implementation from evidence still missing.
79
+ - [Version alignment](VERSION-ALIGNMENT.md) and [release security](RELEASE-SECURITY.md)
80
+ describe peer compatibility and publication.
81
+ - Open proposals: [middleware layering](SPIKE-CORE-LAYERING.md),
82
+ [Lambda compilation](SPIKE-LAMBDA-COMPILE.md),
83
+ [agent benchmark](SPIKE-AI-FRAMEWORK-BENCHMARK.md), and
84
+ [business suite](SPIKE-BUSINESS-SUITE.md). None is an implementation promise.
85
+ - [Historical plans and reviews](archive/README.md) are archived separately.
109
86
 
110
- Examples are educational unless backed by the runnable cookbook and fixtures.
111
- Infrastructure limits are deployment settings, not fields to invent in route YAML.
87
+ Examples are educational unless backed by runnable fixtures. Infrastructure
88
+ limits are deployment settings, not fields to invent in route YAML.
@@ -0,0 +1,50 @@
1
+ # Coordinated 0.4.0-alpha.3 release
2
+
3
+ This release prepares core, UI, auth and admin at `0.4.0-alpha.3`, as explicitly
4
+ selected by the maintainer. The shared number identifies this tested package
5
+ set; it does not enable permanent fixed versioning or leave the alpha channel.
6
+ Existing versions, tags, and npm `latest` channels are preserved.
7
+
8
+ ## Included changes
9
+
10
+ Core includes the monorepo consolidation, corrected Windows npm invocation,
11
+ current trust-by-default authoring guidance, and support for a TypeScript module
12
+ shared by trusted and sandboxed routes without weakening the sandbox checks.
13
+ The CLI and MCP report the new runtime version. The runtime remains independent
14
+ of the extension implementations.
15
+
16
+ Auth includes deterministic worker cleanup on rejected initialization and
17
+ Windows backup flushing. Auth/admin refresh a lifecycle hook's entry module on
18
+ each activation; changes to the entry module's own imports still require restart.
19
+ The extension changelogs record their package-specific changes.
20
+
21
+ All four packages use the shared release coordinator, immutable release tags,
22
+ exact-commit full verification, retained retry artifacts and trusted npm
23
+ publication. The candidate rehearsal installs their tarballs together outside
24
+ the workspace and checks peers, public imports and scaffolding.
25
+
26
+ ## Installation and compatibility
27
+
28
+ Once publication has completed, install an exact, coordinated set in the
29
+ consumer application's directory:
30
+
31
+ ```sh
32
+ npm install --save-exact @jimhoyd/urlcode@0.4.0-alpha.3 @jimhoyd/urlcode-ui@0.4.0-alpha.3 @jimhoyd/urlcode-auth@0.4.0-alpha.3 @jimhoyd/urlcode-admin@0.4.0-alpha.3
33
+ ```
34
+
35
+ Applications only need the extensions they actually use; admin requires auth
36
+ and UI, and auth requires UI. Auth/admin peer floors for this release are
37
+ `>=0.4.0-alpha.3 <0.5.0`. Update their dependencies together when crossing from
38
+ the former `0.1.x` extension line. Commit the resulting lockfile and use `npm ci`
39
+ in deployment. This release changes package peer compatibility intentionally;
40
+ it does not imply all previously mixed versions are supported.
41
+
42
+ Publication order is core, UI, auth, admin. A partial release stops before the
43
+ next package; diagnose and rerun its original workflow without moving tags.
44
+ The standalone template remains an exact core consumer and is updated through
45
+ its own PR after core is published. Archived extension repositories are not
46
+ publication targets.
47
+
48
+ CI and candidate success are not independent security assessment, live-provider
49
+ acceptance, or operational recovery proof. The intermittent Windows startup
50
+ timeout remains tracked in #202.
@@ -41,7 +41,7 @@ deferred to the post-merge run.
41
41
  | Worker replacement | Repeated guest deadlines shed load and the pool returns to service after backoff, rather than latching off for the life of the process | Bounded by the configured worker count; no cross-process load balancing |
42
42
  | Shutdown | New work rejects; repeated close shares completion | Existing deadlines can still fail during shutdown |
43
43
  | Activation/recovery | Invalid reload retains last-good snapshot; corrupt revision metadata rejects activation | No deployment orchestration |
44
- | Packaging | Packed installation and starter examples tested; sensitive files excluded | `0.3.0` and `0.4.0-alpha.1` are published to npm as `@jimhoyd/urlcode` (`latest` and `alpha` dist-tags respectively; dist-tags verified against the npm registry on 2026-09-19, when the repository stood at the unpublished `0.4.0-alpha.2`). Published extension packages on the same date: `@jimhoyd/urlcode-auth@0.1.0-alpha.2`, `@jimhoyd/urlcode-admin@0.1.0-alpha.2`, `@jimhoyd/urlcode-ui@0.1.0-alpha.4`, `@jimhoyd/urlcode-short@0.1.0-alpha.1`, `@jimhoyd/urlcode-dynamic-link@0.1.0-alpha.1`, `@jimhoyd/urlcode-middleware@0.1.0-alpha.1`. Observed in passing: auth's dist-tags are split — `alpha` points at `0.1.0-alpha.2` while `latest` still points at `0.1.0-alpha.1`, so a plain `npm install @jimhoyd/urlcode-auth` resolves the older alpha. GitHub Releases attach a Homebrew formula (`urlcode.rb`) for manual copy into a tap, not an automated Homebrew Core/tap publish. No provider adapter guarantee. |
44
+ | Packaging | Packed installation and starter examples tested; sensitive files excluded | `0.3.0` and `0.4.0-alpha.1` are published to npm as `@jimhoyd/urlcode` (`latest` and `alpha` dist-tags respectively; dist-tags verified against the npm registry on 2026-09-19, when the repository stood at the unpublished `0.4.0-alpha.2`). Published extension packages on the same date: `@jimhoyd/urlcode-auth@0.1.0-alpha.2`, `@jimhoyd/urlcode-admin@0.1.0-alpha.2`, `@jimhoyd/urlcode-ui@0.1.0-alpha.4`. (`@jimhoyd/urlcode-short@0.1.0-alpha.1`, `@jimhoyd/urlcode-dynamic-link@0.1.0-alpha.1` and `@jimhoyd/urlcode-middleware@0.1.0-alpha.2` were also published on that date, then retired and unpublished later the same day; all three repositories were deleted. Middleware's withdrawal removed no capability — per-route middleware is native to core.) Observed in passing on that date: auth's dist-tags were split — `alpha` at `0.1.0-alpha.2` while `latest` lagged at `0.1.0-alpha.1`, so a plain `npm install @jimhoyd/urlcode-auth` resolved a build below admin's declared floor. That is resolved: auth and admin both read `latest` = `alpha` = `0.1.0-alpha.3`. `@jimhoyd/urlcode-ui` now carries a split of its own — `alpha` = `0.1.0-alpha.6`, `latest` = `0.1.0-alpha.5` — which is deliberate rather than drift, and safe only because admin's ui floor is exactly `>=0.1.0-alpha.5`. See [VERSION-ALIGNMENT.md](VERSION-ALIGNMENT.md). GitHub Releases attach a Homebrew formula (`urlcode.rb`) for manual copy into a tap, not an automated Homebrew Core/tap publish. No provider adapter guarantee. |
45
45
 
46
46
  `npm run check:downstream-skills` is a manual, advisory report worth running
47
47
  before a release: it diffs core's `.claude/skills/` copies against copies
@@ -93,7 +93,7 @@ local recipes, TypeScript authoring, bounded self-hosted proxy/signals and read-
93
93
  MCP. Local AWS/Vercel/Cloudflare adapter tests and deployment probe tooling exist,
94
94
  but actual provider deployments remain unverified. Node process/container hosting
95
95
  remains the reference execution target. Guest networking, durable signals and
96
- realtime capabilities are not provided. See [implementation status](NEXT-PHASE-PLAN.md)
96
+ realtime capabilities are not provided. See [implementation status](archive/2026-09-19/NEXT-PHASE-PLAN.md)
97
97
  and [roadmap](../ROADMAP.md); these additions do not close the operational gates above.
98
98
 
99
99
  The [internal security audit](SECURITY-AUDIT.md) records reproduced findings, fixes
@@ -107,10 +107,10 @@ compilation deadline, scoped/expiring/revocable operator credentials for host
107
107
  bindings, executable local/CI operational drills, and a main-only candidate
108
108
  signing/SBOM workflow. The loopback-only management API and its atomic SQLite
109
109
  mutation audits were part of the `link`/`dynamicLinks` store that PR #126
110
- removed from core; that functionality, and its hardening, now belongs to the
111
- `urlcode-dynamic-link` extension (docs/EXTENSIONS.md), published on npm as
112
- `@jimhoyd/urlcode-dynamic-link@0.1.0-alpha.1` as of 2026-09-19, not this
113
- runtime.
110
+ removed from core; that functionality moved to the `urlcode-dynamic-link`
111
+ extension (docs/EXTENSIONS.md), which was retired and unpublished on
112
+ 2026-09-19. No supported stored-link package ships today, and this runtime does
113
+ not provide one: a project needing a durable link store owns it itself.
114
114
 
115
115
  Still required: [independent review](SANDBOX-REVIEW.md), [actual deployment proof](OPERATIONAL-PROOF.md),
116
116
  and publication/support arrangements. The Apache-2.0 license and the 0.3.0 self-hosted
@@ -1,181 +1,81 @@
1
- # Candidate and release security process
1
+ # Candidate and release security
2
2
 
3
- URLCode 0.3.0 is the Apache-2.0 self-hosted baseline; licensing is defined
4
- in [LICENSE](../LICENSE). Two workflows share one audited build path and differ
5
- only in what they do with its output:
3
+ The [development pipeline](DEVELOPMENT-PIPELINE.md) is the operational runbook
4
+ for CI selection, release planning, tags, publication and recovery. The
5
+ [September 19 audit](CI-RELEASE-AUDIT-2026-09-19.md) explains the changes;
6
+ [the prior process and failure history](archive/2026-09-19/RELEASE-SECURITY.md)
7
+ is retained as a historical record, not current instructions.
6
8
 
7
- - `candidate.yml` is dispatched manually on main and retains a **signed build
8
- candidate** for 30 days without publishing it. Use it to review a commit
9
- before tagging it.
10
- - `release.yml` runs on a `v*` tag whose commit is already on main, and publishes
11
- a GitHub release. Publication to npm and GHCR is opt-in per repository variable
12
- (`PUBLISH_NPM`, `PUBLISH_CONTAINER`), so a release can be artifacts-only.
9
+ The license remains Apache-2.0. A successful release is not an independent
10
+ security assessment, hostile multi-tenant readiness claim or deployment proof.
11
+ See [release readiness](RELEASE-READINESS.md) and [security](../SECURITY.md).
13
12
 
14
- Neither workflow is a statement that a release is production-ready; see
15
- [release readiness](RELEASE-READINESS.md).
13
+ ## Source and validation
16
14
 
17
- ## Publishing an alpha
15
+ A release must name the checked-out commit, already on main, with successful
16
+ full verification of that exact SHA and CodeQL analysis. Full verification
17
+ means a successful nightly or manual `ci.yml` run across every supported OS/Node
18
+ combination; the compact push/PR matrix alone does not authorize publication. Package manifests,
19
+ lockfile versions and tag names must agree. Published peer floors must exist and
20
+ extension tests must resolve the published packages, not workspace source.
21
+ The manual core candidate and tagged core release use the same preparation
22
+ script with the digest-pinned Node image from Dockerfile. Locked dependencies,
23
+ verification, runtime audit, package installation tests and local drills precede
24
+ packing. Build commands in that container receive no GitHub token.
18
25
 
19
- An alpha such as `0.4.0-alpha.1` follows the same path: tag `v0.4.0-alpha.1`
20
- on a commit that is already on main. The release workflow publishes to npm
21
- only when the repository variable `PUBLISH_NPM` is `true` and the npm trusted
22
- publisher for this repository and `release.yml` exists; otherwise the run is
23
- artifacts-only (a GitHub release with the signed tarball). Publish order is
24
- core ui auth admin, because the extension packages declare
25
- `@jimhoyd/urlcode >=0.4.0-alpha.1 <0.5.0` and must resolve the core alpha.
26
+ The candidate workflow stores artifacts without publishing. A tagged release
27
+ publishes npm only when `PUBLISH_NPM=true` and core images only when
28
+ `PUBLISH_CONTAINER=true`. Preparation retains original artifacts for 90 days
29
+ before publication so reruns of the same run reuse them. Manual candidates retain
30
+ their existing 30-day retention. Keep independent last-good artifacts and
31
+ rehearse deployment rollback; Actions retention is not an archival guarantee.
26
32
 
27
- 1. Report vulnerabilities privately through [GitHub advisories](https://github.com/jimhoyd-com/urlcode/security/advisories/new).
28
- The maintainer triages impact, confirms affected exact revisions, coordinates a
29
- fix/retest privately, and publishes an advisory with upgrade guidance when safe.
30
- Current reviewed main is the security support baseline; no guaranteed SLA/backports.
31
- 2. Change dependencies through protected PRs. Review upstream provenance/advisories,
32
- lockfile integrity and tests. Direct dependencies are exact, npm installs use
33
- `npm ci`, CI actions use full commit SHAs, and container bases use SHA-256 digests.
34
- Dependabot proposes updates; it does not authorize merging. Never silently
35
- refresh dependencies during a candidate build.
36
- 3. After protected main checks pass, a maintainer manually dispatches
37
- `.github/workflows/candidate.yml` **on main**, or pushes a `v<version>` tag to
38
- run `.github/workflows/release.yml`. The release workflow refuses a tag whose
39
- commit is not an ancestor of main, refuses a tag that disagrees with
40
- `package.json`, and refuses to build a private or unlicensed package. It reads and validates the digest-pinned Node image directly from Dockerfile,
41
- installs without lifecycle scripts, verifies, package-tests and runs local drills.
42
- It packs the runtime and creates a CycloneDX dependency SBOM plus a manifest
43
- recording source commit, lockfile hash, engine versions and artifact hashes.
44
- The package contains `dist/`, produced inside that build from the tagged
45
- TypeScript sources by Node's type stripping (`scripts/build.ts`); `dist` is
46
- never committed. The manifest records the Node version that stripped it, the
47
- locked TypeScript version and a SHA-256 per emitted file
48
- (`dist/BUILD-MANIFEST.json`), so a download can be verified by running
49
- `npm run build` on the tagged commit with that Node version and comparing its
50
- `dist/` file by file. The build strips types and rewrites specifier
51
- extensions; it never bundles, minifies or transforms syntax, so every line of
52
- `dist/x.js` is the corresponding line of `src/x.ts`. CI's `build-fidelity`
53
- job builds twice and diffs the trees, so the transform is known to be
54
- deterministic before a tag is cut.
55
- 4. The pinned official `actions/attest` action signs provenance for the package,
56
- SBOM and manifest using short-lived GitHub OIDC/Sigstore credentials. No long-lived
57
- signing key is stored. Signing permissions exist only in this manual job; build
58
- commands run in a container without passing GitHub tokens. Candidate files are
59
- retained as GitHub Actions artifacts for 30 days. A release additionally attaches
60
- them to the GitHub release, and publishes to npm and to GHCR when those
61
- repository variables are enabled.
33
+ ## Identity and provenance
62
34
 
63
- **npm publication holds no credential.** The registry is configured with a
64
- trusted publisher naming this repository and `release.yml`, so the publish
65
- step exchanges the job's OIDC identity for a credential that lives for the
66
- length of one publish. There is no npm token in the repository's secrets to
67
- leak, revoke or rotate, and a fork or another workflow cannot publish under
68
- this package's name. Provenance is generated on that same identity, so
69
- `--provenance` is not passed and its absence is not a downgrade.
35
+ The four per-package workflow filenames are stable npm trusted-publisher
36
+ identities. npm publishing uses OIDC, npm 11.5.1 and a supported Node version,
37
+ with no long-lived npm token. Renaming a workflow or changing the repository
38
+ requires a reviewed registry trust migration. Successful preparation does not
39
+ prove the registry-side identity permits direct publication.
70
40
 
71
- A bearer token would silently take precedence over this exchange, so the
72
- publish step must reference none; `test/release.test.ts` fails if one
73
- reappears in it, and checks the npm and Node floors below which the exchange
74
- is not attempted at all.
75
- 5. Download the candidate for the intended commit and verify **each file**, e.g.
76
- `gh attestation verify jimhoyd-urlcode-0.3.0.tgz --repo jimhoyd-com/urlcode --signer-workflow jimhoyd-com/urlcode/.github/workflows/candidate.yml --source-ref refs/heads/main --source-digest APPROVED_COMMIT_SHA`
77
- (use `release.yml` as the signer workflow for a tagged release).
78
- Check the verified provenance's source commit against the approved commit, and
79
- compare package/SBOM hashes with the signed manifest. A signature establishes
80
- provenance, not safety, reproducible bytes or production approval. See
81
- [GitHub verification](https://cli.github.com/manual/gh_attestation_verify) and
82
- [the official attestation action](https://github.com/actions/attest).
83
- 6. Before registry publication, assign patch/release ownership and retention, and
84
- document version/support policy. Before claiming hostile multi-tenant or
85
- deployment-specific readiness, close independent-review and deployment gates. Keep last-good verified artifacts and compatible policies;
86
- rehearse rollback. Never overwrite a published artifact/version or downgrade a
87
- management writer past its audit/security baseline.
41
+ `actions/attest` signs the candidate files with GitHub OIDC/Sigstore provenance.
42
+ Core includes its package archive, dependency SBOM, build manifest, checksums,
43
+ and, for a release, Homebrew formula. Extensions include their archive and
44
+ checksums. The core manifest records source SHA, lockfile hash, Node and
45
+ TypeScript versions and emitted-file hashes. `dist/` is built, never committed.
88
46
 
89
- The SBOM describes npm dependencies; it is not a complete OS/container SBOM. Hosted
90
- runners and action runtimes remain platform-controlled. Digest pins improve supply
91
- chain integrity but do not prove byte-for-byte reproducibility or engine safety.
92
- Signing verification must be demonstrated on a successful main workflow run before
93
- claiming a candidate has been signed. Workflow definition alone is not that evidence.
94
- `release.yml` ran successfully for the first time publishing `v0.4.0-alpha.1`
95
- (2026-09-18), after the fixes below; treat any repository whose workflow has not
96
- had a real successful tagged run the same way this one was treated before that.
47
+ Verify an artifact with `gh attestation verify <tarball> --repo
48
+ jimhoyd-com/urlcode`, and constrain verification to the expected workflow,
49
+ source ref and source digest for the selected release. Compare the source and
50
+ artifact hashes to the intended release, rather than accepting any signed file.
51
+ A signature establishes provenance, not safety or reproducibility. The npm SBOM
52
+ is not a complete OS/container SBOM; hosted runners remain platform-controlled.
97
53
 
98
- ## What broke on every first release, and why
54
+ ## Immutability and channels
99
55
 
100
- Four repositories (core, ui, auth, admin) each cut their first tagged release in
101
- the same session. Every one hit a subset of the same bugs, because each
102
- `release.yml` was written and reviewed but never actually run end-to-end against
103
- a real tag before. None of this is repository-specific; check for all of it
104
- before trusting an unexercised release workflow:
56
+ Never delete/recreate or move a version tag to repair a workflow. A source fix
57
+ requires a new version. Repeating publication of an existing npm version requires
58
+ identical SHA-512 integrity. GitHub assets are compared and missing assets added;
59
+ existing unequal assets are never clobbered. Transient registry errors fail
60
+ closed rather than count as an unpublished version.
105
61
 
106
- - **`npm ci` on the bare runner's root-owned npm.** A build that runs entirely
107
- inside a pinned Docker image never calls `actions/setup-node`, so a later
108
- `npm install --global npm@11.5.1` (needed for the trusted-publishing floor)
109
- hits the runner's preinstalled, root-owned npm and fails `EACCES`. Add
110
- `actions/setup-node` before any step that installs global npm packages, even
111
- if the main build never touches the runner's own Node.
112
- - **The floor check must run after the pin, not before.** A guard asserting
113
- "npm ≥ 11.5.1" is useless directly after `setup-node` with `node-version: '22'`,
114
- which bundles npm ~10.9.x — it can never pass. The floor only means something
115
- once the publish step's own `npm install --global npm@11.5.1` has actually run.
116
- - **`npm publish` refuses an unqualified prerelease.** `You must specify a tag
117
- using --tag when publishing a prerelease version.` npm's safety default is
118
- `latest`; a prerelease must derive an explicit dist-tag from its version
119
- (`0.1.0-alpha.1` → `alpha`, anything without a `-` → `latest`) and pass
120
- `--tag`. This path is only exercised by a package's *first* prerelease, so it
121
- silently sat broken in every repository until each hit it for the first time.
122
- - **`npm pack --pack-destination candidate` needs `candidate/` to exist first.**
123
- npm does not create the destination directory; `mkdir -p candidate` first.
124
- - **A private repository's unauthenticated `git fetch origin main` cannot work.**
125
- If checkout uses `persist-credentials: false` (correct, for a step that
126
- should not need write access) and the repo is private, `git fetch` fails
127
- `could not read Username for 'https://github.com'` before ever reaching the
128
- version check. Compare the tag against main through the GitHub API instead
129
- (`gh api repos/OWNER/REPO/compare/main...SHA --jq .status`, expecting
130
- `identical` or `behind`) — it needs no credentials and stays read-only. Public
131
- repositories can keep the plain fetch; it works there.
132
- - **`--conditions=development` in `npm run verify`'s test script resolves peers
133
- to source that a real npm install never ships.** The regular CI job symlinks
134
- sibling checkouts in place of `node_modules`, so `./src/*.ts` exists and the
135
- flag is correct there. A release installs real published tarballs of its
136
- peers, which only ever ship `dist/`, so the same flag makes every import of a
137
- peer fail `ERR_MODULE_NOT_FOUND`. Drop the flag for the release-workflow test
138
- invocation specifically (run `node scripts/check-sqlite.mjs` explicitly first,
139
- since bypassing `npm test` skips that pretest hook), and audit any test file
140
- that separately hardcodes the flag in a spawned child process — it has to be
141
- fixed the same way, independently, wherever it appears.
142
- - **A peer-install command with the wrong flag combination is a silent no-op.**
143
- `npm install --no-save --no-package-lock --ignore-scripts --legacy-peer-deps
144
- <peer>@<version>` installed *nothing*, with no error, when the target package
145
- names already appear in `peerDependencies` — `npm ci` earlier reports "added N
146
- packages" as if it worked. Confirm the install actually happened
147
- (`ls node_modules/@scope/*/package.json` and print each version) rather than
148
- trusting the exit code; `--no-save --ignore-scripts <specs>` (no
149
- `--no-package-lock`, no `--legacy-peer-deps`) is the version that works, paired
150
- with `git diff --exit-code -- package.json package-lock.json` to prove nothing
151
- was recorded as a dependency.
152
- - **A version published from an unbuilt checkout is burned forever.** npm never
153
- allows a version to be replaced. `@jimhoyd/urlcode-auth@0.1.0-alpha.1` reached
154
- the registry from something other than the CI workflow (a manual `npm
155
- publish` run before `npm run build` had produced `dist/`), so the published
156
- tarball contained only metadata files and no code. Every consumer's typecheck
157
- failed with `Cannot find module '@jimhoyd/urlcode-auth'` — a real, correct
158
- failure, not a bug in the consumer. The only fix is bumping to a new version
159
- and publishing that instead; nothing can repair or unpublish the bad one.
160
- **Never run `npm publish` by hand outside the release workflow** — the
161
- workflow is the only place that reliably builds before packing.
162
- - **`ENEEDAUTH` on `npm publish` under trusted publishing usually means the
163
- registry-side configuration doesn't exist or doesn't permit direct publish
164
- yet**, not a workflow bug. Trusted publishing needs an entry under the
165
- package's npm settings ("Trusted Publisher") naming the exact GitHub
166
- org/repo and workflow filename, with no environment set unless the workflow
167
- declares one; recent npm UI changes default new configurations to
168
- "stage publish" only; "allow npm publish" (direct publish, which is what
169
- this project's workflows do) must be explicitly enabled too. A wrong
170
- org/repo/workflow match tends to surface as a 404, not `ENEEDAUTH`;
171
- `ENEEDAUTH` is the signature of no matching configuration existing at all.
172
- - **Publish order matters and is easy to get backwards.** Extension packages
173
- declare `@jimhoyd/urlcode >=X <Y` as a peer range; publish core before ui,
174
- auth or admin, or their own release-workflow peer-install step has nothing
175
- real to resolve against.
62
+ Alpha versions use npm/GHCR `alpha` and GitHub prerelease classification. New
63
+ GitHub releases are not automatically promoted to GitHub `latest`. Mutable npm
64
+ and container channels cannot regress to an older version. Existing core image
65
+ versions are reused only with matching source labels; unlabeled historical
66
+ images require a reviewed migration rather than an inferred identity.
176
67
 
177
- None of the above is exotic; all nine bugs were found by actually running each
178
- workflow against a real tag, one release at a time, and reading the actual
179
- failure rather than guessing from the workflow source. Treat "the workflow file
180
- looks right" and "the workflow has actually published successfully once" as two
181
- different, unrelated claims.
68
+ The coordinator creates one package tag at a time and waits for success before
69
+ releasing dependents. Shared publication concurrency avoids cross-version races.
70
+ The active immutable-tag rule blocks release tag updates/deletions with no
71
+ bypass actors; its configuration is in `.github/rulesets/release-tags.json`. No automation needs permission to bypass main checks or approve
72
+ its own PR. A repository-scoped GitHub App is the preferred eventual automation
73
+ identity; a narrowly scoped fine-grained PAT can support a maintainer script.
74
+
75
+ ## Remaining validation
76
+
77
+ Keep full supported-OS/Node coverage and archive-install tests green. The actual
78
+ publish path, OIDC trust for every package, tag protection, GHCR behavior and
79
+ partial-failure recovery must be verified on an authorized release; local tests
80
+ and workflow inspection cannot prove them. The release helpers do not alter
81
+ historical npm channels, GitHub flags, tags or registry artifacts.
@@ -156,6 +156,6 @@ admission/fairness, production metrics/exporters, dedicated slow-reader protecti
156
156
  provider-level mitigation validation and sustained failure/soak testing. These are
157
157
  free-runtime/operator requirements.
158
158
 
159
- Core has no durable store of its own to recover; a future durable-state
160
- extension (such as the planned `urlcode-dynamic-link`) is responsible for its
161
- own management listener, backup and recovery procedure once it exists.
159
+ Core has no durable store of its own to recover; a durable-state extension is
160
+ responsible for its own management listener, backup and recovery procedure. No
161
+ such extension ships today `urlcode-dynamic-link` has been retired.
package/docs/ROUTING.md CHANGED
@@ -84,10 +84,9 @@ any per-visitor session record. Git owns route behavior and code; user-created r
84
84
  their own persistence, backup and export lifecycle.
85
85
 
86
86
  Core has no native handler for this today: the `link` handler that implemented
87
- it was removed. Stored short links are moving to a future
88
- `urlcode-dynamic-link` extension package (mount-based, like `auth`/`admin`,
89
- not yet published); a project needing them declares an `extension` mount once
90
- that package exists.
87
+ it was removed. The `urlcode-dynamic-link` extension package that replaced it
88
+ has been retired and unpublished, so a project needing stored short links owns
89
+ that storage itself.
91
90
 
92
91
  Functions still cannot access databases, the filesystem or network directly.
93
92
  General application state and realtime sessions remain future work.
@@ -85,7 +85,7 @@ Management event status 0 means no response headers were sent before disconnect.
85
85
  An aborted request may have committed a mutation: reconcile record/version before
86
86
  retrying. These logs are best effort, may be dropped under pressure, identify a configured credential ID (or a legacy shared token), and are not a
87
87
  tamper-evident journal. Successful store mutations now have separate transactional
88
- audit records; see [management security](MANAGEMENT-SECURITY.md). A failed sink needs collector/operator recovery;
88
+ audit records; see [management security](archive/2026-09-19/MANAGEMENT-SECURITY.md). A failed sink needs collector/operator recovery;
89
89
  URLCode cannot report failures reliably through the same broken output stream.
90
90
 
91
91
  ## Boundaries checked
@@ -122,7 +122,7 @@ limits. No anonymous code/config upload service is approved by these changes.
122
122
  collection/action scopes, expiry and hot revocation, plus atomic SQLite mutation
123
123
  audits are implemented. Legacy shared tokens remain for compatibility. There is
124
124
  no public user-account system, MFA/SSO, built-in rate limiter, credential issuance
125
- service or external tamper-evident archive. See [management security](MANAGEMENT-SECURITY.md).
125
+ service or external tamper-evident archive. See [management security](archive/2026-09-19/MANAGEMENT-SECURITY.md).
126
126
 
127
127
  **Before claiming operational readiness:** execute sustained mixed-workload soak,
128
128
  backup restoration, disk-full, process-kill, proxy timeout and rollback drills on
@@ -158,10 +158,10 @@ keys preserve repeated values. Headers are forwarded only through explicit maps.
158
158
  ## Stored links
159
159
 
160
160
  Core has no native `link` handler or `dynamicLinks` project flag; both were
161
- removed. Stored short links are moving to a future `urlcode-dynamic-link`
162
- extension package (mount-based, like `auth`/`admin`), not yet published. A
163
- project needing them declares an `extension` mount once that package exists;
164
- there is no in-core replacement or deprecation shim for `link`/`dynamicLinks`.
161
+ removed. The `urlcode-dynamic-link` extension package that replaced them has
162
+ been retired and unpublished, so a project needing stored short links owns that
163
+ storage itself; there is no in-core replacement or deprecation shim for
164
+ `link`/`dynamicLinks`.
165
165
 
166
166
  ## Functions
167
167
 
@@ -329,7 +329,9 @@ are local Git-owned examples; they grant no capabilities. [Build-time TypeScript
329
329
  is separate from runtime execution.
330
330
 
331
331
  The [tooling SDK and optional local MCP](TOOLING.md) inspect and validate without
332
- executing handlers or reading binding values. [Provider conformance](PROVIDER-VERIFICATION.md)
332
+ executing handlers or reading binding values. MCP defaults to inspection; the
333
+ explicit `--allow-authoring` option enables bounded project writes, separately
334
+ from host-file loading and grants. [Provider conformance](PROVIDER-VERIFICATION.md)
333
335
  distinguishes local adapter replay from actual deployment observations; no real
334
336
  provider deployment is implied by CI. [Proxy and signal egress](EGRESS.md) requires
335
337
  external revision-pinned operator grants and bounded host-owned transport;
@@ -32,7 +32,7 @@ Before building the application or a new harness, investigate:
32
32
  - Agent productivity studies, framework comparison applications and standard
33
33
  CRUD/full-stack benchmark applications.
34
34
  - URLCode's existing [agent harness](../benchmarks/agent/README.md), authoring
35
- evals, [next-steps plan](NEXT-STEPS.md), and runtime benchmarks in
35
+ evals, [next-steps plan](archive/2026-09-19/NEXT-STEPS.md), and runtime benchmarks in
36
36
  `benchmarks/routing.ts`, `benchmarks/bulk.ts` and
37
37
  `benchmarks/sandbox-vs-trusted.ts`.
38
38
 
@@ -198,8 +198,9 @@ For each verified, actionable issue include:
198
198
  - Acceptance criteria and related/duplicate issue links.
199
199
 
200
200
  Use the owning repository's issue template and the ownership map in
201
- [AGENTS.md](../AGENTS.md): core/runtime issues belong here, public documentation
202
- in `urlcode-docs`, and extension defects in the corresponding extension repository.
201
+ [AGENTS.md](../AGENTS.md): core/runtime issues belong here, documentation
202
+ included -- `urlcode-docs` is deleted and cannot accept issues -- and extension
203
+ defects in the corresponding extension repository.
203
204
  Update existing issues with new evidence rather than duplicating them. Track
204
205
  prepared, filed, duplicate and unverified dispositions in the findings report;
205
206
  file verified issues and retain unresolved hypotheses as explicitly unverified
@@ -220,8 +221,8 @@ current contract when documents and historical benchmark assumptions differ.
220
221
 
221
222
  Preserve Agent A's baseline before editing guidance. Then propose the smallest
222
223
  authoritative set of changes that makes the principle clear to people and agents,
223
- including when custom JavaScript is appropriate. Public authoring guidance belongs
224
- in `urlcode-docs`; contributor records and spikes remain here. Do not copy the rule
224
+ including when custom JavaScript is appropriate. Public authoring guidance and
225
+ contributor records both belong here, now that `urlcode-docs` is deleted. Do not copy the rule
225
226
  everywhere or expose the experimental prompt as product guidance by accident.
226
227
 
227
228
  ## Phase 6 — Fastify comparison
@@ -1,17 +1,25 @@
1
1
  # URLCode business suite spike
2
2
 
3
+ > Review update, 2026-09-19: Current status: an unapproved candidate list, gated on observed repetition
4
+ > and benchmark evidence under PROJECT-DIRECTION.md. The short-link products
5
+ > are retired; the seven-product recommendation below is historical, not agreed
6
+ > current scope. No business-suite implementation is implied.
7
+
8
+
3
9
  Date: 2026-09-18. Status: proposal, not an implemented contract or production claim.
4
10
  Core inspected at `50790d3` (0.4.0-alpha.1), plus local auth, admin, UI and
5
11
  shortener source/status files. Competitor research below is a documentation
6
12
  review, not hands-on benchmarking. Features and commercial packaging can change.
7
13
 
8
14
  > **Update:** this proposal was written when `link`/`LinkStore` was still a
9
- > native core feature. Core no longer has that API — it was extracted to the
10
- > separate [`urlcode-dynamic-link`](https://github.com/jimhoyd-com/urlcode-dynamic-link)
11
- > package. References below to core owning link storage (e.g. "Reuse core's
12
- > LinkStore", "Retain core link semantics", the `core LinkStore -> short`
13
- > dependency line) describe the pre-extraction state this spike was proposing
14
- > against, not current core.
15
+ > native core feature. Core no longer has that API — it was extracted to a
16
+ > separate `urlcode-dynamic-link` package, which has since been retired,
17
+ > unpublished and deleted (September 2026), along with the `urlcode-short`
18
+ > shortener this document proposes. Those two products are no longer planned.
19
+ > References below to core owning link storage (e.g. "Reuse core's LinkStore",
20
+ > "Retain core link semantics", the `core LinkStore -> short` dependency line)
21
+ > describe the pre-extraction state this spike was proposing against, and the
22
+ > `urlcode-short` migration sections record an abandoned plan.
15
23
 
16
24
  ## Recommendation
17
25