@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/urlcode-authoring/SKILL.md +122 -0
- package/.claude/skills/urlcode-operations/SKILL.md +108 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/CONTRIBUTING.md +30 -2
- package/README.md +195 -255
- package/ROADMAP.md +143 -15
- package/SECURITY.md +31 -9
- package/dist/BUILD-MANIFEST.json +72 -47
- 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/build-static.js +134 -0
- package/dist/bulk.js +37 -0
- package/dist/capabilities.js +262 -0
- package/dist/capability-query.js +71 -0
- package/dist/catalog.js +105 -0
- package/dist/cli.js +165 -34
- package/dist/client-address.js +1 -1
- package/dist/compliance-rules/baseline.js +9 -17
- package/dist/compliance-rules/privacy.js +7 -18
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance-rules/strict.js +5 -5
- package/dist/compliance.js +6 -8
- package/dist/conditions.js +88 -0
- package/dist/config.js +69 -6
- package/dist/context.js +155 -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 +131 -0
- package/dist/extensions.js +231 -0
- package/dist/function-sources.js +49 -5
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +40 -6
- package/dist/init-with.js +165 -0
- package/dist/interchange-cli.js +42 -0
- package/dist/interchange.js +189 -0
- package/dist/manifest.js +109 -0
- package/dist/match.js +2 -2
- package/dist/mcp-authoring.js +147 -0
- package/dist/mcp.js +97 -0
- package/dist/observability.js +7 -21
- package/dist/operator-host.js +29 -0
- package/dist/plugins.js +12 -0
- package/dist/policies/agents.js +2 -2
- package/dist/policies/cache.js +8 -3
- package/dist/policies/compression.js +2 -1
- package/dist/policies/security.js +0 -0
- package/dist/policies.js +1 -1
- package/dist/policy.js +56 -15
- 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 +34 -11
- package/dist/recipes.js +41 -0
- package/dist/route-diff.js +106 -0
- package/dist/router.js +45 -7
- package/dist/runtime.js +164 -64
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/schema-query.js +62 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/signals.js +24 -0
- package/dist/site.js +0 -0
- package/dist/tooling.js +96 -0
- package/dist/trusted-functions.js +210 -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/build-static.d.ts +43 -0
- package/dist/types/bulk.d.ts +27 -0
- package/dist/types/capabilities.d.ts +64 -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/shared.d.ts +0 -2
- package/dist/types/compliance-rules/strict.d.ts +0 -5
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/conditions.d.ts +19 -0
- package/dist/types/config.d.ts +21 -2
- package/dist/types/context.d.ts +66 -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 +177 -0
- package/dist/types/function-sources.d.ts +9 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +36 -6
- 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/manifest.d.ts +79 -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 +3 -14
- 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 -2
- package/dist/types/provider-verification.d.ts +53 -0
- package/dist/types/proxy.d.ts +21 -0
- package/dist/types/readiness.d.ts +10 -3
- package/dist/types/recipes.d.ts +30 -0
- package/dist/types/route-diff.d.ts +27 -0
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +11 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/schema-query.d.ts +12 -0
- package/dist/types/server.d.ts +1 -4
- 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/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +71 -7
- 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 +37 -5
- package/dist/typescript-authoring.js +142 -0
- package/dist/vercel.js +4 -3
- package/dist/verify-deployment.js +270 -0
- package/docs/AI-AUTHORING.md +232 -15
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +3 -2
- package/docs/BULK.md +79 -0
- package/docs/CAPABILITIES.md +192 -0
- package/docs/CAPACITY.md +129 -32
- package/docs/CI.md +142 -0
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/COMPLIANCE.md +6 -9
- package/docs/CONDITIONS.md +74 -0
- package/docs/DEPLOYMENT-CHECKS.md +108 -0
- package/docs/EGRESS.md +125 -0
- package/docs/EXTENSIONS.md +398 -0
- package/docs/FRAMEWORK.md +198 -0
- package/docs/FUNCTION-SECURITY.md +129 -32
- package/docs/INSTALL.md +45 -12
- package/docs/INTERCHANGE.md +134 -0
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
- package/docs/MIDDLEWARE.md +29 -16
- package/docs/MONITORING.md +2 -19
- package/docs/NEXT-PHASE-PLAN.md +98 -0
- package/docs/NEXT-STEPS.md +634 -0
- package/docs/OBSERVABILITY.md +11 -18
- package/docs/OPEN-DECISIONS.md +212 -0
- package/docs/OPERATIONAL-PROOF.md +30 -31
- package/docs/OPERATIONS.md +29 -35
- package/docs/PLUGINS.md +37 -0
- package/docs/POLICIES.md +23 -309
- package/docs/PRERENDER.md +41 -1
- package/docs/PROJECT-DIRECTION.md +75 -8
- package/docs/PROVIDER-VERIFICATION.md +84 -0
- package/docs/READINESS.md +21 -1
- package/docs/README.md +87 -34
- package/docs/RECIPES.md +99 -0
- package/docs/RELEASE-READINESS.md +57 -35
- package/docs/RELEASE-SECURITY.md +116 -7
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +8 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +41 -1
- package/docs/SPECIFICATION.md +150 -29
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +1021 -0
- package/docs/SPIKE-CORE-LAYERING.md +337 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
- package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
- package/docs/SPIKE-EXTENSIONS.md +6 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +201 -0
- package/docs/SPIKE-MONOREPO.md +322 -0
- package/docs/STANDARDS.md +150 -142
- package/docs/STARTERS.md +21 -1
- package/docs/STATIC.md +94 -0
- package/docs/TOOLING.md +295 -0
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +82 -0
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/USABILITY-REVIEW.md +129 -0
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +205 -0
- package/docs/YAML-GUIDE.md +15 -479
- package/docs/YAML-REFERENCE.md +143 -22
- package/docs/policies/agents.md +1 -1
- package/docs/policies/cache.md +13 -0
- 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/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 +29 -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 +20 -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/monitoring/example.yaml +8 -0
- package/examples/prerender/README.md +2 -2
- 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 +3084 -0
- package/llms.txt +61 -21
- package/package.json +36 -7
- package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +122 -0
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +108 -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 +29 -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 +20 -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 +8 -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 +20 -0
- package/recipes/webhook-receiver/functions/receive.mjs +16 -0
- package/recipes/webhook-receiver/recipe.yaml +27 -0
- package/recipes/webhook-receiver/tests/requests.json +59 -0
- package/recipes/webhook-receiver/urlcode.yaml +23 -0
- package/schemas/recipe.schema.json +139 -0
- package/schemas/urlcode.schema.json +659 -110
- package/skills/urlcode/SKILL.md +119 -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/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -41
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -36
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -9
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -561
- package/docs/MANAGEMENT-SECURITY.md +0 -82
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
package/docs/YAML-GUIDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# YAML guide and recipe book
|
|
2
2
|
|
|
3
|
-
This guide targets URLCode 0.
|
|
3
|
+
This guide targets URLCode 0.3.0. Start with the function example below,
|
|
4
4
|
then add only the fields your route needs. The authoritative machine-readable
|
|
5
5
|
shape is [JSON Schema](../schemas/urlcode.schema.json); semantic rules are in the
|
|
6
6
|
[specification](SPECIFICATION.md). Unsupported fields fail validation.
|
|
@@ -16,7 +16,7 @@ From the runtime checkout:
|
|
|
16
16
|
npm ci
|
|
17
17
|
node src/cli.ts validate --project examples/cookbook
|
|
18
18
|
node src/cli.ts test --project examples/cookbook
|
|
19
|
-
node src/cli.ts audit --project examples/cookbook --expect-routes
|
|
19
|
+
node src/cli.ts audit --project examples/cookbook --expect-routes 40
|
|
20
20
|
node src/cli.ts dev --project examples/cookbook
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -24,482 +24,21 @@ The cookbook is a larger learning project. The normal `urlcode init ../my-links`
|
|
|
24
24
|
remains a small two-route starter. For an independent application with a pinned
|
|
25
25
|
runtime dependency, clone [urlcode-template](https://github.com/jimhoyd-com/urlcode-template).
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Pages
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Each page holds the recipes for one task; the section numbers continue across pages.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
args:
|
|
43
|
-
name: {from: path, name: name}
|
|
44
|
-
env:
|
|
45
|
-
GREETING: {value: Hello}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Create `functions/hello.mjs`:
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
export default function hello(request, {args, env}) {
|
|
52
|
-
return Response.json({message: `${env.GREETING}, ${args.name}!`});
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
GET `/hello/Ada` returns JSON. HEAD invokes the function and suppresses the body.
|
|
57
|
-
Methods default to GET and HEAD. Function paths resolve from the project root,
|
|
58
|
-
not the YAML file's directory. `.js` and `.mjs` ES modules work; TypeScript, Node
|
|
59
|
-
APIs, npm imports, network access and filesystem access do not.
|
|
60
|
-
|
|
61
|
-
## 2. Ordinary and permanent redirects
|
|
62
|
-
|
|
63
|
-
The following snippets are **entries under `routes:`** unless stated otherwise:
|
|
64
|
-
|
|
65
|
-
```yaml
|
|
66
|
-
/go:
|
|
67
|
-
redirect:
|
|
68
|
-
url: https://example.com/
|
|
69
|
-
/moved:
|
|
70
|
-
redirect:
|
|
71
|
-
url: https://example.com/new
|
|
72
|
-
status: 308
|
|
73
|
-
response:
|
|
74
|
-
headers:
|
|
75
|
-
Cache-Control: public, max-age=60
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
302 is the default. Allowed codes are 301, 302, 303, 307 and 308. Choose status
|
|
79
|
-
and cache policy deliberately: a cached permanent redirect can outlive a server
|
|
80
|
-
rollback. Requests' query strings are not forwarded by default. No function or
|
|
81
|
-
middleware means no sandbox execution for these routes.
|
|
82
|
-
|
|
83
|
-
## 3. Parameterized redirects and explicit query forwarding
|
|
84
|
-
|
|
85
|
-
```yaml
|
|
86
|
-
/product/{id}:
|
|
87
|
-
parameters:
|
|
88
|
-
- name: id
|
|
89
|
-
in: path
|
|
90
|
-
required: true
|
|
91
|
-
schema: {type: string, minLength: 1, maxLength: 64}
|
|
92
|
-
- name: page
|
|
93
|
-
in: query
|
|
94
|
-
schema: {type: integer, minimum: 1, maximum: 100, default: 1}
|
|
95
|
-
- name: tag
|
|
96
|
-
in: query
|
|
97
|
-
schema: {type: array, items: {type: string}, maxItems: 3}
|
|
98
|
-
- name: x-channel
|
|
99
|
-
in: header
|
|
100
|
-
schema: {type: string, enum: [web, email], default: web}
|
|
101
|
-
redirect:
|
|
102
|
-
url: https://example.com/products/{id}
|
|
103
|
-
query:
|
|
104
|
-
map:
|
|
105
|
-
page: {from: query, name: page}
|
|
106
|
-
label: {from: query, name: tag}
|
|
107
|
-
channel: {from: header, name: x-channel}
|
|
108
|
-
pass: [utm_source]
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
`/product/abc?page=2&tag=red&tag=blue&utm_source=news&ignored=no` redirects to
|
|
112
|
-
`https://example.com/products/abc?page=2&label=red&label=blue&channel=web&utm_source=news`.
|
|
113
|
-
The unknown `ignored` key is dropped. Missing `page` becomes 1. Arrays produce
|
|
114
|
-
repeated destination keys. Invalid page values return 400 before redirecting.
|
|
115
|
-
|
|
116
|
-
Destination hosts/schemes are literal HTTP(S); path placeholders are safely
|
|
117
|
-
encoded. No arbitrary input-controlled host, credentials, secret interpolation,
|
|
118
|
-
or unrestricted `pass: true`. Mapping/passthrough keys must not collide with
|
|
119
|
-
existing destination keys. Header inputs are client-supplied values, not proof
|
|
120
|
-
of identity. See [input and redirect semantics](SPECIFICATION.md).
|
|
121
|
-
|
|
122
|
-
## 4. Input types and constraints
|
|
123
|
-
|
|
124
|
-
Use this list under a route's `parameters` when those inputs are needed:
|
|
125
|
-
|
|
126
|
-
```yaml
|
|
127
|
-
parameters:
|
|
128
|
-
- name: search
|
|
129
|
-
in: query
|
|
130
|
-
required: true
|
|
131
|
-
schema: {type: string, minLength: 1, maxLength: 200}
|
|
132
|
-
- name: page
|
|
133
|
-
in: query
|
|
134
|
-
schema: {type: integer, minimum: 1, default: 1}
|
|
135
|
-
- name: weight
|
|
136
|
-
in: query
|
|
137
|
-
schema: {type: number, minimum: 0, maximum: 1}
|
|
138
|
-
- name: preview
|
|
139
|
-
in: query
|
|
140
|
-
schema: {type: boolean, default: false}
|
|
141
|
-
- name: category
|
|
142
|
-
in: query
|
|
143
|
-
schema: {type: string, enum: [docs, news], default: docs}
|
|
144
|
-
- name: ids
|
|
145
|
-
in: query
|
|
146
|
-
schema: {type: array, items: {type: integer}, maxItems: 10}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Path inputs must be required strings with no default. Query/header scalar types
|
|
150
|
-
are string, integer, number and boolean; arrays are query-only. Booleans are
|
|
151
|
-
exactly `true`/`false`; numbers do not accept exponent notation or whitespace.
|
|
152
|
-
Defaults apply to absence, not empty strings. Duplicate scalar values fail.
|
|
153
|
-
Required, missing and invalid inputs return 400. This is a documented subset,
|
|
154
|
-
not full OpenAPI/JSON Schema: no `pattern`, `format`, nested input objects,
|
|
155
|
-
`oneOf`, `style` or `explode` in parameter schemas.
|
|
156
|
-
|
|
157
|
-
## 5. Methods and body validation
|
|
158
|
-
|
|
159
|
-
```yaml
|
|
160
|
-
/echo:
|
|
161
|
-
methods: [POST]
|
|
162
|
-
request:
|
|
163
|
-
body:
|
|
164
|
-
required: true
|
|
165
|
-
maxBytes: 4096
|
|
166
|
-
contentTypes: [application/json]
|
|
167
|
-
format: json
|
|
168
|
-
function:
|
|
169
|
-
source: functions/echo.mjs
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
```js
|
|
173
|
-
export default async function echo(request) {
|
|
174
|
-
return Response.json(await request.json());
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
This validates JSON syntax/media type/UTF-8 and body size, not an application
|
|
179
|
-
object schema. Validate business fields in code. Empty required body: 400;
|
|
180
|
-
oversized body: 413; wrong media type: 415. For text, use `contentTypes:
|
|
181
|
-
[text/plain]`, `format: text`, and `request.text()`; see the runnable `/text`
|
|
182
|
-
recipe. `maxBytes: 0` can reject nonempty bodies. Bodies are buffered, not streamed.
|
|
183
|
-
|
|
184
|
-
Allowed methods: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS. An explicit list
|
|
185
|
-
replaces the defaults: `[GET]` does not add HEAD. Wrong method returns 405 with
|
|
186
|
-
Allow. Asset handlers accept only GET/HEAD. Body bytes are not automatically
|
|
187
|
-
mapped to function arguments.
|
|
188
|
-
|
|
189
|
-
## 6. All function argument sources
|
|
190
|
-
|
|
191
|
-
Within `function.args`, supported values are:
|
|
192
|
-
|
|
193
|
-
```yaml
|
|
194
|
-
args:
|
|
195
|
-
label: campaign
|
|
196
|
-
attempts: 3
|
|
197
|
-
preview: false
|
|
198
|
-
code: {from: path, name: code}
|
|
199
|
-
page: {from: query, name: page}
|
|
200
|
-
channel: {from: header, name: x-channel}
|
|
201
|
-
greeting: {env: GREETING}
|
|
202
|
-
token: {secret: TOKEN}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
This is a field-shape illustration: declare the referenced path/query/header
|
|
206
|
-
inputs and route binding aliases before using it. Null, array and arbitrary
|
|
207
|
-
object arguments are not supported. Read `context.args` or directly access
|
|
208
|
-
`context.inputs.path/query/header`, `context.env` and `context.secrets`.
|
|
209
|
-
`function.export` selects a named export; omit it for `default`.
|
|
210
|
-
|
|
211
|
-
For a dynamic redirect, use validated choices instead of accepting any URL:
|
|
212
|
-
|
|
213
|
-
```js
|
|
214
|
-
export default function choice(request, {args}) {
|
|
215
|
-
const destinations = {docs: 'https://example.com/docs', home: 'https://example.com/'};
|
|
216
|
-
return Response.redirect(destinations[args.destination], 302);
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
The runnable `/choice` recipe declares an enum query input and binds it to args.
|
|
221
|
-
Functions can return `Response.json(...)`, `new Response('text', {status, headers})`,
|
|
222
|
-
or `Response.redirect(...)`. HTML is a string response with Content-Type text/html;
|
|
223
|
-
escape untrusted values yourself. See the exact [guest API](SPECIFICATION.md#functions).
|
|
224
|
-
|
|
225
|
-
## 7. Middleware before and after a handler
|
|
226
|
-
|
|
227
|
-
```yaml
|
|
228
|
-
/go-with-header:
|
|
229
|
-
middleware:
|
|
230
|
-
- source: middleware/headers.mjs
|
|
231
|
-
export: decorate
|
|
232
|
-
redirect: {url: 'https://example.com/'}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
```js
|
|
236
|
-
export async function decorate(request, context, next) {
|
|
237
|
-
context.state.example = 'cookbook';
|
|
238
|
-
const response = await next();
|
|
239
|
-
response.headers.set('x-middleware', context.state.example);
|
|
240
|
-
return response;
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Entries run in declared order before the handler and reverse order afterward.
|
|
245
|
-
Return a Response early to skip downstream code; call `next()` at most once.
|
|
246
|
-
Up to 16 middleware entries share one sandbox/deadline and approved route
|
|
247
|
-
bindings. Native bodies are opaque; preserving them requires retaining original
|
|
248
|
-
status/headers. Return a new Response to replace native content or destination.
|
|
249
|
-
YAML response headers apply last. See [middleware](MIDDLEWARE.md) for details.
|
|
250
|
-
|
|
251
|
-
## 8. Native responses, headers and cookies
|
|
252
|
-
|
|
253
|
-
```yaml
|
|
254
|
-
/status:
|
|
255
|
-
respond:
|
|
256
|
-
json: {ok: true, service: my-links}
|
|
257
|
-
/notice:
|
|
258
|
-
respond:
|
|
259
|
-
status: 503
|
|
260
|
-
text: Temporarily unavailable
|
|
261
|
-
response:
|
|
262
|
-
headers:
|
|
263
|
-
Retry-After: "60"
|
|
264
|
-
/empty:
|
|
265
|
-
respond: {status: 204}
|
|
266
|
-
/cookie-demo:
|
|
267
|
-
respond: {text: Non-secret preferences only}
|
|
268
|
-
response:
|
|
269
|
-
headers:
|
|
270
|
-
Set-Cookie:
|
|
271
|
-
- "theme=light; Path=/; Secure; SameSite=Lax"
|
|
272
|
-
- "notice=seen; Path=/; HttpOnly; Secure; SameSite=Lax"
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
`respond` defaults to 200. Use text or JSON, never both. Omit both for an empty
|
|
276
|
-
body; 204/205 must have no body. 206/304 belong to native asset handling.
|
|
277
|
-
Header values are literal strings; quote numeric-looking values. Only Set-Cookie
|
|
278
|
-
accepts arrays. Do not put live session tokens in YAML. Secure cookies require
|
|
279
|
-
HTTPS at the browser. Functions can create dynamic cookies, but no cookie
|
|
280
|
-
parsing/signing/authentication framework is built in.
|
|
281
|
-
|
|
282
|
-
Do not set Content-Length, Location, Allow, ETag, Content-Range or other
|
|
283
|
-
runtime-owned headers in YAML. Use the corresponding handler. The full reserved
|
|
284
|
-
list and precedence rules are in [HTTP](HTTP.md).
|
|
285
|
-
|
|
286
|
-
## 9. Explicit OPTIONS response (not automatic CORS)
|
|
287
|
-
|
|
288
|
-
```yaml
|
|
289
|
-
/preflight:
|
|
290
|
-
methods: [OPTIONS]
|
|
291
|
-
respond: {status: 204}
|
|
292
|
-
response:
|
|
293
|
-
headers:
|
|
294
|
-
Access-Control-Allow-Origin: https://app.example.com
|
|
295
|
-
Access-Control-Allow-Methods: GET, HEAD
|
|
296
|
-
Access-Control-Allow-Headers: Content-Type
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
This teaches declared headers only; it is not a working cross-origin GET API.
|
|
300
|
-
For a real API, OPTIONS and the actual methods must be handled on the same URL,
|
|
301
|
-
and actual responses also need the appropriate CORS headers. Because one path
|
|
302
|
-
has one handler, use a function with `[GET, HEAD, OPTIONS]` to branch on method.
|
|
303
|
-
Never reflect arbitrary Origin with credentials. Automatic CORS is unsupported.
|
|
304
|
-
|
|
305
|
-
## 10. Pages, static folders, downloads and MIME
|
|
306
|
-
|
|
307
|
-
```yaml
|
|
308
|
-
/about:
|
|
309
|
-
page:
|
|
310
|
-
file: public/about.html
|
|
311
|
-
cacheControl: no-cache
|
|
312
|
-
/assets/*:
|
|
313
|
-
static:
|
|
314
|
-
directory: public/assets
|
|
315
|
-
index: index.html
|
|
316
|
-
cacheControl: public, max-age=3600
|
|
317
|
-
/download:
|
|
318
|
-
download:
|
|
319
|
-
file: public/guide.txt
|
|
320
|
-
filename: urlcode-guide.txt
|
|
321
|
-
contentType: text/plain
|
|
322
|
-
cacheControl: no-store
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
All files must exist. MIME is detected by extension, not content sniffing; unknown
|
|
326
|
-
extensions become application/octet-stream. `contentType` overrides detection
|
|
327
|
-
without MIME parameters. An override on a static mount affects all its files.
|
|
328
|
-
The download name defaults to the source basename. `index` is opt-in and only
|
|
329
|
-
applies to slash-terminated requests. No automatic slash redirect or SPA fallback.
|
|
330
|
-
|
|
331
|
-
Cache choices: `no-cache` (asset default), `no-store`, `public, max-age=3600`,
|
|
332
|
-
`public, max-age=31536000, immutable`. Reserve immutable caching for versioned
|
|
333
|
-
URLs. GET/HEAD, ETag/date validation and single byte ranges are supported.
|
|
334
|
-
Files stay snapshotted until reload/restart. See [assets](ASSETS.md) for complete
|
|
335
|
-
conditional/range semantics and publication safety. Files are limited to 16 MiB
|
|
336
|
-
each and 64 MiB total unique bytes per snapshot.
|
|
337
|
-
|
|
338
|
-
## 11. Enable, disable and expire
|
|
339
|
-
|
|
340
|
-
```yaml
|
|
341
|
-
/paused:
|
|
342
|
-
enabled: false
|
|
343
|
-
redirect: {url: 'https://example.com/'}
|
|
344
|
-
/campaign:
|
|
345
|
-
description: A scheduled end, no scheduled start
|
|
346
|
-
expires: "2030-01-01T00:00:00Z"
|
|
347
|
-
redirect: {url: 'https://example.com/'}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
Quote timestamps so they remain strings. Disabled routes return 404; expired
|
|
351
|
-
routes return 410. Expiry is an absolute UTC timestamp, not a TTL. There is no
|
|
352
|
-
start-time scheduler. `description` is authoring metadata. Changing YAML activates
|
|
353
|
-
through dev reload or production restart/deployment; it is not an HTTP mutation.
|
|
354
|
-
|
|
355
|
-
## 12. Environment and secret references
|
|
356
|
-
|
|
357
|
-
Route-level shape (references only, never secret values):
|
|
358
|
-
|
|
359
|
-
```yaml
|
|
360
|
-
env:
|
|
361
|
-
GREETING: {value: Hello}
|
|
362
|
-
REGION: {env: APP_REGION}
|
|
363
|
-
secrets:
|
|
364
|
-
TOKEN: {secret: APP_TOKEN}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
Literal non-secret env needs no grant. External env and secrets require an
|
|
368
|
-
operator-owned policy outside the checkout, granting exact names to the route
|
|
369
|
-
and pinning the reviewed config/code digest. `urlcode permissions --project
|
|
370
|
-
./my-links` prints a proposed policy; review it and store it outside the app.
|
|
371
|
-
Then pass `--policy /operator/path/policy.json` to validate/dev/test/serve.
|
|
372
|
-
This inspection does not authorize the project or execute its code.
|
|
373
|
-
|
|
374
|
-
Use ignored `.env.local` for local values; process environment wins. Production
|
|
375
|
-
`serve` reads process environment, never `.env.local`. Let your supervisor resolve
|
|
376
|
-
provider secrets and inject them; direct provider secret-store adapters do not
|
|
377
|
-
exist yet. Every config/code change invalidates the grant; rotate values by
|
|
378
|
-
restarting/redeploying. Never return a secret in an example response. Middleware
|
|
379
|
-
and functions on an approved route can read its bindings. See [policy setup](FUNCTION-SECURITY.md).
|
|
380
|
-
|
|
381
|
-
## 13. Split files and folders
|
|
382
|
-
|
|
383
|
-
Complete entry point:
|
|
384
|
-
|
|
385
|
-
```yaml
|
|
386
|
-
version: "1"
|
|
387
|
-
includes:
|
|
388
|
-
- routes/code.yaml
|
|
389
|
-
- routes/marketing/links.yaml
|
|
390
|
-
routes: {}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
Each included file contains `version: "1"` and `routes`. No nested includes,
|
|
394
|
-
globs, anchors, merge keys or remote includes. References always use project-root
|
|
395
|
-
paths. Duplicate routes fail; include order is not priority. See [organization](ORGANIZATION.md)
|
|
396
|
-
and [matching/regex/wildcard rules](ROUTING.md).
|
|
397
|
-
|
|
398
|
-
## 14. Assert inputs and outputs
|
|
399
|
-
|
|
400
|
-
Save a JSON array as `tests/requests.json`:
|
|
401
|
-
|
|
402
|
-
```json
|
|
403
|
-
[
|
|
404
|
-
{"path":"/hello/Ada","status":200,"expectBody":"{\"message\":\"Hello, Ada!\"}"},
|
|
405
|
-
{"path":"/hello/Ada","method":"HEAD","status":200,"expectBody":""},
|
|
406
|
-
{"path":"/go","status":302,"expectHeaders":{"location":"https://example.com/"}},
|
|
407
|
-
{"path":"/go","method":"POST","status":405,"expectHeaders":{"allow":"GET, HEAD"}}
|
|
408
|
-
]
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
This fixture targets recipes 1 and 2 together; the runnable cookbook has its own
|
|
412
|
-
matching expectations. Supported test fields: `path`, optional `method`, request
|
|
413
|
-
`headers` and string `body`, required `status`, optional exact string `expectBody`
|
|
414
|
-
and string-map `expectHeaders`. Tests do not follow external redirects. There
|
|
415
|
-
are no route-local YAML test fields or JSON-path assertions yet.
|
|
416
|
-
|
|
417
|
-
Run validate, test, routes, and audit with an intentional expected count. Test
|
|
418
|
-
both positive and negative inputs, every allowed method, HEAD, middleware short
|
|
419
|
-
circuits and relevant asset conditions. Audit needs meaningful body/header
|
|
420
|
-
assertions; a status-only success is insufficient. Benchmarks and recovery drills
|
|
421
|
-
are separate from functional correctness. See [readiness](READINESS.md).
|
|
422
|
-
|
|
423
|
-
See [organization and readability practices](BEST-PRACTICES.md) for conventions
|
|
424
|
-
that keep larger projects easy to maintain.
|
|
425
|
-
|
|
426
|
-
## 15. Live short-link records
|
|
427
|
-
|
|
428
|
-
Set `dynamicLinks: true` in the entry `urlcode.yaml` before adding this route.
|
|
429
|
-
It defaults to false and cannot be enabled by an included file.
|
|
430
|
-
|
|
431
|
-
```yaml
|
|
432
|
-
/r/{code}:
|
|
433
|
-
parameters:
|
|
434
|
-
- name: code
|
|
435
|
-
in: path
|
|
436
|
-
required: true
|
|
437
|
-
schema: {type: string, minLength: 1, maxLength: 128}
|
|
438
|
-
link:
|
|
439
|
-
collection: links
|
|
440
|
-
code: {from: path, name: code}
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
The seventh handler resolves stored records without rebuilding YAML. It requires
|
|
444
|
-
an external operator store binding; the [live-link example](../examples/live-links/README.md)
|
|
445
|
-
has separate setup and fixtures. See [dynamic links](DYNAMIC-LINKS.md) for CLI/API
|
|
446
|
-
creation, optimistic updates, disabled/expired records, persistence and backups.
|
|
447
|
-
This is not a general database capability for sandboxed functions.
|
|
448
|
-
|
|
449
|
-
## 16. Hardened profile and per-route overrides
|
|
450
|
-
|
|
451
|
-
```yaml
|
|
452
|
-
version: "1"
|
|
453
|
-
policies:
|
|
454
|
-
profile: hardened # security, agents, throttle, compression, cache
|
|
455
|
-
throttle: { quota: 60, window: 60 } # tighten one number; the rest stays
|
|
456
|
-
profiles:
|
|
457
|
-
public-api:
|
|
458
|
-
security: { headers: oshp-no-csp, set: { x-robots-tag: noindex } }
|
|
459
|
-
cache: { strategy: swr, maxAge: 30, staleWhileRevalidate: 300 }
|
|
460
|
-
routes:
|
|
461
|
-
/:
|
|
462
|
-
page: {source: pages/index.html}
|
|
463
|
-
/api/lookup/{id}:
|
|
464
|
-
parameters:
|
|
465
|
-
- {name: id, in: path, required: true, schema: {type: string, maxLength: 64}}
|
|
466
|
-
function: {source: functions/lookup.mjs}
|
|
467
|
-
policies:
|
|
468
|
-
profile: public-api # merges over the project layer
|
|
469
|
-
throttle: {quota: 10, window: 60, partition: client-route}
|
|
470
|
-
/healthz:
|
|
471
|
-
respond: {text: ok}
|
|
472
|
-
policies: {throttle: false, agents: false}
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
Everything under `policies` is optional and off unless declared. The project
|
|
476
|
-
block sets defaults, a route block adjusts them, `false` removes one policy for
|
|
477
|
-
that route and an object merges shallowly over what is below it. `hardened`
|
|
478
|
-
is the only built-in profile; `profiles` defines your own. Serve with
|
|
479
|
-
`--trusted-proxies` when a proxy sits in front so `client` partitioning sees
|
|
480
|
-
the real peer. Not every target accepts every policy: see the per-target
|
|
481
|
-
table in [policies](POLICIES.md) before deploying the same YAML to an adapter.
|
|
482
|
-
|
|
483
|
-
## 17. Site conventions
|
|
484
|
-
|
|
485
|
-
Generate the well-known files from a top-level `site` block instead of writing
|
|
486
|
-
them by hand. Each declared key becomes one native route counted by
|
|
487
|
-
`routes`/`audit`; a declared route at the same path wins.
|
|
488
|
-
|
|
489
|
-
```yaml
|
|
490
|
-
site:
|
|
491
|
-
robots:
|
|
492
|
-
disallow: [ai-crawlers, /admin]
|
|
493
|
-
sitemap: true # Sitemap line needs --origin
|
|
494
|
-
favicon: public/favicon.svg # served at /favicon.ico
|
|
495
|
-
securityTxt:
|
|
496
|
-
contact: [mailto:security@example.com]
|
|
497
|
-
expires: "2099-01-01T00:00:00Z"
|
|
498
|
-
llms: public/llms.txt # served at /llms.txt
|
|
499
|
-
# sitemap: true # /sitemap.xml; refuses to start without --origin
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
See [site conventions](SITE.md) for every field, exclusions and target support.
|
|
31
|
+
| Page | Sections |
|
|
32
|
+
|---|---|
|
|
33
|
+
| [Functions, inputs and methods](yaml/functions.md) | 1. A URL that runs code; 4. Input types and constraints; 5. Methods and body validation; 6. All function argument sources |
|
|
34
|
+
| [Redirects](yaml/redirects.md) | 2. Ordinary and permanent redirects; 3. Parameterized redirects and explicit query forwarding |
|
|
35
|
+
| [Middleware](yaml/middleware.md) | 7. Middleware before and after a handler |
|
|
36
|
+
| [Declared responses, headers and cookies](yaml/responses.md) | 8. Native responses, headers and cookies; 9. Explicit OPTIONS response (not automatic CORS) |
|
|
37
|
+
| [Pages, static folders and downloads](yaml/assets.md) | 10. Pages, static folders, downloads and MIME |
|
|
38
|
+
| [Enable, disable and expire](yaml/conditions.md) | 11. Enable, disable and expire |
|
|
39
|
+
| [Bindings, split files and tests](yaml/organization.md) | 12. Environment and secret references; 13. Split files and folders; 14. Assert inputs and outputs |
|
|
40
|
+
| [Policies and profiles](yaml/policies.md) | 16. Hardened profile and per-route overrides |
|
|
41
|
+
| [Site conventions](yaml/site.md) | 17. Site conventions |
|
|
503
42
|
|
|
504
43
|
## Common mistakes
|
|
505
44
|
|
|
@@ -516,6 +55,3 @@ See [site conventions](SITE.md) for every field, exclusions and target support.
|
|
|
516
55
|
| Automatic hot updates in `serve` | Deploy/restart or use the embedding reload API deliberately |
|
|
517
56
|
| “All examples are production-ready” | Validate your security, load and deployment requirements separately |
|
|
518
57
|
|
|
519
|
-
Live-link recipes require `dynamicLinks: true` in the entry `urlcode.yaml`. It is
|
|
520
|
-
false by default and cannot be set in included route files. Parameterized routes
|
|
521
|
-
and functions alone do not need it. See [dynamic-link opt-in](DYNAMIC-LINKS.md#explicit-project-opt-in).
|