@jimhoyd/urlcode 0.4.0-alpha.1 → 0.4.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/urlcode-authoring/SKILL.md +36 -22
- package/.claude/skills/urlcode-operations/SKILL.md +16 -22
- package/.claude-plugin/marketplace.json +1 -1
- package/CONTRIBUTING.md +20 -16
- package/README.md +83 -80
- package/ROADMAP.md +61 -331
- package/SECURITY.md +23 -8
- package/dist/BUILD-MANIFEST.json +42 -47
- package/dist/agents-guide.js +18 -18
- package/dist/build-static.js +136 -0
- package/dist/capabilities.js +85 -31
- package/dist/capability-query.js +0 -1
- package/dist/cli.js +24 -32
- package/dist/compliance-rules/baseline.js +2 -10
- package/dist/compliance-rules/privacy.js +5 -16
- package/dist/compliance-rules/shared.js +0 -2
- package/dist/compliance.js +6 -8
- package/dist/config.js +15 -8
- package/dist/context.js +9 -10
- package/dist/examples.js +2 -2
- package/dist/explain-cli.js +7 -5
- package/dist/explain.js +10 -5
- package/dist/extensions.js +61 -2
- package/dist/function-sources.js +34 -2
- package/dist/function-worker.js +3 -1
- package/dist/functions.js +84 -13
- package/dist/guest-api.js +29 -3
- package/dist/index.js +3 -6
- package/dist/manifest.js +11 -7
- package/dist/mcp-authoring.js +2 -2
- package/dist/mcp.js +1 -1
- package/dist/observability.js +1 -21
- package/dist/policies/cache.js +8 -3
- package/dist/policies.js +3 -1
- package/dist/policy.js +28 -9
- package/dist/prerender.js +4 -0
- package/dist/project-tests.js +3 -3
- package/dist/readiness.js +35 -9
- package/dist/route-diff.js +12 -5
- package/dist/router.js +5 -7
- package/dist/runtime.js +77 -58
- package/dist/sandbox.js +48 -0
- package/dist/scaffold.js +0 -0
- package/dist/scripts/operational-drills.js +12 -54
- package/dist/server.js +3 -29
- package/dist/tooling.js +1 -1
- package/dist/trusted-functions.js +210 -0
- package/dist/types/build-static.d.ts +43 -0
- package/dist/types/capabilities.d.ts +14 -5
- package/dist/types/compliance-rules/shared.d.ts +0 -2
- package/dist/types/compliance.d.ts +0 -3
- package/dist/types/config.d.ts +2 -1
- package/dist/types/context.d.ts +2 -1
- package/dist/types/examples.d.ts +1 -1
- package/dist/types/explain.d.ts +6 -0
- package/dist/types/extensions.d.ts +55 -0
- package/dist/types/function-sources.d.ts +4 -0
- package/dist/types/functions.d.ts +48 -5
- package/dist/types/guest-api.d.ts +1 -0
- package/dist/types/index.d.ts +3 -6
- package/dist/types/manifest.d.ts +5 -3
- package/dist/types/observability.d.ts +1 -14
- package/dist/types/project-tests.d.ts +1 -2
- package/dist/types/readiness.d.ts +12 -3
- package/dist/types/router.d.ts +2 -1
- package/dist/types/runtime.d.ts +0 -27
- package/dist/types/sandbox.d.ts +12 -0
- package/dist/types/scaffold.d.ts +0 -2
- package/dist/types/server.d.ts +1 -4
- package/dist/types/tooling.d.ts +3 -3
- package/dist/types/trusted-functions.d.ts +29 -0
- package/dist/types/types.d.ts +22 -8
- package/dist/types/verify-deployment.d.ts +2 -2
- package/dist/types.js +25 -5
- package/dist/typescript-authoring.js +67 -18
- package/dist/verify-deployment.js +3 -3
- package/docs/AI-AUTHORING.md +109 -10
- package/docs/ASSETS.md +2 -1
- package/docs/AUTH-BACKUP.md +32 -0
- package/docs/AWS.md +4 -4
- package/docs/BEST-PRACTICES.md +17 -8
- package/docs/CAPABILITIES.md +30 -17
- package/docs/CAPACITY.md +128 -31
- package/docs/CI-FOLLOWUP-2026-09-19.md +97 -0
- package/docs/CI-RELEASE-AUDIT-2026-09-19.md +322 -0
- package/docs/CI.md +8 -3
- package/docs/CLOUDFLARE.md +1 -2
- package/docs/CODEBASE-AUDIT-2026-09-20.md +278 -0
- package/docs/COMPLIANCE.md +6 -9
- package/docs/DEPLOYMENT-CHECKS.md +1 -1
- package/docs/DEVELOPMENT-PIPELINE.md +181 -0
- package/docs/EXTENSIONS.md +193 -11
- package/docs/FRAMEWORK.md +53 -33
- package/docs/FUNCTION-SECURITY.md +173 -32
- package/docs/INSTALL.md +0 -5
- package/docs/LOAD-TESTING.md +4 -4
- package/docs/LOCAL-DEVELOPMENT.md +3 -0
- package/docs/MIDDLEWARE.md +27 -16
- package/docs/MONITORING.md +2 -19
- package/docs/OBSERVABILITY.md +7 -16
- package/docs/OPEN-DECISIONS.md +184 -0
- package/docs/OPERATIONAL-PROOF.md +26 -30
- package/docs/OPERATIONS.md +23 -32
- package/docs/POLICIES.md +27 -8
- package/docs/PRERENDER.md +25 -13
- package/docs/PROJECT-DIRECTION.md +35 -10
- package/docs/READINESS.md +6 -2
- package/docs/README.md +20 -41
- package/docs/RELEASE-0.4.0-alpha.3.md +50 -0
- package/docs/RELEASE-READINESS.md +50 -30
- package/docs/RELEASE-SECURITY.md +72 -86
- package/docs/RESILIENCE.md +16 -15
- package/docs/ROUTING.md +7 -10
- package/docs/SANDBOX-REVIEW.md +19 -6
- package/docs/SCAFFOLDING.md +0 -2
- package/docs/SECURITY-AUDIT.md +42 -2
- package/docs/SPECIFICATION.md +63 -27
- package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +288 -0
- package/docs/SPIKE-BUSINESS-SUITE.md +16 -0
- package/docs/SPIKE-CORE-LAYERING.md +368 -0
- package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +211 -0
- package/docs/SPIKE-LAMBDA-COMPILE.md +12 -2
- package/docs/STARTERS.md +1 -1
- package/docs/STATIC.md +105 -0
- package/docs/TOOLING.md +17 -12
- package/docs/TUNNELS.md +0 -3
- package/docs/TYPESCRIPT-AUTHORING.md +32 -12
- package/docs/TYPESCRIPT.md +25 -4
- package/docs/VERCEL.md +4 -5
- package/docs/VERSION-ALIGNMENT.md +46 -0
- package/docs/YAML-GUIDE.md +0 -3
- package/docs/YAML-REFERENCE.md +16 -6
- package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +68 -0
- package/docs/{MANAGEMENT-SECURITY.md → archive/2026-09-19/MANAGEMENT-SECURITY.md} +20 -0
- package/docs/{NEXT-PHASE-PLAN.md → archive/2026-09-19/NEXT-PHASE-PLAN.md} +26 -8
- package/docs/{NEXT-STEPS.md → archive/2026-09-19/NEXT-STEPS.md} +274 -43
- package/docs/archive/2026-09-19/OPEN-DECISIONS.md +277 -0
- package/docs/archive/2026-09-19/RELEASE-SECURITY.md +186 -0
- package/docs/archive/2026-09-19/ROADMAP.md +386 -0
- package/docs/{SPIKE-EXTENSION-MODEL.md → archive/2026-09-19/SPIKE-EXTENSION-MODEL.md} +12 -2
- package/docs/{SPIKE-EXTENSIONS.md → archive/2026-09-19/SPIKE-EXTENSIONS.md} +28 -12
- package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +776 -0
- package/docs/{USABILITY-REVIEW.md → archive/2026-09-19/USABILITY-REVIEW.md} +18 -2
- package/docs/archive/README.md +27 -0
- package/docs/policies/agents.md +1 -1
- package/docs/policies/cache.md +13 -0
- package/docs/policies/compression.md +3 -2
- package/docs/policies/security.md +3 -2
- package/examples/assets/example.yaml +2 -2
- package/examples/aws/example.yaml +1 -1
- package/examples/cloudflare/example.yaml +1 -1
- package/examples/conditions/example.yaml +1 -1
- package/examples/cookbook/example.yaml +1 -1
- package/examples/cookbook/middleware/bucket.mjs +12 -2
- package/examples/cookbook/middleware/locale.mjs +7 -3
- package/examples/cookbook/route-index.json +1 -1
- package/examples/cookbook/routes/middleware.yaml +1 -1
- package/examples/egress/example.yaml +1 -1
- package/examples/extensions/example.yaml +1 -1
- package/examples/prerender/README.md +14 -6
- package/examples/prerender/example.yaml +1 -1
- package/examples/prerender/functions/page.mjs +4 -2
- package/examples/prerender/middleware/template.mjs +1 -1
- package/examples/prerender/prerender.mjs +1 -1
- package/examples/prerender/urlcode.yaml +8 -4
- package/examples/provider-conformance/example.yaml +1 -1
- package/examples/vercel/example.yaml +1 -1
- package/llms-full.txt +686 -239
- package/llms.txt +27 -15
- package/package.json +32 -5
- package/packaging/claude-plugin/.claude-plugin/plugin.json +2 -2
- package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +36 -22
- package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +16 -22
- package/recipes/authenticated-json-api/README.md +4 -3
- package/recipes/authenticated-json-api/functions/profile.mjs +2 -1
- package/recipes/authenticated-json-api/recipe.yaml +2 -2
- package/recipes/contact-form/functions/contact.mjs +2 -1
- package/recipes/contact-form/recipe.yaml +3 -3
- package/recipes/cors-api/README.md +2 -2
- package/recipes/cors-api/recipe.yaml +2 -2
- package/recipes/health-page/README.md +1 -1
- package/recipes/health-page/recipe.yaml +1 -1
- package/recipes/json-api/README.md +1 -1
- package/recipes/json-api/recipe.yaml +4 -4
- package/recipes/middleware/README.md +8 -4
- package/recipes/middleware/middleware/bucket.mjs +12 -2
- package/recipes/middleware/middleware/locale.mjs +7 -3
- package/recipes/middleware/recipe.yaml +1 -1
- package/recipes/protected-download/README.md +1 -1
- package/recipes/protected-download/recipe.yaml +2 -2
- package/recipes/redirect/recipe.yaml +1 -1
- package/recipes/static-plus-api/README.md +2 -2
- package/recipes/static-plus-api/public/index.html +1 -1
- package/recipes/static-plus-api/recipe.yaml +2 -2
- package/recipes/static-plus-api/urlcode.yaml +1 -1
- package/recipes/typescript/README.md +2 -1
- package/recipes/typescript/recipe.yaml +5 -5
- package/recipes/webhook-receiver/README.md +5 -1
- package/recipes/webhook-receiver/recipe.yaml +2 -1
- package/recipes/webhook-receiver/urlcode.yaml +7 -0
- package/schemas/recipe.schema.json +4 -3
- package/schemas/urlcode.schema.json +14 -41
- package/skills/urlcode/SKILL.md +32 -11
- package/starters/default/AGENTS.md +18 -18
- package/starters/default/urlcode.yaml +0 -1
- package/dist/link-api.js +0 -136
- package/dist/link-cli.js +0 -141
- package/dist/link-events.js +0 -76
- package/dist/link-records.js +0 -31
- package/dist/link-store-worker.js +0 -150
- package/dist/link-store.js +0 -250
- package/dist/management-policy.js +0 -40
- package/dist/sqlite-version.js +0 -6
- package/dist/types/link-api.d.ts +0 -30
- package/dist/types/link-cli.d.ts +0 -37
- package/dist/types/link-events.d.ts +0 -27
- package/dist/types/link-records.d.ts +0 -11
- package/dist/types/link-store-worker.d.ts +0 -1
- package/dist/types/link-store.d.ts +0 -130
- package/dist/types/management-policy.d.ts +0 -8
- package/dist/types/sqlite-version.d.ts +0 -1
- package/docs/DYNAMIC-LINKS.md +0 -61
- package/docs/links/cli.md +0 -110
- package/docs/links/limits.md +0 -175
- package/docs/links/management-api.md +0 -80
- package/docs/links/pools.md +0 -75
- package/docs/links/setup.md +0 -135
- package/docs/yaml/links.md +0 -30
- package/examples/live-links/README.md +0 -11
- package/examples/live-links/example.yaml +0 -21
- package/examples/live-links/tests/requests.json +0 -6
- package/examples/live-links/urlcode.yaml +0 -16
|
@@ -6,11 +6,23 @@ export interface ExtensionDeclaration {
|
|
|
6
6
|
config: Record<string, unknown>;
|
|
7
7
|
}
|
|
8
8
|
export type ExtensionPolicies = Record<string, Record<string, unknown> | false>;
|
|
9
|
+
/**
|
|
10
|
+
* `root` is the project's resolved absolute directory (the same value
|
|
11
|
+
* `loadDocument()` computes and `functionFile()`/router.ts resolves
|
|
12
|
+
* `function`/`middleware` `source` entries against). It is not the process's
|
|
13
|
+
* `cwd()`: `--project`/`--host-file` are independent paths, a server can be
|
|
14
|
+
* started from any working directory, and the JS API can load a project
|
|
15
|
+
* programmatically with no relationship to `cwd()` at all. An extension that
|
|
16
|
+
* resolves project-relative paths of its own (for example, an alternative
|
|
17
|
+
* middleware source it loads by convention rather than through core's native
|
|
18
|
+
* `middleware:` array) must resolve them against this field, never `cwd()`.
|
|
19
|
+
*/
|
|
9
20
|
export interface ExtensionActivation {
|
|
10
21
|
origin: string;
|
|
11
22
|
target: TargetName;
|
|
12
23
|
projectSha256: string;
|
|
13
24
|
mounts: readonly string[];
|
|
25
|
+
root: string;
|
|
14
26
|
}
|
|
15
27
|
export interface ExtensionRequest {
|
|
16
28
|
method: string;
|
|
@@ -28,6 +40,20 @@ export interface ExtensionRequest {
|
|
|
28
40
|
export interface ExtensionInstance {
|
|
29
41
|
handle(request: ExtensionRequest): HandlerResult | Promise<HandlerResult>;
|
|
30
42
|
authorize?(requirement: Readonly<Record<string, unknown>>, request: ExtensionRequest): HandlerResult | undefined | Promise<HandlerResult | undefined>;
|
|
43
|
+
/**
|
|
44
|
+
* Wrap semantics, not gate semantics: attached the same way as `authorize`
|
|
45
|
+
* (policies.extensions.<name> on a route, `config` the same validated
|
|
46
|
+
* per-route value `authorize`'s `requirement` receives), but given `next`,
|
|
47
|
+
* a callable invoking the rest of the pipeline for this route (any other
|
|
48
|
+
* declared extension `middleware()` after this one, then the route's own
|
|
49
|
+
* native `middleware:` chain and handler) at most once. Calling it lets
|
|
50
|
+
* this hook run code before and after the rest of the pipeline, inspecting
|
|
51
|
+
* or mutating the `HandlerResult` it resolves to; skipping it short-circuits
|
|
52
|
+
* the rest of the pipeline entirely, the same way `authorize` can. Never
|
|
53
|
+
* touches the native `middleware:` array or its own sandboxed/trusted
|
|
54
|
+
* dispatch, and never runs before `authorize` on the same route.
|
|
55
|
+
*/
|
|
56
|
+
middleware?(config: Readonly<Record<string, unknown>>, request: ExtensionRequest, next: () => Promise<HandlerResult>): HandlerResult | Promise<HandlerResult>;
|
|
31
57
|
close?(): void | Promise<void>;
|
|
32
58
|
}
|
|
33
59
|
/** Trusted operator code only. YAML declares names/configuration, never modules. */
|
|
@@ -49,6 +75,23 @@ export interface RuntimeExtension {
|
|
|
49
75
|
policySchema?: object;
|
|
50
76
|
credentialHeaders?: string[];
|
|
51
77
|
immutableAssets?: ExtensionImmutableAssets;
|
|
78
|
+
/**
|
|
79
|
+
* Reviewed, operator-declared cache sensitivity for `policies.extensions.<name>`
|
|
80
|
+
* routes (never for an `extension:` mount, which is always treated as
|
|
81
|
+
* sensitive). Omitted or `true`: the current, safe default — the runtime
|
|
82
|
+
* forces `Cache-Control: no-store`, disables compression and applies the
|
|
83
|
+
* extension response's header/size caps, exactly like `authorize`-gating
|
|
84
|
+
* auth/admin extensions. `false` is an explicit, reviewed opt-in a generic,
|
|
85
|
+
* cache-transparent extension (pure request/response middleware with no
|
|
86
|
+
* gating semantics of its own) makes to say its
|
|
87
|
+
* `middleware()` hook never depends on withholding the response from
|
|
88
|
+
* shared caches: the wrapped route's own declared cache headers pass
|
|
89
|
+
* through unchanged, exactly as the native `middleware:` array already
|
|
90
|
+
* does. A route naming more than one extension is treated as sensitive if
|
|
91
|
+
* any of them is (or leaves this unset) — this can only relax the no-store
|
|
92
|
+
* floor, never weaken it, and it never changes whether `authorize()` runs.
|
|
93
|
+
*/
|
|
94
|
+
cacheSensitive?: boolean;
|
|
52
95
|
activate(config: Readonly<Record<string, unknown>>, context: ExtensionActivation): ExtensionInstance | Promise<ExtensionInstance>;
|
|
53
96
|
}
|
|
54
97
|
/** `urlcode init --with <name>` contract: what core hands `@jimhoyd/urlcode-<name>`'s `scaffold` export. Nothing is written by `scaffold`. */
|
|
@@ -107,6 +150,18 @@ export declare const immutableCacheControl = "public, max-age=31536000, immutabl
|
|
|
107
150
|
export declare function inspectExtensionRevision(project: string): Promise<string>;
|
|
108
151
|
export declare function effectiveExtensionPolicies(document: ProjectDocument, route: Pick<RouteConfig, 'policies'>): Record<string, Record<string, unknown>>;
|
|
109
152
|
export declare function hasExtensionPolicy(document: ProjectDocument, route: Pick<RouteConfig, 'policies'>): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether a route naming these `policies.extensions` names must be treated as
|
|
155
|
+
* confidential (forced no-store, no compression, extension response caps).
|
|
156
|
+
* `names` with no entries is never confidential. Without a `registrations`
|
|
157
|
+
* list to consult (a build path with no operator host loaded), every name is
|
|
158
|
+
* treated as sensitive: the safe default this can only relax, never weaken.
|
|
159
|
+
* A name whose registration is missing, or declares no `cacheSensitive` (or
|
|
160
|
+
* `true`), counts as sensitive; only an explicit `cacheSensitive: false`
|
|
161
|
+
* excuses it, and one sensitive name among several makes the whole route
|
|
162
|
+
* confidential.
|
|
163
|
+
*/
|
|
164
|
+
export declare function isSensitiveExtensionPolicy(names: readonly string[], registrations?: readonly Pick<RuntimeExtension, 'name' | 'cacheSensitive'>[]): boolean;
|
|
110
165
|
export declare function prepareExtensions(document: ProjectDocument, routes: Record<string, RouteConfig>, registrations: RuntimeExtension[] | undefined, context: Omit<ExtensionActivation, 'mounts'>): {
|
|
111
166
|
activate(): Promise<ExtensionRegistry>;
|
|
112
167
|
};
|
|
@@ -23,4 +23,8 @@ export declare const MODULE_LIMIT = 128;
|
|
|
23
23
|
export declare const MODULE_BYTE_LIMIT = 1048576;
|
|
24
24
|
export declare const TOTAL_BYTE_LIMIT = 4194304;
|
|
25
25
|
export declare function routeFunctions<D>(route: FunctionRoute<D>): D[];
|
|
26
|
+
export declare function collectTrustedSources(routes: FunctionRoute[], root: string): Promise<Record<string, string>>;
|
|
27
|
+
export declare function collectSourcesFor(definitions: FunctionDefinition[], root: string): Promise<FunctionSources>;
|
|
28
|
+
/** Route-shaped convenience over `collectSourcesFor`: every existing caller (policy.ts,
|
|
29
|
+
* prerender.ts, typescript-authoring.ts) keeps working unchanged from `FunctionRoute[]`. */
|
|
26
30
|
export declare function collectFunctionSources(routes: FunctionRoute[], root: string): Promise<FunctionSources>;
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import { Worker } from 'node:worker_threads';
|
|
2
|
-
import type { FunctionRoute, FunctionSources } from './function-sources.ts';
|
|
2
|
+
import type { FunctionDefinition, FunctionRoute, FunctionSources } from './function-sources.ts';
|
|
3
3
|
import type { HandlerResult, HeaderPair } from './http-response.ts';
|
|
4
4
|
import type { ParameterValue, RequestContext } from './match.ts';
|
|
5
5
|
import type { LogFn } from './types.ts';
|
|
6
6
|
import type { GuestRequestPayload } from './guest-api.ts';
|
|
7
7
|
export type { FunctionDefinition, FunctionRoute } from './function-sources.ts';
|
|
8
8
|
export type { GuestRequestPayload, GuestResponsePayload } from './guest-api.ts';
|
|
9
|
-
|
|
9
|
+
/** A module entry point the sandbox must load: an absolute source file path
|
|
10
|
+
* (already resolved and validated, e.g. via `functionFile()`) plus which
|
|
11
|
+
* export of it needs to be reachable. The same shape a `FunctionDefinition`
|
|
12
|
+
* already uses for `function`/`middleware` routes. */
|
|
13
|
+
export type SandboxEntry = FunctionDefinition;
|
|
14
|
+
/** What one `SandboxPool.execute()` call invokes: the same `{source, export}`
|
|
15
|
+
* shape as a `SandboxEntry`, naming one of the pool's declared entries. */
|
|
16
|
+
export type SandboxTarget = FunctionDefinition;
|
|
17
|
+
/** `entry` runs last (the route's `function`/handler); `chain` runs first, in
|
|
18
|
+
* order, each with `(request, context, next)` — the same wrap/middleware
|
|
19
|
+
* semantics `__invokePipeline` already gives sandboxed routes. Neither is
|
|
20
|
+
* required: an empty invocation with a `native` reply just returns it. */
|
|
21
|
+
export interface SandboxInvocation {
|
|
22
|
+
entry?: SandboxTarget | undefined;
|
|
23
|
+
chain?: SandboxTarget[] | undefined;
|
|
24
|
+
}
|
|
25
|
+
export interface SandboxPoolOptions {
|
|
10
26
|
root?: string | undefined;
|
|
11
27
|
snapshot?: FunctionSources | undefined;
|
|
12
28
|
workers?: number | undefined;
|
|
@@ -14,6 +30,7 @@ export interface FunctionPoolOptions {
|
|
|
14
30
|
maxBytes?: number | undefined;
|
|
15
31
|
log?: LogFn | undefined;
|
|
16
32
|
}
|
|
33
|
+
export type FunctionPoolOptions = SandboxPoolOptions;
|
|
17
34
|
export interface FunctionWorkerData {
|
|
18
35
|
sources: Record<string, string>;
|
|
19
36
|
dependencies: Record<string, string[]>;
|
|
@@ -52,6 +69,7 @@ export type FunctionWorkerMessage = {
|
|
|
52
69
|
headers: HeaderPair[];
|
|
53
70
|
body: Uint8Array;
|
|
54
71
|
nativeBody: boolean;
|
|
72
|
+
contentLength?: number;
|
|
55
73
|
} | {
|
|
56
74
|
id: string;
|
|
57
75
|
error: true;
|
|
@@ -67,9 +85,9 @@ interface Slot {
|
|
|
67
85
|
ready: boolean;
|
|
68
86
|
pending: Pending | null;
|
|
69
87
|
}
|
|
70
|
-
export declare class
|
|
88
|
+
export declare class SandboxPool {
|
|
71
89
|
root: string | undefined;
|
|
72
|
-
|
|
90
|
+
entries: SandboxEntry[];
|
|
73
91
|
preparedSnapshot: FunctionSources | undefined;
|
|
74
92
|
snapshot: FunctionSources | undefined;
|
|
75
93
|
restarts: Map<number, number>;
|
|
@@ -81,12 +99,37 @@ export declare class FunctionPool {
|
|
|
81
99
|
size: number;
|
|
82
100
|
slots: (Slot | undefined)[];
|
|
83
101
|
closed: boolean;
|
|
84
|
-
constructor(
|
|
102
|
+
constructor(entries: SandboxEntry[], { root, snapshot, workers, timeoutMs, maxBytes, log }?: SandboxPoolOptions);
|
|
85
103
|
start(): Promise<this>;
|
|
86
104
|
spawn(index: number): Promise<void>;
|
|
87
105
|
report(status: string, index: number, extra?: object): void;
|
|
88
106
|
scheduleRespawn(index: number): void;
|
|
89
107
|
get healthy(): boolean;
|
|
108
|
+
/** `invocation.entry` runs last (chain-wrapped), `invocation.chain` first, in
|
|
109
|
+
* declared order — the same `__invokePipeline` wrap/middleware discipline
|
|
110
|
+
* (`next()` callable at most once) the sandboxed route path already
|
|
111
|
+
* enforces; there is no second dispatch mechanism for this. Every entry and
|
|
112
|
+
* chain source named here must already be one of this pool's declared
|
|
113
|
+
* `entries` (constructor), or the worker's own module allowlist denies it. */
|
|
114
|
+
execute(invocation: SandboxInvocation, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
|
|
115
|
+
close(): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
export declare class FunctionPool {
|
|
118
|
+
routes: FunctionRoute[];
|
|
119
|
+
private pool;
|
|
120
|
+
constructor(routes: FunctionRoute[], options?: FunctionPoolOptions);
|
|
121
|
+
start(): Promise<this>;
|
|
90
122
|
execute(route: FunctionRoute, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
|
|
123
|
+
scheduleRespawn(index: number): void;
|
|
91
124
|
close(): Promise<void>;
|
|
125
|
+
get healthy(): boolean;
|
|
126
|
+
get restarts(): Map<number, number>;
|
|
127
|
+
get restartTimers(): Set<NodeJS.Timeout>;
|
|
128
|
+
get slots(): (Slot | undefined)[];
|
|
129
|
+
get size(): number;
|
|
130
|
+
get closed(): boolean;
|
|
131
|
+
get snapshot(): FunctionSources | undefined;
|
|
132
|
+
get log(): LogFn;
|
|
133
|
+
get timeoutMs(): number;
|
|
134
|
+
get maxBytes(): number;
|
|
92
135
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
export { createRuntime } from './runtime.ts';
|
|
2
|
-
export type { Runtime, RuntimeOptions, RuntimeRequest, RequestTrace,
|
|
2
|
+
export type { Runtime, RuntimeOptions, RuntimeRequest, RequestTrace, HostPlugin, Observer, TestPlan } from './runtime.ts';
|
|
3
3
|
export { startServer } from './server.ts';
|
|
4
4
|
export type { Server, ServerOptions } from './server.ts';
|
|
5
5
|
export { loadDocument, validateDocument, parseYaml } from './config.ts';
|
|
6
|
-
export { openLinkStore } from './link-store.ts';
|
|
7
|
-
export type { LinkStore, LinkRow, LinkStoreOptions } from './link-store.ts';
|
|
8
|
-
export { startLinkApi } from './link-api.ts';
|
|
9
|
-
export type { LinkApi, LinkApiOptions } from './link-api.ts';
|
|
10
|
-
export type { LinkEvent, LinkObserverOptions, LinkObserverStats } from './link-events.ts';
|
|
11
6
|
export { events as observabilityEvents, validateObservers, createObserverSink, createMetrics, renderPrometheus } from './observability.ts';
|
|
12
7
|
export { getCapabilities, routeCapabilities, analyzeProjectCapabilities, analyzeCompiledCapabilities, assertTargetCompatibility, normalizeCapabilityTarget } from './capabilities.ts';
|
|
13
8
|
export { capabilityDetails } from './capabilities.ts';
|
|
@@ -35,6 +30,8 @@ export { normalizeMatch, assertDisjointMatches, matchesRoute } from './condition
|
|
|
35
30
|
export type { RouteMatch, ConditionRequest } from './conditions.ts';
|
|
36
31
|
export { buildCloudflare } from './build-cloudflare.ts';
|
|
37
32
|
export type { BuildOptions as CloudflareBuildOptions, BuildReport as CloudflareBuildReport } from './build-cloudflare.ts';
|
|
33
|
+
export { buildStatic } from './build-static.ts';
|
|
34
|
+
export type { BuildOptions as StaticBuildOptions, BuildReport as StaticBuildReport, StaticRedirect, StaticObject, RedirectManifest, ObjectManifest } from './build-static.ts';
|
|
38
35
|
export { runProjectTests } from './project-tests.ts';
|
|
39
36
|
export type { ProjectTestOptions, ProjectTestResult } from './project-tests.ts';
|
|
40
37
|
export { scaffoldProject } from './scaffold.ts';
|
package/dist/types/manifest.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CapabilityName, CapabilityTarget } from './capabilities.ts';
|
|
2
2
|
import type { InspectOptions } from './tooling.ts';
|
|
3
3
|
import type { RouteExplanation } from './explain.ts';
|
|
4
|
-
export declare const MANIFEST_SCHEMA_VERSION =
|
|
4
|
+
export declare const MANIFEST_SCHEMA_VERSION = 3;
|
|
5
5
|
export interface ManifestRoute {
|
|
6
6
|
path: string;
|
|
7
7
|
methods: string[];
|
|
@@ -10,6 +10,10 @@ export interface ManifestRoute {
|
|
|
10
10
|
expires?: string;
|
|
11
11
|
generated?: string;
|
|
12
12
|
description?: string;
|
|
13
|
+
/** Execution mode for the route's whole `function`/`middleware` chain: `true` for the
|
|
14
|
+
* QuickJS sandbox, `false` for trusted in-process execution. */
|
|
15
|
+
sandbox: boolean;
|
|
16
|
+
sandboxReason?: string;
|
|
13
17
|
middleware: {
|
|
14
18
|
source: string;
|
|
15
19
|
export: string;
|
|
@@ -63,8 +67,6 @@ export interface Manifest {
|
|
|
63
67
|
signals: string[];
|
|
64
68
|
};
|
|
65
69
|
extensions: string[];
|
|
66
|
-
linkStores: string[];
|
|
67
|
-
dynamicLinks: boolean;
|
|
68
70
|
};
|
|
69
71
|
functions: ManifestModule[];
|
|
70
72
|
middleware: ManifestModule[];
|
|
@@ -4,12 +4,8 @@ export declare const events: Readonly<{
|
|
|
4
4
|
reload: readonly string[];
|
|
5
5
|
watch: readonly string[];
|
|
6
6
|
function_worker: readonly string[];
|
|
7
|
-
link_store_worker: readonly string[];
|
|
8
|
-
link_request: readonly string[];
|
|
9
|
-
link_observer: readonly string[];
|
|
10
7
|
logs_dropped: readonly string[];
|
|
11
8
|
observer: readonly string[];
|
|
12
|
-
management_request: readonly string[];
|
|
13
9
|
throttle: readonly string[];
|
|
14
10
|
agents: readonly string[];
|
|
15
11
|
cache: readonly string[];
|
|
@@ -62,21 +58,12 @@ export interface MetricsSnapshot {
|
|
|
62
58
|
healthySlots: number;
|
|
63
59
|
slots: number;
|
|
64
60
|
};
|
|
65
|
-
linkStoreWorkers: {
|
|
66
|
-
started: number;
|
|
67
|
-
restarts: number;
|
|
68
|
-
};
|
|
69
61
|
policies: {
|
|
70
62
|
throttle: Counters;
|
|
71
63
|
agents: Counters;
|
|
72
64
|
cache: Counters;
|
|
73
65
|
};
|
|
74
66
|
signals: Counters;
|
|
75
|
-
linkRequests: Counters;
|
|
76
|
-
linkObserver: {
|
|
77
|
-
failed: number;
|
|
78
|
-
dropped: number;
|
|
79
|
-
};
|
|
80
67
|
logsDropped: number;
|
|
81
68
|
observers: {
|
|
82
69
|
errors: number;
|
|
@@ -99,7 +86,7 @@ export type ObserverSink = ((event: ObserverEvent, context?: RecordContext) => v
|
|
|
99
86
|
close(): Promise<void>;
|
|
100
87
|
};
|
|
101
88
|
export declare function validateObservers(observers?: unknown): Observer[];
|
|
102
|
-
export declare const SNAPSHOT_VERSION =
|
|
89
|
+
export declare const SNAPSHOT_VERSION = 2;
|
|
103
90
|
export declare function createMetrics(): Metrics;
|
|
104
91
|
export declare function createObserverSink(observers?: unknown, fallbackLog?: (event: ObserverEvent) => void, metrics?: Metrics): ObserverSink;
|
|
105
92
|
export declare function renderPrometheus(snapshot: Partial<MetricsSnapshot>): string;
|
|
@@ -5,11 +5,10 @@ export interface ProjectTestOptions {
|
|
|
5
5
|
plugins?: ServerOptions['plugins'];
|
|
6
6
|
log?: LogFn | undefined;
|
|
7
7
|
permissions?: ServerOptions['permissions'];
|
|
8
|
-
linkStore?: ServerOptions['linkStore'];
|
|
9
8
|
origin?: string | undefined;
|
|
10
9
|
}
|
|
11
10
|
export interface ProjectTestResult {
|
|
12
11
|
total: number;
|
|
13
12
|
failed: number;
|
|
14
13
|
}
|
|
15
|
-
export declare function runProjectTests(project: string, { log, permissions,
|
|
14
|
+
export declare function runProjectTests(project: string, { log, permissions, origin, extensions, plugins }?: ProjectTestOptions): Promise<ProjectTestResult>;
|
|
@@ -4,10 +4,15 @@ import type { CompiledRedirect, CompiledRoute, LogFn, PlanInventoryEntry, Policy
|
|
|
4
4
|
import type { ComplianceOptions, ComplianceReport } from './compliance.ts';
|
|
5
5
|
import type { CompiledRoutes } from './match.ts';
|
|
6
6
|
export type { RouteState } from './types.ts';
|
|
7
|
-
export type HandlerName = 'extension' | 'proxy' | 'conditional' | 'redirect' | 'function' | 'page' | 'static' | 'download' | 'respond'
|
|
7
|
+
export type HandlerName = 'extension' | 'proxy' | 'conditional' | 'redirect' | 'function' | 'page' | 'static' | 'download' | 'respond';
|
|
8
8
|
/** One configured route as the inventory reports it: a PlanInventoryEntry with the handler kind named. */
|
|
9
9
|
export interface RouteInventory extends PlanInventoryEntry {
|
|
10
10
|
handler: HandlerName | undefined;
|
|
11
|
+
/** Always reported here, so a trust change is visible in `routes` and its diff. */
|
|
12
|
+
sandbox: boolean;
|
|
13
|
+
/** Non-blocking `audit` observations about this route (e.g. a webhook-shaped
|
|
14
|
+
* route with no declared `sandbox`/`sandboxReason`); never affects `ready`. */
|
|
15
|
+
advisories?: string[];
|
|
11
16
|
}
|
|
12
17
|
/** One request case: a generated probe or a `tests/requests.json` fixture. */
|
|
13
18
|
export interface RequestCase {
|
|
@@ -40,7 +45,6 @@ export interface AuditableApp {
|
|
|
40
45
|
address: AddressInfo;
|
|
41
46
|
root: string;
|
|
42
47
|
testPlan(): ProjectPlan & {
|
|
43
|
-
dynamicLinks?: boolean;
|
|
44
48
|
policies?: Record<string, PolicyInventory>;
|
|
45
49
|
};
|
|
46
50
|
}
|
|
@@ -51,7 +55,6 @@ export interface AuditOptions {
|
|
|
51
55
|
compliance?: ComplianceOptions | undefined;
|
|
52
56
|
}
|
|
53
57
|
export interface AuditReport {
|
|
54
|
-
dynamicLinks: boolean | undefined;
|
|
55
58
|
elapsedMs: number;
|
|
56
59
|
ready: boolean;
|
|
57
60
|
counts: {
|
|
@@ -74,6 +77,12 @@ export interface AuditReport {
|
|
|
74
77
|
}[];
|
|
75
78
|
policies: Record<string, PolicyInventory>;
|
|
76
79
|
compliance: ComplianceReport | null;
|
|
80
|
+
/** Non-blocking `audit` observations, e.g. a route that looks webhook-shaped
|
|
81
|
+
* but declares neither `sandbox: true` nor `sandboxReason`. Never affects `ready`. */
|
|
82
|
+
advisories: {
|
|
83
|
+
route: string;
|
|
84
|
+
message: string;
|
|
85
|
+
}[];
|
|
77
86
|
}
|
|
78
87
|
export interface BenchmarkOptions {
|
|
79
88
|
requests?: number | undefined;
|
package/dist/types/router.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RuntimeExtension } from './extensions.ts';
|
|
1
2
|
import type { CompiledRouteTable, LoadedDocument } from './types.ts';
|
|
2
3
|
export { parseTarget, matchRoute, contextFor, resolveValue, redirectLocation } from './match.ts';
|
|
3
4
|
/** The grants compileRoutes consults: a validated OperatorPolicy (policy.ts) or nothing, which denies every binding. */
|
|
@@ -8,4 +9,4 @@ export interface BindingPermissions {
|
|
|
8
9
|
secrets?: string[];
|
|
9
10
|
}>;
|
|
10
11
|
}
|
|
11
|
-
export declare function compileRoutes(loaded: LoadedDocument, bindings: Record<string, string | undefined>, permissions?: BindingPermissions, projectSha256?: string): Promise<CompiledRouteTable>;
|
|
12
|
+
export declare function compileRoutes(loaded: LoadedDocument, bindings: Record<string, string | undefined>, permissions?: BindingPermissions, projectSha256?: string, extensions?: readonly Pick<RuntimeExtension, 'name' | 'cacheSensitive'>[]): Promise<CompiledRouteTable>;
|
package/dist/types/runtime.d.ts
CHANGED
|
@@ -2,34 +2,15 @@ import type { RuntimeExtension } from './extensions.ts';
|
|
|
2
2
|
import type { EgressDependencies } from './egress.ts';
|
|
3
3
|
import type { ProjectPlan } from './readiness.ts';
|
|
4
4
|
import type { OperatorPolicy } from './policy.ts';
|
|
5
|
-
import type { LinkStoreOptions } from './link-store.ts';
|
|
6
5
|
import type { Plugin } from './plugins.ts';
|
|
7
6
|
import type { MetricsSnapshot, Observer } from './observability.ts';
|
|
8
7
|
import type { HandlerResult, HeaderPair } from './http-response.ts';
|
|
9
8
|
import type { LogFn, PolicyInventory, TargetName } from './types.ts';
|
|
10
|
-
/** A stored link as a link store returns it; the runtime validates the fields it uses. */
|
|
11
|
-
export interface LinkLookup {
|
|
12
|
-
url?: unknown;
|
|
13
|
-
status?: unknown;
|
|
14
|
-
enabled?: unknown;
|
|
15
|
-
expires?: unknown;
|
|
16
|
-
}
|
|
17
|
-
/** What a `linkStores` binding must provide: a reader and, optionally, its health. */
|
|
18
|
-
export interface LinkReader {
|
|
19
|
-
get(collection: string, code: string): Promise<LinkLookup | null | undefined>;
|
|
20
|
-
readonly readHealthy?: boolean;
|
|
21
|
-
readonly healthy?: boolean;
|
|
22
|
-
}
|
|
23
|
-
/** An operator-owned SQLite link store the runtime opens read-only for one collection. */
|
|
24
|
-
export interface LinkStoreBinding extends LinkStoreOptions {
|
|
25
|
-
collection: string;
|
|
26
|
-
}
|
|
27
9
|
export type { OperatorPolicy } from './policy.ts';
|
|
28
10
|
/** An operator plugin (src/plugins.ts). */
|
|
29
11
|
export type HostPlugin = Plugin;
|
|
30
12
|
export type { Observer, MetricsSnapshot } from './observability.ts';
|
|
31
13
|
export interface TestPlan extends ProjectPlan {
|
|
32
|
-
dynamicLinks: boolean;
|
|
33
14
|
policies: Record<string, PolicyInventory>;
|
|
34
15
|
}
|
|
35
16
|
export interface RuntimeOptions {
|
|
@@ -42,8 +23,6 @@ export interface RuntimeOptions {
|
|
|
42
23
|
local?: boolean | undefined;
|
|
43
24
|
environment?: NodeJS.ProcessEnv | undefined;
|
|
44
25
|
permissions?: OperatorPolicy | undefined;
|
|
45
|
-
linkStore?: LinkStoreBinding | undefined;
|
|
46
|
-
linkStores?: Record<string, LinkReader> | undefined;
|
|
47
26
|
target?: TargetName | undefined;
|
|
48
27
|
plugins?: HostPlugin[] | undefined;
|
|
49
28
|
workers?: number | undefined;
|
|
@@ -57,16 +36,10 @@ export interface RuntimeOptions {
|
|
|
57
36
|
only?: readonly string[] | undefined;
|
|
58
37
|
}
|
|
59
38
|
/** Per-request facts the host may read after handle() settles; never request text. */
|
|
60
|
-
export interface LinkTrace {
|
|
61
|
-
collection: string;
|
|
62
|
-
code: string | null;
|
|
63
|
-
result: string;
|
|
64
|
-
}
|
|
65
39
|
export interface RequestTrace {
|
|
66
40
|
route?: string;
|
|
67
41
|
probe?: boolean;
|
|
68
42
|
client?: string | null;
|
|
69
|
-
link?: LinkTrace;
|
|
70
43
|
}
|
|
71
44
|
export interface RuntimeRequest {
|
|
72
45
|
target: string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { SandboxPool } from './functions.ts';
|
|
2
|
+
export type { SandboxEntry, SandboxTarget, SandboxInvocation, SandboxPoolOptions, FunctionContext, FunctionResult, } from './functions.ts';
|
|
3
|
+
export type { GuestRequestPayload, GuestResponsePayload } from './guest-api.ts';
|
|
4
|
+
export type { HandlerResult, HeaderPair } from './http-response.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a project-relative hook source string the same way a native
|
|
7
|
+
* `function`/`middleware` route's `source` is resolved (`.mjs`/`.js` only, no
|
|
8
|
+
* path traversal outside the project root) into the absolute path
|
|
9
|
+
* `SandboxPool`'s entries and `execute()` targets expect. `root` must be the
|
|
10
|
+
* project's resolved directory (`ExtensionActivation.root`, never `cwd()`).
|
|
11
|
+
*/
|
|
12
|
+
export { functionFile } from './config.ts';
|
package/dist/types/scaffold.d.ts
CHANGED
package/dist/types/server.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import type { AddressInfo } from 'node:net';
|
|
3
3
|
import type { RuntimeOptions, TestPlan } from './runtime.ts';
|
|
4
|
-
import type { LinkObserverStats } from './link-events.ts';
|
|
5
4
|
import type { MetricsSnapshot, Observer } from './observability.ts';
|
|
6
5
|
export interface ServerOptions extends Omit<RuntimeOptions, 'observers'> {
|
|
7
6
|
project?: string | undefined;
|
|
@@ -13,7 +12,6 @@ export interface ServerOptions extends Omit<RuntimeOptions, 'observers'> {
|
|
|
13
12
|
maxInFlightHealthRequests?: number | undefined;
|
|
14
13
|
requestLog?: string | undefined;
|
|
15
14
|
trustRequestId?: boolean | undefined;
|
|
16
|
-
linkEvents?: unknown;
|
|
17
15
|
trustedProxies?: string | string[] | undefined;
|
|
18
16
|
observers?: Observer[] | undefined;
|
|
19
17
|
metrics?: boolean | undefined;
|
|
@@ -25,7 +23,6 @@ export interface Server {
|
|
|
25
23
|
address: AddressInfo;
|
|
26
24
|
root: string;
|
|
27
25
|
testPlan(): TestPlan;
|
|
28
|
-
linkEventStats(): LinkObserverStats | undefined;
|
|
29
26
|
metrics(): MetricsSnapshot;
|
|
30
27
|
readonly observers: {
|
|
31
28
|
name: string;
|
|
@@ -34,4 +31,4 @@ export interface Server {
|
|
|
34
31
|
origin: string;
|
|
35
32
|
close(): Promise<void>;
|
|
36
33
|
}
|
|
37
|
-
export declare function startServer({ project, host, port, watch, local, log, maxBodyBytes, maxInFlightRequests, maxInFlightHealthRequests, requestLog, trustRequestId, origin,
|
|
34
|
+
export declare function startServer({ project, host, port, watch, local, log, maxBodyBytes, maxInFlightRequests, maxInFlightHealthRequests, requestLog, trustRequestId, origin, trustedProxies, observers, metrics, metricsIntervalMs, ...runtimeOptions }?: ServerOptions): Promise<Server>;
|
package/dist/types/tooling.d.ts
CHANGED
|
@@ -39,14 +39,14 @@ export declare function inspectProject(project: string, options?: InspectOptions
|
|
|
39
39
|
path: string;
|
|
40
40
|
methods: string[];
|
|
41
41
|
enabled: boolean;
|
|
42
|
-
capabilities: ("function" | "
|
|
42
|
+
capabilities: ("function" | "expires" | "middleware" | "extension" | "proxy" | "signals" | "conditional" | "methods" | "enabled" | "parameters" | "redirect" | "page" | "download" | "static" | "respond" | "policies.extensions" | "conditions" | "request.body" | "response.headers" | "bindings" | "policies.agents" | "policies.security" | "policies.cache" | "policies.compression" | "policies.throttle")[];
|
|
43
43
|
}[];
|
|
44
44
|
compatibility: {
|
|
45
45
|
offset: number;
|
|
46
46
|
limit: number;
|
|
47
47
|
hasMore: boolean;
|
|
48
48
|
issues: import("./capabilities.ts").CapabilityRequirement[];
|
|
49
|
-
target: "vercel" | "aws" | "cloudflare" | "self-hosted";
|
|
49
|
+
target: "vercel" | "aws" | "cloudflare" | "static" | "self-hosted";
|
|
50
50
|
compatible: boolean;
|
|
51
51
|
deployment: "local-runtime" | "unverified";
|
|
52
52
|
requirementCount: number;
|
|
@@ -58,7 +58,7 @@ export declare function validateProject(project: string, options?: InspectOption
|
|
|
58
58
|
projectSha256: string;
|
|
59
59
|
routeCount: number;
|
|
60
60
|
compatibility: {
|
|
61
|
-
target: "vercel" | "aws" | "cloudflare" | "self-hosted";
|
|
61
|
+
target: "vercel" | "aws" | "cloudflare" | "static" | "self-hosted";
|
|
62
62
|
compatible: boolean;
|
|
63
63
|
deployment: "local-runtime" | "unverified";
|
|
64
64
|
requirementCount: number;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FunctionRoute } from './function-sources.ts';
|
|
2
|
+
import type { FunctionContext, FunctionResult } from './functions.ts';
|
|
3
|
+
import type { GuestRequestPayload } from './guest-api.ts';
|
|
4
|
+
import type { HandlerResult } from './http-response.ts';
|
|
5
|
+
import type { LogFn } from './types.ts';
|
|
6
|
+
export interface TrustedFunctionsOptions {
|
|
7
|
+
timeoutMs?: number | undefined;
|
|
8
|
+
maxBytes?: number | undefined;
|
|
9
|
+
log?: LogFn | undefined;
|
|
10
|
+
}
|
|
11
|
+
interface TrustedDefinition {
|
|
12
|
+
source: string;
|
|
13
|
+
export: string;
|
|
14
|
+
}
|
|
15
|
+
export type TrustedRoute = FunctionRoute<TrustedDefinition>;
|
|
16
|
+
export declare class TrustedFunctions {
|
|
17
|
+
timeoutMs: number;
|
|
18
|
+
maxBytes: number;
|
|
19
|
+
log: LogFn;
|
|
20
|
+
private readonly epoch;
|
|
21
|
+
constructor({ timeoutMs, maxBytes, log }?: TrustedFunctionsOptions);
|
|
22
|
+
start(routes: TrustedRoute[]): Promise<this>;
|
|
23
|
+
private loadExport;
|
|
24
|
+
execute(route: TrustedRoute, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
|
|
25
|
+
private readBody;
|
|
26
|
+
private invoke;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -42,10 +42,6 @@ export type AuthoredRouteConfig = Omit<RouteConfig, 'function' | 'middleware'> &
|
|
|
42
42
|
function?: string | FunctionConfig;
|
|
43
43
|
middleware?: (string | MiddlewareConfig)[];
|
|
44
44
|
};
|
|
45
|
-
export interface LinkConfig {
|
|
46
|
-
collection: string;
|
|
47
|
-
code: ValueRef;
|
|
48
|
-
}
|
|
49
45
|
export interface PageConfig {
|
|
50
46
|
file: string;
|
|
51
47
|
contentType?: string;
|
|
@@ -151,6 +147,8 @@ export interface RouteAuthConfig {
|
|
|
151
147
|
export interface RouteConfig {
|
|
152
148
|
extension?: string;
|
|
153
149
|
auth?: true | RouteAuthConfig;
|
|
150
|
+
/** Route-level `cache` short form: the same object accepted by `policies.cache`, expanded to it before anything else reads the project. */
|
|
151
|
+
cache?: CacheConfig;
|
|
154
152
|
proxy?: ProxyConfig;
|
|
155
153
|
signals?: SignalConfig[];
|
|
156
154
|
match?: RouteMatch;
|
|
@@ -159,6 +157,18 @@ export interface RouteConfig {
|
|
|
159
157
|
enabled?: boolean;
|
|
160
158
|
expires?: string;
|
|
161
159
|
description?: string;
|
|
160
|
+
/** Opt into the isolated QuickJS/WASM worker pool for this route's `function`/`middleware`
|
|
161
|
+
* chain (docs/FUNCTION-SECURITY.md). Default false: trusted, in-process, unsandboxed
|
|
162
|
+
* execution (docs/SPIKE-DEFAULT-TRUST-MODEL.md). Applies uniformly to the whole
|
|
163
|
+
* chain — `function` and any `middleware` on the same route run in the same mode. */
|
|
164
|
+
sandbox?: boolean;
|
|
165
|
+
/** Optional, human-authored justification for this route's sandbox decision — why it
|
|
166
|
+
* needs isolation when `sandbox: true`, or why it is safe to trust when it is not.
|
|
167
|
+
* Parsed and schema-validated (max 500 characters, schemas/urlcode.schema.json), stored
|
|
168
|
+
* on the compiled route and surfaced by `explain`/`context`/manifest next to `sandbox`.
|
|
169
|
+
* Never inferred or enforced: the trust decision remains the author's judgment call
|
|
170
|
+
* (docs/AI-AUTHORING.md, "Deciding when a route needs sandbox: true"). */
|
|
171
|
+
sandboxReason?: string;
|
|
162
172
|
parameters?: ParameterConfig[];
|
|
163
173
|
redirect?: RedirectConfig;
|
|
164
174
|
function?: FunctionConfig;
|
|
@@ -175,7 +185,6 @@ export interface RouteConfig {
|
|
|
175
185
|
};
|
|
176
186
|
respond?: RespondSpec;
|
|
177
187
|
middleware?: MiddlewareConfig[];
|
|
178
|
-
link?: LinkConfig;
|
|
179
188
|
policies?: PoliciesConfig;
|
|
180
189
|
/** Set by site.ts on a route it generated (`site.<key>`); never declared in YAML. */
|
|
181
190
|
generated?: string;
|
|
@@ -185,7 +194,6 @@ export interface ProjectDocument {
|
|
|
185
194
|
extensions?: Record<string, ExtensionDeclaration>;
|
|
186
195
|
routes: Record<string, RouteConfig>;
|
|
187
196
|
includes?: string[];
|
|
188
|
-
dynamicLinks?: boolean;
|
|
189
197
|
policies?: PoliciesConfig;
|
|
190
198
|
profiles?: Record<string, PolicyLayer>;
|
|
191
199
|
site?: SiteConfig;
|
|
@@ -370,7 +378,7 @@ export type PolicyChain = {
|
|
|
370
378
|
describe: PolicyInventory;
|
|
371
379
|
} & Partial<PolicyStates>;
|
|
372
380
|
export type RouteState = 'active' | 'disabled' | 'expired';
|
|
373
|
-
/** One route in the audit inventory: its handler kind, methods and lifecycle state. */
|
|
381
|
+
/** One route in the audit inventory: its handler kind, methods, execution mode and lifecycle state. */
|
|
374
382
|
export interface PlanInventoryEntry {
|
|
375
383
|
path: string;
|
|
376
384
|
handler: string | undefined;
|
|
@@ -379,11 +387,17 @@ export interface PlanInventoryEntry {
|
|
|
379
387
|
policies: string[];
|
|
380
388
|
generated?: string;
|
|
381
389
|
state: RouteState;
|
|
390
|
+
/** The route's execution mode: `true` when its `function`/`middleware` chain runs in the
|
|
391
|
+
* QuickJS sandbox, `false` when it runs trusted in-process. Route-level, because the mode
|
|
392
|
+
* applies to the whole chain — a native handler with `middleware` has one too. Optional
|
|
393
|
+
* only at the report-parsing boundary: reports written before it existed omit it. */
|
|
394
|
+
sandbox?: boolean;
|
|
395
|
+
/** The route's declared `sandboxReason`, when it has one. */
|
|
396
|
+
sandboxReason?: string;
|
|
382
397
|
}
|
|
383
398
|
export interface TestPlan {
|
|
384
399
|
inventory: PlanInventoryEntry[];
|
|
385
400
|
cases: unknown[];
|
|
386
401
|
resolve?(path: string): string | undefined;
|
|
387
|
-
dynamicLinks?: boolean;
|
|
388
402
|
policies?: Record<string, PolicyInventory>;
|
|
389
403
|
}
|
|
@@ -12,7 +12,7 @@ export interface VerifyFinding {
|
|
|
12
12
|
expected?: string;
|
|
13
13
|
observed?: string;
|
|
14
14
|
}
|
|
15
|
-
export interface VerifyOptions extends Pick<RuntimeOptions, 'permissions'
|
|
15
|
+
export interface VerifyOptions extends Pick<RuntimeOptions, 'permissions'> {
|
|
16
16
|
target: string;
|
|
17
17
|
origin?: string | undefined;
|
|
18
18
|
expectRoutes?: number | undefined;
|
|
@@ -44,4 +44,4 @@ export interface VerifyReport {
|
|
|
44
44
|
compliance: ComplianceReport | null;
|
|
45
45
|
}
|
|
46
46
|
export declare const failLevels: readonly FailOn[];
|
|
47
|
-
export declare function verifyDeployment(project: string, { target, origin, expectRoutes, timeoutMs, expectMetrics, failOn, compliance, complianceWarn, log, permissions
|
|
47
|
+
export declare function verifyDeployment(project: string, { target, origin, expectRoutes, timeoutMs, expectMetrics, failOn, compliance, complianceWarn, log, permissions }: VerifyOptions): Promise<VerifyReport>;
|