@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.1
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 +106 -0
- package/.claude/skills/urlcode-operations/SKILL.md +114 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/CONTRIBUTING.md +30 -2
- package/README.md +157 -230
- package/ROADMAP.md +85 -2
- package/SECURITY.md +8 -1
- package/dist/BUILD-MANIFEST.json +62 -32
- package/dist/adapters.js +4 -23
- package/dist/agent-lists.js +1 -1
- package/dist/agents-guide.js +113 -0
- package/dist/authoring-files.js +60 -0
- package/dist/authoring.js +11 -1
- package/dist/aws.js +4 -3
- package/dist/build-cloudflare.js +11 -24
- package/dist/bulk.js +37 -0
- package/dist/capabilities.js +208 -0
- package/dist/capability-query.js +72 -0
- package/dist/catalog.js +105 -0
- package/dist/cli.js +154 -15
- package/dist/client-address.js +1 -1
- package/dist/compliance-rules/baseline.js +8 -8
- package/dist/compliance-rules/privacy.js +3 -3
- package/dist/compliance-rules/strict.js +5 -5
- package/dist/conditions.js +88 -0
- package/dist/config.js +60 -4
- package/dist/context.js +156 -0
- package/dist/ecosystem-cli.js +88 -0
- package/dist/egress.js +98 -0
- package/dist/examples.js +92 -0
- package/dist/explain-cli.js +64 -0
- package/dist/explain.js +132 -0
- package/dist/extensions.js +172 -0
- package/dist/function-sources.js +15 -3
- package/dist/index.js +37 -0
- package/dist/init-with.js +165 -0
- package/dist/interchange-cli.js +42 -0
- package/dist/interchange.js +189 -0
- package/dist/link-cli.js +1 -1
- package/dist/management-policy.js +0 -1
- package/dist/manifest.js +111 -0
- package/dist/match.js +2 -2
- package/dist/mcp-authoring.js +147 -0
- package/dist/mcp.js +97 -0
- package/dist/observability.js +6 -0
- package/dist/operator-host.js +29 -0
- package/dist/plugins.js +12 -0
- package/dist/policies/agents.js +2 -2
- package/dist/policies/compression.js +2 -1
- package/dist/policies/security.js +0 -0
- package/dist/policies.js +1 -1
- package/dist/policy.js +29 -7
- package/dist/prerender.js +100 -41
- package/dist/project-tests.js +3 -3
- package/dist/provider-verification.js +92 -0
- package/dist/proxy.js +44 -0
- package/dist/readiness.js +5 -5
- package/dist/recipes.js +41 -0
- package/dist/route-diff.js +106 -0
- package/dist/router.js +42 -2
- package/dist/runtime.js +95 -14
- package/dist/schema-query.js +62 -0
- package/dist/signals.js +24 -0
- package/dist/site.js +0 -0
- package/dist/tooling.js +96 -0
- package/dist/types/adapters.d.ts +7 -4
- package/dist/types/agent-lists.d.ts +0 -1
- package/dist/types/agents-guide.d.ts +17 -0
- package/dist/types/authoring-files.d.ts +10 -0
- package/dist/types/aws.d.ts +3 -1
- package/dist/types/build-cloudflare.d.ts +1 -0
- package/dist/types/bulk.d.ts +27 -0
- package/dist/types/capabilities.d.ts +55 -0
- package/dist/types/capability-query.d.ts +24 -0
- package/dist/types/catalog.d.ts +65 -0
- package/dist/types/client-address.d.ts +0 -1
- package/dist/types/compliance-rules/baseline.d.ts +1 -9
- package/dist/types/compliance-rules/privacy.d.ts +1 -4
- package/dist/types/compliance-rules/strict.d.ts +0 -5
- package/dist/types/conditions.d.ts +19 -0
- package/dist/types/config.d.ts +20 -2
- package/dist/types/context.d.ts +65 -0
- package/dist/types/ecosystem-cli.d.ts +17 -0
- package/dist/types/egress.d.ts +46 -0
- package/dist/types/examples.d.ts +50 -0
- package/dist/types/explain-cli.d.ts +11 -0
- package/dist/types/explain.d.ts +95 -0
- package/dist/types/extensions.d.ts +122 -0
- package/dist/types/function-sources.d.ts +5 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/init-with.d.ts +30 -0
- package/dist/types/interchange-cli.d.ts +16 -0
- package/dist/types/interchange.d.ts +42 -0
- package/dist/types/link-cli.d.ts +2 -1
- package/dist/types/management-policy.d.ts +0 -1
- package/dist/types/manifest.d.ts +81 -0
- package/dist/types/match.d.ts +1 -0
- package/dist/types/mcp-authoring.d.ts +92 -0
- package/dist/types/mcp.d.ts +12 -0
- package/dist/types/observability.d.ts +2 -0
- package/dist/types/operator-host.d.ts +8 -0
- package/dist/types/plugins.d.ts +2 -0
- package/dist/types/policies/agents.d.ts +0 -2
- package/dist/types/policies/compression.d.ts +2 -0
- package/dist/types/policies/security.d.ts +0 -1
- package/dist/types/policy.d.ts +15 -4
- package/dist/types/project-tests.d.ts +3 -1
- package/dist/types/provider-verification.d.ts +53 -0
- package/dist/types/proxy.d.ts +21 -0
- package/dist/types/readiness.d.ts +1 -1
- package/dist/types/recipes.d.ts +30 -0
- package/dist/types/route-diff.d.ts +27 -0
- package/dist/types/runtime.d.ts +11 -0
- package/dist/types/schema-query.d.ts +12 -0
- package/dist/types/signals.d.ts +25 -0
- package/dist/types/site.d.ts +0 -1
- package/dist/types/tooling.d.ts +115 -0
- package/dist/types/types.d.ts +57 -0
- package/dist/types/typescript-authoring.d.ts +12 -0
- package/dist/types/vercel.d.ts +3 -1
- package/dist/types/verify-deployment.d.ts +47 -0
- package/dist/types.js +21 -2
- package/dist/typescript-authoring.js +104 -0
- package/dist/vercel.js +4 -3
- package/dist/verify-deployment.js +270 -0
- package/docs/AI-AUTHORING.md +130 -8
- package/docs/BULK.md +79 -0
- package/docs/CAPABILITIES.md +179 -0
- package/docs/CAPACITY.md +1 -1
- package/docs/CI.md +142 -0
- package/docs/CONDITIONS.md +74 -0
- package/docs/DEPLOYMENT-CHECKS.md +108 -0
- package/docs/DYNAMIC-LINKS.md +18 -518
- package/docs/EGRESS.md +125 -0
- package/docs/EXTENSIONS.md +226 -0
- package/docs/FRAMEWORK.md +182 -0
- package/docs/INSTALL.md +45 -7
- package/docs/INTERCHANGE.md +134 -0
- package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
- package/docs/MIDDLEWARE.md +2 -0
- package/docs/NEXT-PHASE-PLAN.md +90 -0
- package/docs/NEXT-STEPS.md +415 -0
- package/docs/OBSERVABILITY.md +4 -2
- package/docs/OPERATIONAL-PROOF.md +4 -1
- package/docs/OPERATIONS.md +6 -3
- package/docs/PLUGINS.md +37 -0
- package/docs/POLICIES.md +12 -309
- package/docs/PRERENDER.md +40 -0
- package/docs/PROJECT-DIRECTION.md +42 -0
- package/docs/PROVIDER-VERIFICATION.md +84 -0
- package/docs/READINESS.md +21 -1
- package/docs/README.md +82 -31
- package/docs/RECIPES.md +99 -0
- package/docs/RELEASE-READINESS.md +11 -9
- package/docs/RELEASE-SECURITY.md +27 -4
- package/docs/SECURITY-AUDIT.md +1 -1
- package/docs/SPECIFICATION.md +95 -8
- package/docs/SPIKE-BUSINESS-SUITE.md +1013 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
- package/docs/SPIKE-EXTENSIONS.md +1 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +199 -0
- package/docs/STANDARDS.md +150 -142
- package/docs/STARTERS.md +21 -1
- package/docs/TOOLING.md +291 -0
- package/docs/TYPESCRIPT-AUTHORING.md +67 -0
- package/docs/TYPESCRIPT.md +1 -1
- package/docs/USABILITY-REVIEW.md +123 -0
- package/docs/YAML-GUIDE.md +18 -479
- package/docs/YAML-REFERENCE.md +127 -16
- package/docs/links/cli.md +110 -0
- package/docs/links/limits.md +175 -0
- package/docs/links/management-api.md +80 -0
- package/docs/links/pools.md +75 -0
- package/docs/links/setup.md +135 -0
- package/docs/policies/agents.md +1 -1
- package/docs/policies/contract.md +52 -0
- package/docs/policies/hardened.md +56 -0
- package/docs/policies/interoperability.md +169 -0
- package/docs/policies/operations.md +45 -0
- package/docs/yaml/assets.md +36 -0
- package/docs/yaml/conditions.md +20 -0
- package/docs/yaml/functions.md +160 -0
- package/docs/yaml/links.md +30 -0
- package/docs/yaml/middleware.md +29 -0
- package/docs/yaml/organization.md +74 -0
- package/docs/yaml/policies.md +37 -0
- package/docs/yaml/redirects.md +64 -0
- package/docs/yaml/responses.md +57 -0
- package/docs/yaml/site.md +24 -0
- package/examples/assets/example.yaml +17 -0
- package/examples/aws/example.yaml +20 -0
- package/examples/cloudflare/example.yaml +19 -0
- package/examples/compliance/example.yaml +11 -0
- package/examples/conditions/README.md +12 -0
- package/examples/conditions/example.yaml +19 -0
- package/examples/conditions/tests/requests.json +13 -0
- package/examples/conditions/urlcode.yaml +24 -0
- package/examples/cookbook/README.md +8 -4
- package/examples/cookbook/example.yaml +17 -0
- package/examples/cookbook/functions/catalog.mjs +3 -0
- package/examples/cookbook/functions/fail.mjs +4 -0
- package/examples/cookbook/functions/items.mjs +3 -0
- package/examples/cookbook/functions/profile.mjs +3 -0
- package/examples/cookbook/functions/resource.mjs +3 -0
- package/examples/cookbook/functions/status.mjs +3 -0
- package/examples/cookbook/middleware/auth.mjs +48 -0
- package/examples/cookbook/middleware/body.mjs +15 -0
- package/examples/cookbook/middleware/bucket.mjs +19 -0
- package/examples/cookbook/middleware/cors.mjs +21 -0
- package/examples/cookbook/middleware/debug.mjs +13 -0
- package/examples/cookbook/middleware/envelope.mjs +11 -0
- package/examples/cookbook/middleware/errors.mjs +11 -0
- package/examples/cookbook/middleware/etag.mjs +18 -0
- package/examples/cookbook/middleware/locale.mjs +16 -0
- package/examples/cookbook/middleware/maintenance.mjs +10 -0
- package/examples/cookbook/middleware/methods.mjs +15 -0
- package/examples/cookbook/middleware/negotiate.mjs +20 -0
- package/examples/cookbook/middleware/referer.mjs +12 -0
- package/examples/cookbook/middleware/request-id.mjs +16 -0
- package/examples/cookbook/route-index.json +676 -0
- package/examples/cookbook/routes/middleware.yaml +126 -0
- package/examples/cookbook/tests/requests.json +526 -0
- package/examples/cookbook/urlcode.yaml +1 -0
- package/examples/egress/README.md +22 -0
- package/examples/egress/example.yaml +19 -0
- package/examples/egress/urlcode.yaml +19 -0
- package/examples/extensions/README.md +7 -0
- package/examples/extensions/example.yaml +21 -0
- package/examples/extensions/urlcode.yaml +25 -0
- package/examples/live-links/example.yaml +21 -0
- package/examples/monitoring/example.yaml +8 -0
- package/examples/prerender/example.yaml +16 -0
- package/examples/provider-conformance/README.md +12 -0
- package/examples/provider-conformance/example.yaml +14 -0
- package/examples/provider-conformance/urlcode.yaml +34 -0
- package/examples/tunnel/example.yaml +8 -0
- package/examples/vercel/example.yaml +19 -0
- package/llms-full.txt +2709 -0
- package/llms.txt +48 -19
- package/package.json +29 -7
- package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +106 -0
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +114 -0
- package/recipes/authenticated-json-api/README.md +51 -0
- package/recipes/authenticated-json-api/functions/profile.mjs +5 -0
- package/recipes/authenticated-json-api/recipe.yaml +34 -0
- package/recipes/authenticated-json-api/tests/requests.json +39 -0
- package/recipes/authenticated-json-api/urlcode.yaml +12 -0
- package/recipes/contact-form/README.md +25 -0
- package/recipes/contact-form/functions/contact.mjs +17 -0
- package/recipes/contact-form/recipe.yaml +33 -0
- package/recipes/contact-form/tests/requests.json +47 -0
- package/recipes/contact-form/urlcode.yaml +18 -0
- package/recipes/cors-api/README.md +16 -0
- package/recipes/cors-api/functions/items.mjs +3 -0
- package/recipes/cors-api/middleware/cors.mjs +21 -0
- package/recipes/cors-api/recipe.yaml +26 -0
- package/recipes/cors-api/tests/requests.json +65 -0
- package/recipes/cors-api/urlcode.yaml +12 -0
- package/recipes/health-page/README.md +13 -0
- package/recipes/health-page/recipe.yaml +23 -0
- package/recipes/health-page/tests/requests.json +36 -0
- package/recipes/health-page/urlcode.yaml +19 -0
- package/recipes/json-api/README.md +6 -0
- package/recipes/json-api/functions/echo.mjs +3 -0
- package/recipes/json-api/recipe.yaml +25 -0
- package/recipes/json-api/tests/requests.json +34 -0
- package/recipes/json-api/urlcode.yaml +12 -0
- package/recipes/middleware/README.md +34 -0
- package/recipes/middleware/functions/catalog.mjs +3 -0
- package/recipes/middleware/functions/fail.mjs +4 -0
- package/recipes/middleware/functions/items.mjs +3 -0
- package/recipes/middleware/functions/profile.mjs +3 -0
- package/recipes/middleware/functions/resource.mjs +3 -0
- package/recipes/middleware/functions/status.mjs +3 -0
- package/recipes/middleware/middleware/auth.mjs +48 -0
- package/recipes/middleware/middleware/body.mjs +15 -0
- package/recipes/middleware/middleware/bucket.mjs +19 -0
- package/recipes/middleware/middleware/cors.mjs +21 -0
- package/recipes/middleware/middleware/debug.mjs +13 -0
- package/recipes/middleware/middleware/envelope.mjs +11 -0
- package/recipes/middleware/middleware/errors.mjs +11 -0
- package/recipes/middleware/middleware/etag.mjs +18 -0
- package/recipes/middleware/middleware/locale.mjs +16 -0
- package/recipes/middleware/middleware/maintenance.mjs +10 -0
- package/recipes/middleware/middleware/methods.mjs +15 -0
- package/recipes/middleware/middleware/negotiate.mjs +20 -0
- package/recipes/middleware/middleware/referer.mjs +12 -0
- package/recipes/middleware/middleware/request-id.mjs +16 -0
- package/recipes/middleware/public/guide.txt +1 -0
- package/recipes/middleware/recipe.yaml +50 -0
- package/recipes/middleware/tests/requests.json +528 -0
- package/recipes/middleware/urlcode.yaml +127 -0
- package/recipes/protected-download/README.md +22 -0
- package/recipes/protected-download/files/report.txt +1 -0
- package/recipes/protected-download/recipe.yaml +31 -0
- package/recipes/protected-download/tests/requests.json +32 -0
- package/recipes/protected-download/urlcode.yaml +15 -0
- package/recipes/redirect/README.md +7 -0
- package/recipes/redirect/recipe.yaml +25 -0
- package/recipes/redirect/tests/requests.json +19 -0
- package/recipes/redirect/urlcode.yaml +9 -0
- package/recipes/static-plus-api/README.md +15 -0
- package/recipes/static-plus-api/functions/info.mjs +3 -0
- package/recipes/static-plus-api/public/assets/index.html +3 -0
- package/recipes/static-plus-api/public/assets/site.css +1 -0
- package/recipes/static-plus-api/public/index.html +8 -0
- package/recipes/static-plus-api/recipe.yaml +29 -0
- package/recipes/static-plus-api/tests/requests.json +56 -0
- package/recipes/static-plus-api/urlcode.yaml +23 -0
- package/recipes/typescript/README.md +7 -0
- package/recipes/typescript/functions/hello.ts +5 -0
- package/recipes/typescript/recipe.yaml +23 -0
- package/recipes/typescript/tests/requests.json +18 -0
- package/recipes/typescript/urlcode.yaml +5 -0
- package/recipes/webhook-receiver/README.md +16 -0
- package/recipes/webhook-receiver/functions/receive.mjs +16 -0
- package/recipes/webhook-receiver/recipe.yaml +26 -0
- package/recipes/webhook-receiver/tests/requests.json +59 -0
- package/recipes/webhook-receiver/urlcode.yaml +16 -0
- package/schemas/recipe.schema.json +138 -0
- package/schemas/urlcode.schema.json +656 -80
- package/skills/urlcode/SKILL.md +98 -0
- package/starters/default/.github/workflows/urlcode.yml +23 -0
- package/starters/default/.mcp.json +12 -0
- package/starters/default/AGENTS.md +79 -0
package/dist/BUILD-MANIFEST.json
CHANGED
|
@@ -1,60 +1,90 @@
|
|
|
1
1
|
{
|
|
2
|
-
"node": "v26.
|
|
2
|
+
"node": "v26.9.0",
|
|
3
3
|
"files": {
|
|
4
|
-
"dist/adapters.js": "
|
|
5
|
-
"dist/agent-lists.js": "
|
|
4
|
+
"dist/adapters.js": "a7153ec52f2ed7e0cdd8ed7d433504815f402ec53b2b1c3d38d0cf0e2fcf6509",
|
|
5
|
+
"dist/agent-lists.js": "35ab484198897501d011cb6cc00b5a6787192e19df29c97646e8c118fcc19eef",
|
|
6
|
+
"dist/agents-guide.js": "9cecc60690fe91e1f09a5298273c1d918428f114b5abb11f40f37f341668309c",
|
|
6
7
|
"dist/assets.js": "0833b093d2fe457ce68281110dc07d47914992753607741c13b339d92c76cf5c",
|
|
7
|
-
"dist/authoring.js": "
|
|
8
|
-
"dist/
|
|
9
|
-
"dist/
|
|
10
|
-
"dist/
|
|
11
|
-
"dist/
|
|
8
|
+
"dist/authoring-files.js": "ad32814f9ae9c549c6247396f982aa700d13a293cc0a589609eccc68f8965550",
|
|
9
|
+
"dist/authoring.js": "ec5240e8686c124f4601229b45f89ce112d9eeb9d35e3059fe55e93056c45209",
|
|
10
|
+
"dist/aws.js": "7d8e3a97b4f6dbefbd68da058f05192469d1efcaed5458b284863ebe462e060e",
|
|
11
|
+
"dist/build-cloudflare.js": "af4f49ad45287d7c4105bb84b1592b5b8e76c930f7159505338298f7c5fd5651",
|
|
12
|
+
"dist/bulk.js": "aac88d422bd9a7a341a421fb4e29ff5580b28d39250b7f1f5315ba20ae92da8a",
|
|
13
|
+
"dist/capabilities.js": "c1e28c7de676c3b43c154d6f767749a1b34df78a64c58b5c23ad95339f964608",
|
|
14
|
+
"dist/capability-query.js": "850525d542aeeaeb4f89397ac57c6f89daad3fe3fa02ecb0332ea9f75d140b32",
|
|
15
|
+
"dist/catalog.js": "ab1c01c9296cc277d2bd4fd682aeb053656a7d9f91c61974f4b78feea0211de8",
|
|
16
|
+
"dist/cli.js": "4cba007ed3666fdfdf9fc676de1e346ab8196e3907dc2541eeb3e59842d9891a",
|
|
17
|
+
"dist/client-address.js": "9d0d01466aab23124330605c5a0e0f981f87c897858acfad909f546a63df165b",
|
|
12
18
|
"dist/cloudflare.js": "17b43b0a6b6a0ef8a893415c989e4ae3976d97cc966adbf897b785f9adc472e3",
|
|
13
|
-
"dist/compliance-rules/baseline.js": "
|
|
14
|
-
"dist/compliance-rules/privacy.js": "
|
|
19
|
+
"dist/compliance-rules/baseline.js": "0a0c03d932f30797c4837c78c6b64ca6bb88f2ca947eb7f6adf5fdcdd280616d",
|
|
20
|
+
"dist/compliance-rules/privacy.js": "0e4d12106cf777299a7d30451f53c7b996f202fe53d7e1047b69f5df2a74a53d",
|
|
15
21
|
"dist/compliance-rules/shared.js": "595a7ee3a5af8c52197c5c9cbf09f4289a234e52b7a198afdd498be9be8d28a1",
|
|
16
|
-
"dist/compliance-rules/strict.js": "
|
|
22
|
+
"dist/compliance-rules/strict.js": "73ee13c2f893acf20cc3d44bf054e58c1474dec52eafe0cf2ce7f4eb96a3bc53",
|
|
17
23
|
"dist/compliance.js": "e956dc89b0b729fed7031297b8d7554141110334e670edf5cedc3d052a8fb3e4",
|
|
24
|
+
"dist/conditions.js": "ff25e97da550a3bdd80af55522045669438aa31a77d2bc83ad602bcefdee0475",
|
|
18
25
|
"dist/config-worker.js": "bc2170d60c35f8d5de227cbfc4c5067dc61d7cbc5b98aed88e68a11797072da5",
|
|
19
|
-
"dist/config.js": "
|
|
26
|
+
"dist/config.js": "8efc2cfc24e9a958770d73aa8464d18c81d7a9a1d2398398cd9cc2776e639127",
|
|
27
|
+
"dist/context.js": "a6b0278b4fd478175f43b1ef5ae640ce6e0782c906c6fd2c7d1aebaf5a31c918",
|
|
28
|
+
"dist/ecosystem-cli.js": "1e71bacd53d6fa8c7857cfcce3c3012ce054771a434b78d1f39e892e32642edd",
|
|
29
|
+
"dist/egress.js": "2ae29fe2cb4590fd2f715abe6817db47fed2f50dd31f37946ecf42eafbb0dd9e",
|
|
20
30
|
"dist/errors.js": "a908e66496afebbdd632a8c159a6e14d23f8f38798a0b4342ca122f2511c6cde",
|
|
21
|
-
"dist/
|
|
31
|
+
"dist/examples.js": "8de9917a82fb04e44a3182d57c6a95cc730feb8b22a37d54b9b3c4177aa83111",
|
|
32
|
+
"dist/explain-cli.js": "c5414e9627f428f0d8efa4e4f3f89951ea10a6b3fe1d7f633e48f71a792406d2",
|
|
33
|
+
"dist/explain.js": "5dd271b699c9b852fbaa4db271d9a370fe98fca43b1d0ac018de0c0b047bf7b8",
|
|
34
|
+
"dist/extensions.js": "7402ff86017fca83a0e08a50b402bc428056566d63511aa84d609e252dc456e8",
|
|
35
|
+
"dist/function-sources.js": "f6e8bdd9d4ef728b44c6e1f08c601b11fc4ad3e0c104dacf4fea0b71874ea4e7",
|
|
22
36
|
"dist/function-worker.js": "3f5bad4f1b5cb812924c2dcc73ece6f816cf6aac26cd471fd1030dcfbf009c3b",
|
|
23
37
|
"dist/functions.js": "6b1e5d4a3f8db17d4e5df261b98ed15f5f0c5e5507a6fc0f472e9f94ed2b6090",
|
|
24
38
|
"dist/guest-api.js": "bc2501496a6ef9fd20dddb606fbc6fd557d534dd075e7ad38406248b230013ed",
|
|
25
39
|
"dist/header-validation.js": "465181dbb08ff05f52defdd29fda025c0c64589bf319fa87fa6d3ab4b68216d5",
|
|
26
40
|
"dist/http-policy.js": "4cb187642269078ddf3460a3f1813dc57878a616a6f8132ef8f8d3b4b91ebb56",
|
|
27
41
|
"dist/http-response.js": "5fc3bb9eb932a3fd2fbc72c361416a5f1439b8bf45b2be37baca1c6446abf40c",
|
|
28
|
-
"dist/index.js": "
|
|
42
|
+
"dist/index.js": "53648d88b0db7d9168d2f212ea4a28b7fd3ead6238c99c0b8d7d41536274d6d4",
|
|
43
|
+
"dist/init-with.js": "8371f568867ebdc6ab8e9aa762234ae2aa015865f46aa901254528e20d69b791",
|
|
44
|
+
"dist/interchange-cli.js": "35bd70ba8077af5c3e39404ff0e5d28707632090a59a90645141252449fd3f04",
|
|
45
|
+
"dist/interchange.js": "26789420af33344d9a08c00fe6b2708aa71994224df527b3075295be2151611e",
|
|
29
46
|
"dist/link-api.js": "0d1f2fb5ef8cd6fda7b071d3e08c53eb4b1c01d4003167af2f400949b70dea4f",
|
|
30
|
-
"dist/link-cli.js": "
|
|
47
|
+
"dist/link-cli.js": "c4e2121a3e66f33c640832a7cb362a6a1db8b6d91d55a4239ce38ba0ced67b22",
|
|
31
48
|
"dist/link-events.js": "502a6038a538fa43094a9ba9c7546f504b4a1832a1377f26ca8cb69c2326670e",
|
|
32
49
|
"dist/link-records.js": "ef67a58cd107db0c3ac1c0ffd7b32817553606cf69bb3002da4ca0138c272f69",
|
|
33
50
|
"dist/link-store-worker.js": "0080452bbada2154b923449cd14596579bde94ad5f8dab94ecc84aa0d59c089b",
|
|
34
51
|
"dist/link-store.js": "526cdbe1b917cc7a74fb6edbbf13717d823ace5b5d6a5f89bc91438056a10b37",
|
|
35
52
|
"dist/logging.js": "8ec57fea26983aa071b05fe15d680d6550b03488101163ed9666da674118cf31",
|
|
36
|
-
"dist/management-policy.js": "
|
|
37
|
-
"dist/
|
|
38
|
-
"dist/
|
|
39
|
-
"dist/
|
|
40
|
-
"dist/
|
|
53
|
+
"dist/management-policy.js": "bd5563da52c53ace71b01daed0d2a492baeb3f26f5ec5ee1b0981c2b88df9ffa",
|
|
54
|
+
"dist/manifest.js": "d4f58f936febbabf09ec1706baae7c1cb186dcd8a3d29b5725dad5b6eaf43a3f",
|
|
55
|
+
"dist/match.js": "53ebcc2cda529a8d07fb83f8cb69a1446036ffc1641af3c4bd45a55851bded28",
|
|
56
|
+
"dist/mcp-authoring.js": "5030f52ef9c7ebc7b97305fcce687eb0a0d6164e34fda87f8278135a1e6f3d65",
|
|
57
|
+
"dist/mcp.js": "ac96c5a094d7cc88cf16d1d1e3c23f45773729fe28855f921581badb2b95eb89",
|
|
58
|
+
"dist/observability.js": "13a22b9e34cf8da3739856eeada8522fb6c43765386cae07c6aa0981447fcb83",
|
|
59
|
+
"dist/operator-host.js": "e3dac9d43a83beb775202b4ab9eeeba7ac63cebfc5dcc669be38d825be587bd0",
|
|
60
|
+
"dist/plugins.js": "a61aa933cd9e1b41020b86fae78aa3a7f45f5313124aa11b50cb57898722385e",
|
|
61
|
+
"dist/policies/agents.js": "c1dbc1e90339f472eeeb2372f7f4637f59a5d210797ea680ac8120a02aa20c10",
|
|
41
62
|
"dist/policies/cache.js": "ef16d7e592526c29f865b2693faa2c8afbea41c6526687563dffcb13a77fc1f7",
|
|
42
|
-
"dist/policies/compression.js": "
|
|
43
|
-
"dist/policies/security.js": "
|
|
63
|
+
"dist/policies/compression.js": "800f3ae3b1a4c1fe58c3d9908364ea9d78f655ff50c7f7589f584378e7f194b0",
|
|
64
|
+
"dist/policies/security.js": "2b3bfdf82140156fea4b162adc28ee43ccd85c402fb200680dbb8d8706417420",
|
|
44
65
|
"dist/policies/throttle.js": "bbb0cb1c24cf70d0a1ac32fc0618efb6c44e5b5d42564842f9c585ff7e501603",
|
|
45
|
-
"dist/policies.js": "
|
|
46
|
-
"dist/policy.js": "
|
|
47
|
-
"dist/prerender.js": "
|
|
48
|
-
"dist/project-tests.js": "
|
|
49
|
-
"dist/
|
|
50
|
-
"dist/
|
|
51
|
-
"dist/
|
|
66
|
+
"dist/policies.js": "23fa019b7bf1cdedcc5f7772d2f157e4b381a554bce9e84594c2be4a0f8f76b8",
|
|
67
|
+
"dist/policy.js": "8285ed144ba42fd34e926e526cd4dcf60d5ab3668adf4f0b797f074ebd5243ce",
|
|
68
|
+
"dist/prerender.js": "0386ea2411e00b9563b5349133f1d723947b01f837fa92d4c61a699c9cfb5cdb",
|
|
69
|
+
"dist/project-tests.js": "225761d36bbe7e185c49c10c0334e579caf7d98647c9941faa4b0ea6406522fa",
|
|
70
|
+
"dist/provider-verification.js": "ffcf9f05e8cb5f71ea46a97e279e8a613fdfdf9435ab02bd57af11e2680a9107",
|
|
71
|
+
"dist/proxy.js": "34107e59ac0dbbea090efa3cf5badf3226c5302ba25e8f8ff9b2b5596ed80e50",
|
|
72
|
+
"dist/readiness.js": "d419b09a83dc8e6790be7c91ba4e1a2a5cf9b141577c98bd24e99a3609553649",
|
|
73
|
+
"dist/recipes.js": "11853f23e63c3c65c5bed03a278cde0349d28c9fa23266c9907a2df318bb5fc3",
|
|
74
|
+
"dist/route-diff.js": "eebac076a886ddfb2bf5b97ea09d81f888e7bb0063d482eddb8e5fef9acea107",
|
|
75
|
+
"dist/router.js": "4315585232561c1737e579a2cbd990596d337b37565dd449bcb1bbaa6abbfb13",
|
|
76
|
+
"dist/runtime.js": "f6f1bfa320a427423d66be845de3368552b1f4cca4a28136b913ac26fb9d6169",
|
|
52
77
|
"dist/scaffold.js": "9dd30112e070ec554bd7cae1ca0a8b03642632be57411ba76a72972f4ba49b3e",
|
|
78
|
+
"dist/schema-query.js": "bfd1844acd8d54ac361115191fcfbaf828a67e223b9ec6e9c22f158761af149b",
|
|
53
79
|
"dist/server.js": "d8c78d1695b3c11328f3f983281fba78c2aca6a66cf755b39ecf4ec2ec4b6f29",
|
|
54
|
-
"dist/
|
|
80
|
+
"dist/signals.js": "b55e54efc8fb6703e08f2a1e808ec8e011bda67738db8ceadf1b248f695795be",
|
|
81
|
+
"dist/site.js": "c40a06a6f9e2d6d3bea94727783c115fed4309bb0190787f58434eed64cbde84",
|
|
55
82
|
"dist/sqlite-version.js": "a3a08d99064bd0f35847e288027e00a516efdd61c675bfbbe7726e3aa900f0d1",
|
|
56
|
-
"dist/
|
|
57
|
-
"dist/
|
|
83
|
+
"dist/tooling.js": "eaf9aa49df17b5ab3bc538976b2849fac52b5ca779b6e814fd7ca592ecd757b7",
|
|
84
|
+
"dist/types.js": "8579202bf322e542969bbd9e5b98774963b12ac69bdf362eebfcb068de2d5421",
|
|
85
|
+
"dist/typescript-authoring.js": "156c617c2cbf992c299dbbbd5398500f0f30d1c90df8630509036da4ffd7cae9",
|
|
86
|
+
"dist/vercel.js": "a0da20c095d0c7fa8f579ed4dd5951e7a34191f8a72a57c5e782c9eab39f6f08",
|
|
87
|
+
"dist/verify-deployment.js": "cac5d10ea18ae5f699df0eb0a5229837297c7627b47e65140f053820cae2414d",
|
|
58
88
|
"dist/scripts/operational-drills.js": "b7e9448279c59ee9de62023055a9ff5c7a60bcceed4c33d023edc612f5575af9"
|
|
59
89
|
}
|
|
60
90
|
}
|
package/dist/adapters.js
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
|
+
|
|
1
2
|
import { createRuntime } from './runtime.js';
|
|
2
3
|
|
|
3
4
|
import { validatePolicy } from './policy.js';
|
|
4
5
|
import { ConfigError } from './errors.js';
|
|
5
|
-
|
|
6
6
|
|
|
7
7
|
/** The subset of process.env a hosted adapter reads. */
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Handlers a stateless per-request invocation cannot honour. Functions and
|
|
12
|
-
// middleware need worker threads and the WASM engine on every cold start;
|
|
13
|
-
// stored links need a durable writable file that instances share. Adapters
|
|
14
|
-
// refuse them identically, so a project's supported surface does not depend on
|
|
15
|
-
// which provider is serving it.
|
|
16
|
-
const unsupported = { function:'isolated functions', link:'stored live links' };
|
|
9
|
+
|
|
17
10
|
|
|
18
11
|
export function readPolicyFromEnvironment(environment ) {
|
|
19
12
|
if (!environment.URLCODE_POLICY) return undefined;
|
|
@@ -27,20 +20,8 @@ export function readPolicyFromEnvironment(environment )
|
|
|
27
20
|
|
|
28
21
|
// Activates a project for a native-handler-only host, refusing the whole
|
|
29
22
|
// deployment rather than letting individual routes fail at request time.
|
|
30
|
-
export async function activateNativeOnly(project , environment , { target
|
|
31
|
-
|
|
32
|
-
const refused = runtime.testPlan().inventory.flatMap(route => {
|
|
33
|
-
const reason = route.handler === undefined ? undefined : unsupported[route.handler];
|
|
34
|
-
return [
|
|
35
|
-
...(reason ? [`${route.path} uses ${reason}`] : []),
|
|
36
|
-
...(route.middleware ? [`${route.path} declares middleware`] : []),
|
|
37
|
-
];
|
|
38
|
-
});
|
|
39
|
-
if (refused.length) {
|
|
40
|
-
await runtime.close();
|
|
41
|
-
throw new ConfigError(`This adapter serves native handlers only: ${refused.join('; ')}`);
|
|
42
|
-
}
|
|
43
|
-
return runtime;
|
|
23
|
+
export async function activateNativeOnly(project , environment , { target, plugins, extensions, origin } ) {
|
|
24
|
+
return createRuntime(project, { permissions: readPolicyFromEnvironment(environment), environment, target, plugins, extensions, origin });
|
|
44
25
|
}
|
|
45
26
|
|
|
46
27
|
// Caches a successful activation for the life of the instance. A failure is not
|
package/dist/agent-lists.js
CHANGED
|
@@ -10,7 +10,7 @@ import { isListFile, isBundled, validatePattern } from './policies/agents.js';
|
|
|
10
10
|
//
|
|
11
11
|
// A list file is the schema data/agents/*.json uses: either an array of
|
|
12
12
|
// entries or `{ entries: [...] }`, each entry `{ name?, pattern, ... }`.
|
|
13
|
-
|
|
13
|
+
const MAX_LIST_ENTRIES = 4096;
|
|
14
14
|
|
|
15
15
|
function listPath(root , reference , routePattern ) {
|
|
16
16
|
assert(isListFile(reference) && !isAbsolute(reference), `${routePattern}: policies.agents list ${JSON.stringify(reference)} must be a project-relative path ending in .json`);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { getCapabilities } from './capabilities.js';
|
|
2
|
+
|
|
3
|
+
import { registry } from './policies.js';
|
|
4
|
+
import { generatedPaths } from './site.js';
|
|
5
|
+
import { assert } from './errors.js';
|
|
6
|
+
|
|
7
|
+
/** Where the packaged agent skill lives, relative to the installed @jimhoyd/urlcode package. */
|
|
8
|
+
export const skillPath = 'skills/urlcode/SKILL.md';
|
|
9
|
+
/** The MCP registration file `urlcode init` writes beside the project (Claude Code and Codex read this shape). */
|
|
10
|
+
export const mcpConfigFile = '.mcp.json';
|
|
11
|
+
/**
|
|
12
|
+
* Renders `.mcp.json` registering the read-only `urlcode mcp` server for the project at `project`, relative
|
|
13
|
+
* to the file. `--allow-authoring` is deliberately absent: the operator adds it by hand when they want it.
|
|
14
|
+
*/
|
|
15
|
+
export function renderMcpConfig(project = '.') {
|
|
16
|
+
assert(/^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*$/.test(project) && !project.split('/').includes('..'), 'MCP project path must be a relative path without ..');
|
|
17
|
+
return JSON.stringify({ mcpServers: { urlcode: { command: 'urlcode', args: ['mcp', '--project', project] } } }, null, 2) + '\n';
|
|
18
|
+
}
|
|
19
|
+
const handlerNames = ['redirect','respond','page','static','download','function','link','proxy','conditional','extension'];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The application-level AGENTS.md written by `urlcode init`. Built from the
|
|
23
|
+
* installed runtime's capability catalog, so it names only the handlers,
|
|
24
|
+
* policies and site keys this version implements. Under 80 lines by design.
|
|
25
|
+
*/
|
|
26
|
+
export function renderAgentsGuide({ routes } ) {
|
|
27
|
+
assert(Number.isInteger(routes) && routes >= 0 && routes <= 100000, 'Route count must be a non-negative integer');
|
|
28
|
+
const catalog = getCapabilities('self-hosted');
|
|
29
|
+
const native = new Set(catalog.capabilities.filter(row => row.targets['self-hosted']?.support === 'native').map(row => row.capability));
|
|
30
|
+
const handlers = handlerNames.filter(name => native.has(name));
|
|
31
|
+
const policies = Object.keys(registry).filter(name => native.has(`policies.${name}` ));
|
|
32
|
+
const site = Object.entries(generatedPaths).map(([key, path]) => `\`${key}\` (${path})`);
|
|
33
|
+
return `# Working on this project
|
|
34
|
+
|
|
35
|
+
This project uses URLCode: URL behavior is declared in \`urlcode.yaml\`, and the
|
|
36
|
+
installed \`@jimhoyd/urlcode\` runtime serves it. There is no framework code to
|
|
37
|
+
write for routing, validation, middleware wiring, policies, static serving or
|
|
38
|
+
authentication; the runtime provides them. Read this file before changing anything.
|
|
39
|
+
|
|
40
|
+
## Before writing code
|
|
41
|
+
|
|
42
|
+
1. Inspect \`urlcode.yaml\` first, then every file its \`includes\` list names,
|
|
43
|
+
the referenced functions, middleware and \`tests/requests.json\`. Preserve the
|
|
44
|
+
existing organization and every route you were not asked to change.
|
|
45
|
+
2. Run \`urlcode capabilities\` to see what this runtime version implements and
|
|
46
|
+
which targets support it; \`urlcode capabilities --target NAME\` before
|
|
47
|
+
promising any provider deployment.
|
|
48
|
+
3. Run \`urlcode recipes list\` and \`urlcode recipes show NAME\` before writing a
|
|
49
|
+
route from scratch. If a recipe covers the need, add it with
|
|
50
|
+
\`urlcode recipes add NAME --out DIR\` and adapt the copy.
|
|
51
|
+
4. Prefer YAML over code. Prefer native handlers over functions.
|
|
52
|
+
|
|
53
|
+
## Ask the runtime through MCP first
|
|
54
|
+
|
|
55
|
+
\`${mcpConfigFile}\` registers the read-only \`urlcode mcp\` server. When it is
|
|
56
|
+
available, prefer its tools over reading documents: \`get_context\`,
|
|
57
|
+
\`get_capability\`, \`get_schema\`, \`search_recipes\`, \`explain\`, \`get_manifest\`.
|
|
58
|
+
The CLI equivalents are the fallback: \`urlcode context\`, \`urlcode capabilities NAME\`,
|
|
59
|
+
\`urlcode schema PATH\`, \`urlcode recipes search TEXT\`, \`urlcode explain PATH\`,
|
|
60
|
+
\`urlcode manifest\`. \`--allow-authoring\` is an operator opt-in; never add it yourself.
|
|
61
|
+
|
|
62
|
+
## What the runtime provides (this version)
|
|
63
|
+
|
|
64
|
+
- Handlers, exactly one per route: ${handlers.map(name => `\`${name}\``).join(', ')}.
|
|
65
|
+
- Ordered \`middleware\` around any handler, declared in YAML, run in the sandbox.
|
|
66
|
+
- Validated inputs: \`parameters\`, \`request.body\` and \`methods\` on the route;
|
|
67
|
+
functions receive validated \`args\`, never raw user input.
|
|
68
|
+
- Policies, host-enforced and off by default: ${policies.map(name => `\`${name}\``).join(', ')}.
|
|
69
|
+
- Site conventions under \`site\`, each generating one native route: ${site.join(', ')}.
|
|
70
|
+
- Bindings: named \`env\` and \`secrets\` references resolved by the operator, never values in YAML.
|
|
71
|
+
|
|
72
|
+
Never recreate any of these in a function. If a requirement seems to need one
|
|
73
|
+
of them and it is missing, that is a report, not an invitation to reimplement.
|
|
74
|
+
|
|
75
|
+
## Functions and middleware are sandboxed
|
|
76
|
+
|
|
77
|
+
Guest code runs in an isolated JavaScript engine with a fresh heap per call.
|
|
78
|
+
It sees a text/JSON \`Request\`/\`Response\` subset, validated \`args\` and granted
|
|
79
|
+
\`env\`. There is no \`fetch\`, no Node API, no filesystem, no timers and no
|
|
80
|
+
imports outside the project. Do not write code that needs them; declare a
|
|
81
|
+
\`proxy\` route or a binding instead and say why.
|
|
82
|
+
|
|
83
|
+
## Checks that count as evidence
|
|
84
|
+
|
|
85
|
+
\`\`\`sh
|
|
86
|
+
urlcode validate --local
|
|
87
|
+
urlcode test
|
|
88
|
+
urlcode audit --expect-routes ${routes}
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
Run all three after every change. Update the expected route count deliberately
|
|
92
|
+
when you add or remove a route, and add fixtures to \`tests/requests.json\` for
|
|
93
|
+
every new route (positive and negative cases, every active method, HEAD).
|
|
94
|
+
Without a global install, invoke \`node /path/to/urlcode/src/cli.ts\` instead of \`urlcode\`.
|
|
95
|
+
|
|
96
|
+
## Rules
|
|
97
|
+
|
|
98
|
+
- Report unsupported requirements instead of inventing fields. The schema is
|
|
99
|
+
exact; a field the validator rejects does not exist. Say what is missing.
|
|
100
|
+
- Never create or approve operator grants. Request a named binding in YAML and
|
|
101
|
+
stop; the operator grants it outside this project, pinned to the revision.
|
|
102
|
+
- Secrets stay out of the project: no keys, tokens or credentials in YAML,
|
|
103
|
+
functions, fixtures, \`.env\` files that are not ignored, or commit messages.
|
|
104
|
+
- Authentication is host processing: declare \`auth\` on the route, never build
|
|
105
|
+
login forms, sessions or password checks in functions.
|
|
106
|
+
- Validation, tests and the audit are the evidence. Local checks are not a
|
|
107
|
+
deployment, a soak test or a security review; do not claim otherwise.
|
|
108
|
+
|
|
109
|
+
The installed package ships an agent skill with the same loop at
|
|
110
|
+
\`${skillPath}\` inside \`@jimhoyd/urlcode\` (for example
|
|
111
|
+
\`node_modules/@jimhoyd/urlcode/${skillPath}\`).
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {lstat,realpath,open,mkdir,rm,rename} from 'node:fs/promises';
|
|
2
|
+
import {resolve,join,dirname,basename,parse} from 'node:path';
|
|
3
|
+
import {assert} from './errors.js';
|
|
4
|
+
|
|
5
|
+
/** Authoring output never copies hidden state, package hooks, or credential files. */
|
|
6
|
+
export function authoringPath(path ) {
|
|
7
|
+
const parts=path.split('/');
|
|
8
|
+
assert(path.length>0 && path.length<=1024 && parts.length<=32 && parts.every(part=>
|
|
9
|
+
part && !part.startsWith('.') && !/[. ]$/.test(part) && !/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part) && !/[\\:*?"<>|\u0000-\u001f\u007f]/u.test(part) &&
|
|
10
|
+
!/^(?:node_modules|package(?:-lock)?\.json|.*\.(?:pem|key|p12|pfx|env))$/i.test(part)), 'Authoring paths must be safe non-sensitive project-relative paths');
|
|
11
|
+
return path;
|
|
12
|
+
}
|
|
13
|
+
export async function authoringFile(root ,path ,directory=false) {
|
|
14
|
+
authoringPath(path);let file=root;
|
|
15
|
+
for(const [index,part] of path.split('/').entries()){
|
|
16
|
+
file=join(file,part);const info=await lstat(file);
|
|
17
|
+
assert(!info.isSymbolicLink(),'Authoring through symlinks is forbidden');
|
|
18
|
+
assert(index<path.split('/').length-1 || directory ? info.isDirectory() : info.isFile() && info.nlink===1,'Authoring requires ordinary files and directories');
|
|
19
|
+
}
|
|
20
|
+
return file;
|
|
21
|
+
}
|
|
22
|
+
export async function readAuthoringFile(root ,path ,limit ) {
|
|
23
|
+
const file=await authoringFile(root,path),handle=await open(file,'r');
|
|
24
|
+
try {
|
|
25
|
+
const info=await handle.stat();assert(info.isFile() && info.nlink===1 && info.size<=limit,'Authoring source size limit exceeded');
|
|
26
|
+
const bytes=Buffer.alloc(info.size+1);let offset=0;
|
|
27
|
+
while(offset<bytes.length){const read=await handle.read(bytes,offset,bytes.length-offset,null);if(!read.bytesRead)break;offset+=read.bytesRead;}
|
|
28
|
+
assert(offset<=info.size,'Authoring source changed during read');return bytes.subarray(0,offset);
|
|
29
|
+
}finally{await handle.close();}
|
|
30
|
+
}
|
|
31
|
+
/** Reserve a fresh directory exclusively, then publish the entry config last.
|
|
32
|
+
* Failed writes remove only the directory created by this invocation. No existing
|
|
33
|
+
* directory (even an empty one) is accepted; consumers see no activatable project
|
|
34
|
+
* until every dependency has been written. Callers must own the output parent.
|
|
35
|
+
*/
|
|
36
|
+
export async function publishAuthoringProject(output ,files ,dryRun=false) {
|
|
37
|
+
assert(files.has('urlcode.yaml'),'Authoring output requires urlcode.yaml');
|
|
38
|
+
assert(files.size<=10000,'Authoring file limit exceeded');
|
|
39
|
+
const paths=new Set ();
|
|
40
|
+
for(const path of files.keys()){
|
|
41
|
+
authoringPath(path);const key=path.toLowerCase();assert(!paths.has(key),'Conflicting authoring output paths');paths.add(key);
|
|
42
|
+
}
|
|
43
|
+
for(const path of paths){let parent=dirname(path);while(parent!=='.'){assert(!paths.has(parent),'Authoring file/directory conflict');parent=dirname(parent);}}
|
|
44
|
+
const target=resolve(output),parent=dirname(target);assert(target!==parse(target).root,'Invalid authoring output');
|
|
45
|
+
assert(!(await lstat(parent)).isSymbolicLink(),'Authoring output parent must not be a symlink');
|
|
46
|
+
const destination=join(await realpath(parent),basename(target));
|
|
47
|
+
let exists=false;try{await lstat(destination);exists=true;}catch(error){if(!(error instanceof Error && 'code' in error && error.code==='ENOENT'))throw error;}
|
|
48
|
+
assert(!exists,'Authoring output already exists');
|
|
49
|
+
if(dryRun)return destination;
|
|
50
|
+
await mkdir(destination,{mode:0o700});
|
|
51
|
+
try {
|
|
52
|
+
const entries=[...files].sort(([a],[b])=>a==='urlcode.yaml'?1:b==='urlcode.yaml'?-1:a.localeCompare(b));
|
|
53
|
+
for(const [path,content] of entries){
|
|
54
|
+
const file=join(destination,path==='urlcode.yaml'?'.urlcode.yaml.pending':path);await mkdir(dirname(file),{recursive:true,mode:0o700});
|
|
55
|
+
const handle=await open(file,'wx',0o600);try{await handle.writeFile(content);await handle.sync();}finally{await handle.close();}
|
|
56
|
+
if(path==='urlcode.yaml')await rename(file,join(destination,'urlcode.yaml'));
|
|
57
|
+
}
|
|
58
|
+
return destination;
|
|
59
|
+
}catch(error){await rm(destination,{recursive:true,force:true});throw error;}
|
|
60
|
+
}
|
package/dist/authoring.js
CHANGED
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { randomBytes } from 'node:crypto';
|
|
5
5
|
import { parseDocument } from 'yaml';
|
|
6
6
|
import { loadDocument, validateDocument } from './config.js';
|
|
7
|
+
import { renderAgentsGuide, renderMcpConfig, mcpConfigFile } from './agents-guide.js';
|
|
7
8
|
import { compileRoutes } from './router.js';
|
|
8
9
|
import { prepareFunctionSnapshot, requestedPermissions } from './policy.js';
|
|
9
10
|
import { assert } from './errors.js';
|
|
@@ -17,9 +18,18 @@ export async function initProject(destination ) {
|
|
|
17
18
|
try {
|
|
18
19
|
const source = fileURLToPath(new URL('../starters/default/', import.meta.url));
|
|
19
20
|
for (const file of await readdir(source)) {
|
|
20
|
-
if (file === '.gitignore') continue;
|
|
21
|
+
if (file === '.gitignore' || file === 'AGENTS.md' || file === mcpConfigFile) continue;
|
|
21
22
|
await cp(join(source,file), join(target,file === 'gitignore.template' ? '.gitignore' : file), { recursive: true, force: false, errorOnExist: true });
|
|
22
23
|
}
|
|
24
|
+
// AGENTS.md is generated from the installed runtime's capability catalog so
|
|
25
|
+
// it names only what this version implements; the starter carries a
|
|
26
|
+
// committed copy for clones, kept identical by test.
|
|
27
|
+
const routes = Object.keys((await loadDocument(target)).routes).length;
|
|
28
|
+
const guide = await open(join(target,'AGENTS.md'), 'wx', 0o644);
|
|
29
|
+
try { await guide.writeFile(renderAgentsGuide({ routes })); } finally { await guide.close(); }
|
|
30
|
+
// .mcp.json registers the read-only server for repository-aware agents; the starter carries the same bytes.
|
|
31
|
+
const mcp = await open(join(target,mcpConfigFile), 'wx', 0o644);
|
|
32
|
+
try { await mcp.writeFile(renderMcpConfig('.')); } finally { await mcp.close(); }
|
|
23
33
|
} catch (error) { await rm(target, { recursive: true, force: true }); throw error; }
|
|
24
34
|
return target;
|
|
25
35
|
}
|
package/dist/aws.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { activateNativeOnly, lazyRuntime, resolveOrigin } from './adapters.js';
|
|
3
4
|
|
|
@@ -6,7 +7,7 @@ import { prepareResponse, errorResponse } from './http-response.js';
|
|
|
6
7
|
|
|
7
8
|
import { assert, ConfigError, HttpError } from './errors.js';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
/** A Lambda payload format 2.0 event, as far as this adapter reads it. */
|
|
11
12
|
|
|
12
13
|
|
|
@@ -64,9 +65,9 @@ function requestBody(event , limit ) {
|
|
|
64
65
|
// Builds a Lambda handler for payload format 2.0. The runtime is created once
|
|
65
66
|
// per execution environment and reused across warm invocations.
|
|
66
67
|
export function createLambdaHandler({ project = process.cwd(), origin, environment = process.env,
|
|
67
|
-
maxBodyBytes = 1048576, plugins } = {}) {
|
|
68
|
+
maxBodyBytes = 1048576, plugins, extensions } = {}) {
|
|
68
69
|
assert(Number.isInteger(maxBodyBytes) && maxBodyBytes >= 1 && maxBodyBytes <= 16777216, 'Request limit must be 1–16777216 bytes');
|
|
69
|
-
const ready = lazyRuntime(() => activateNativeOnly(project, environment, { target: 'aws', plugins }));
|
|
70
|
+
const ready = lazyRuntime(() => activateNativeOnly(project, environment, { target: 'aws', plugins, extensions, origin:resolveOrigin(origin,environment,platformOrigins) }));
|
|
70
71
|
|
|
71
72
|
return async function handler(raw) {
|
|
72
73
|
const requestId = randomUUID();
|
package/dist/build-cloudflare.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { analyzeProjectCapabilities, analyzeCompiledCapabilities, assertTargetCompatibility } from './capabilities.js';
|
|
1
2
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import Ajv from 'ajv/dist/2020.js';
|
|
@@ -8,23 +9,12 @@ import { assert } from './errors.js';
|
|
|
8
9
|
import { effectivePolicies, registry } from './policies.js';
|
|
9
10
|
import { resolveLists } from './agent-lists.js';
|
|
10
11
|
import { applySite } from './site.js';
|
|
12
|
+
import { buildManifest, renderManifest, manifestPath } from './manifest.js';
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Handlers this target cannot serve, and why. Declarative routes only in this
|
|
18
|
-
// slice: assets need a platform binding rather than an inline copy, and the
|
|
19
|
-
// sandbox needs facilities the platform does not provide.
|
|
20
|
-
const unsupported = {
|
|
21
|
-
function:'isolated functions need worker threads and the WASM engine',
|
|
22
|
-
link:'stored live links need a durable writable store',
|
|
23
|
-
page:'pages need a static-asset binding',
|
|
24
|
-
static:'static directories need a static-asset binding',
|
|
25
|
-
download:'downloads need a static-asset binding',
|
|
26
|
-
} ;
|
|
27
|
-
const unsupportedHandlers = ['function','link','page','static','download'] ;
|
|
17
|
+
|
|
28
18
|
|
|
29
19
|
// The artifact is this runtime's build output, not a published contract: the
|
|
30
20
|
// format may change with any release, and the runtime refuses a version it does
|
|
@@ -80,24 +70,21 @@ export async function buildCloudflare(project , { out = 'dist/cloudflare'
|
|
|
80
70
|
// Generated site routes are built like declared ones; the ones that need
|
|
81
71
|
// an origin get it from --origin, exactly as the server does.
|
|
82
72
|
await applySite(loaded, { origin, log });
|
|
73
|
+
assertTargetCompatibility(analyzeProjectCapabilities(loaded, 'cloudflare'));
|
|
83
74
|
// No bindings are resolved: a build artifact must never carry a secret, and
|
|
84
75
|
// this target has no per-request operator policy to pin one to.
|
|
85
76
|
const compiled = await compileRoutes(loaded, {}, {}, undefined);
|
|
86
77
|
const routes = [...compiled.exact.values(), ...[...compiled.byLength.values()].flat(), ...compiled.mounts];
|
|
87
78
|
|
|
88
|
-
|
|
79
|
+
assertTargetCompatibility(analyzeCompiledCapabilities(loaded.document, compiled, 'cloudflare'));
|
|
89
80
|
for (const route of routes) {
|
|
90
|
-
for (const handler of unsupportedHandlers) {
|
|
91
|
-
if (route[handler]) refused.push(`${route.pattern}: ${unsupported[handler]}`);
|
|
92
|
-
}
|
|
93
|
-
if (route.middleware?.length) refused.push(`${route.pattern}: middleware needs the sandbox`);
|
|
94
81
|
const policies = effectivePolicies(loaded.document, route);
|
|
95
82
|
for (const name of Object.keys(policies)) {
|
|
96
83
|
assert(isPolicyName(name), `Unknown policy "${name}"`);
|
|
97
84
|
const support = policyModule(name).targets(policies[name]).cloudflare;
|
|
98
85
|
// The platform provides it: accepted and dropped, never carried.
|
|
99
86
|
if (support === 'delegated') { delete policies[name]; continue; }
|
|
100
|
-
|
|
87
|
+
assert(compilablePolicies.has(name) && support === 'compiled', `${route.pattern}: policies.${name} cannot be compiled for this target`);
|
|
101
88
|
}
|
|
102
89
|
// Project-relative agent lists are read here, once, so the artifact
|
|
103
90
|
// carries the patterns and the Worker never needs a filesystem.
|
|
@@ -109,11 +96,7 @@ export async function buildCloudflare(project , { out = 'dist/cloudflare'
|
|
|
109
96
|
// evaluates a configuration the runtime would have rejected.
|
|
110
97
|
for (const name of Object.keys(policies)) if (isPolicyName(name) && compilablePolicies.has(name)) await policyModule(name).compile(policies[name], { route, shared: {}, target: 'cloudflare', document: loaded.document, root: loaded.root });
|
|
111
98
|
if (Object.keys(policies).length) route.compiledPolicies = policies; else delete route.compiledPolicies;
|
|
112
|
-
if (Object.keys(route.env).length || Object.keys(route.secrets).length) {
|
|
113
|
-
refused.push(`${route.pattern}: env and secret bindings would have to be baked into the artifact`);
|
|
114
|
-
}
|
|
115
99
|
}
|
|
116
|
-
assert(!refused.length, `This target serves declarative routes only:\n ${refused.join('\n ')}`);
|
|
117
100
|
assert(routes.length, 'No routes to build');
|
|
118
101
|
|
|
119
102
|
const ajv = new Ajv.default({ code:{ source:true, esm:true }, strict:false, allErrors:false });
|
|
@@ -159,6 +142,10 @@ import * as validators from './validators.js';
|
|
|
159
142
|
|
|
160
143
|
export default { fetch: createFetchHandler(artifact, validators) };
|
|
161
144
|
`);
|
|
145
|
+
// The semantic manifest travels with the artifact so a reviewer can read
|
|
146
|
+
// what was built without the project checkout (docs/TOOLING.md).
|
|
147
|
+
const manifest = manifestPath(out);
|
|
148
|
+
await writeFile(manifest, renderManifest(await buildManifest(project, origin === undefined ? {} : { origin })));
|
|
162
149
|
return { out, format:FORMAT, version:loaded.version, routes:serialised.length,
|
|
163
|
-
validators:Object.keys(validators).length };
|
|
150
|
+
validators:Object.keys(validators).length, manifest };
|
|
164
151
|
}
|
package/dist/bulk.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto';
|
|
2
|
+
import {stringify} from 'yaml';
|
|
3
|
+
import {importRoutes} from './interchange.js';
|
|
4
|
+
|
|
5
|
+
import {publishAuthoringProject} from './authoring-files.js';
|
|
6
|
+
import {assert} from './errors.js';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/** Import ordinary redirect rows into small, portable include files. There is no
|
|
15
|
+
* merge mode: duplicate rules and existing output directories are refused. */
|
|
16
|
+
export async function importBulkProject(text ,format ,output ,{dryRun=false,source='<input>'} ={}) {
|
|
17
|
+
assert(['csv','json','yaml'].includes(format),'Bulk input must be csv, json or yaml');
|
|
18
|
+
assert(source.length<=1024 && !/[\u0000-\u001f\u007f]/u.test(source),'Invalid bulk provenance source name');
|
|
19
|
+
const provenance={name:source,format,sha256:createHash('sha256').update(text).digest('hex')};
|
|
20
|
+
const converted=await importRoutes({text,format,source});
|
|
21
|
+
const report ={ok:converted.ok,dryRun,routeCount:converted.routeCount,diagnostics:converted.diagnostics,files:[],source:provenance};
|
|
22
|
+
if(!converted.ok || !converted.document)return report;
|
|
23
|
+
const files=new Map (),entries=Object.entries(converted.document.routes),includes =[];
|
|
24
|
+
// 100 includes at the 100,000-route cap; each parser AST stays small without
|
|
25
|
+
// changing the configuration worker heap, wall deadline or include limits.
|
|
26
|
+
for(let offset=0;offset<entries.length;offset+=1000){
|
|
27
|
+
const group=entries.slice(offset,offset+1000),path=`routes/redirects-${String(includes.length+1).padStart(3,'0')}.yaml`;
|
|
28
|
+
includes.push(path);files.set(path,stringify({version:'1',routes:Object.fromEntries(group)}));
|
|
29
|
+
report.files.push({path,routeCount:group.length,firstPath:group[0] [0],lastPath:group.at(-1) [0]});
|
|
30
|
+
}
|
|
31
|
+
files.set('urlcode.yaml',stringify({version:'1',...(includes.length?{includes}:{}),routes:{}}));
|
|
32
|
+
report.files.unshift({path:'urlcode.yaml',routeCount:0});
|
|
33
|
+
const metadata={version:1,source:provenance,routeCount:report.routeCount,files:report.files};
|
|
34
|
+
files.set('provenance.json',JSON.stringify(metadata,null,2)+'\n');report.files.push({path:'provenance.json',routeCount:0});
|
|
35
|
+
report.output=await publishAuthoringProject(output,files,dryRun);
|
|
36
|
+
return report;
|
|
37
|
+
}
|