veryfront 0.1.755 → 0.1.756
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/esm/cli/auth/callback-server.d.ts +4 -1
- package/esm/cli/auth/callback-server.d.ts.map +1 -1
- package/esm/cli/auth/callback-server.js +52 -13
- package/esm/cli/auth/index.d.ts +1 -1
- package/esm/cli/auth/index.d.ts.map +1 -1
- package/esm/cli/auth/index.js +1 -1
- package/esm/cli/auth/login.d.ts +2 -0
- package/esm/cli/auth/login.d.ts.map +1 -1
- package/esm/cli/auth/login.js +18 -6
- package/esm/cli/commands/demo/demo.d.ts.map +1 -1
- package/esm/cli/commands/demo/demo.js +6 -7
- package/esm/deno.js +1 -1
- package/esm/src/agent/runtime/index.d.ts +3 -96
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +21 -341
- package/esm/src/agent/runtime/model-capabilities.d.ts +3 -0
- package/esm/src/agent/runtime/model-capabilities.d.ts.map +1 -0
- package/esm/src/agent/runtime/model-capabilities.js +18 -0
- package/esm/src/agent/runtime/runtime-tool-config.d.ts +14 -0
- package/esm/src/agent/runtime/runtime-tool-config.d.ts.map +1 -0
- package/esm/src/agent/runtime/runtime-tool-config.js +37 -0
- package/esm/src/agent/runtime/skill-policy-enforcement.d.ts +16 -0
- package/esm/src/agent/runtime/skill-policy-enforcement.d.ts.map +1 -0
- package/esm/src/agent/runtime/skill-policy-enforcement.js +55 -0
- package/esm/src/agent/runtime/tool-result-continuation.d.ts +34 -0
- package/esm/src/agent/runtime/tool-result-continuation.d.ts.map +1 -0
- package/esm/src/agent/runtime/tool-result-continuation.js +194 -0
- package/esm/src/agent/schemas/agent.schema.d.ts +7 -0
- package/esm/src/agent/schemas/agent.schema.d.ts.map +1 -1
- package/esm/src/agent/schemas/agent.schema.js +9 -3
- package/esm/src/agent/schemas/index.d.ts +1 -1
- package/esm/src/agent/schemas/index.d.ts.map +1 -1
- package/esm/src/agent/schemas/index.js +1 -1
- package/esm/src/modules/server/module-server.d.ts.map +1 -1
- package/esm/src/modules/server/module-server.js +31 -9
- package/esm/src/modules/server/rate-limiter.d.ts +3 -2
- package/esm/src/modules/server/rate-limiter.d.ts.map +1 -1
- package/esm/src/platform/adapters/base.d.ts +24 -3
- package/esm/src/platform/adapters/base.d.ts.map +1 -1
- package/esm/src/platform/adapters/base.js +15 -1
- package/esm/src/platform/adapters/runtime/bun/websocket-adapter.d.ts +2 -0
- package/esm/src/platform/adapters/runtime/bun/websocket-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/runtime/bun/websocket-adapter.js +33 -1
- package/esm/src/platform/adapters/runtime/node/websocket-adapter.d.ts +1 -1
- package/esm/src/platform/adapters/runtime/node/websocket-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/runtime/node/websocket-adapter.js +3 -10
- package/esm/src/proxy/handler.d.ts.map +1 -1
- package/esm/src/proxy/handler.js +25 -116
- package/esm/src/proxy/local-project-resolver.d.ts +18 -0
- package/esm/src/proxy/local-project-resolver.d.ts.map +1 -0
- package/esm/src/proxy/local-project-resolver.js +63 -0
- package/esm/src/proxy/proxy-token-resolution.d.ts +37 -0
- package/esm/src/proxy/proxy-token-resolution.d.ts.map +1 -0
- package/esm/src/proxy/proxy-token-resolution.js +51 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts +10 -0
- package/esm/src/rendering/orchestrator/module-loader/index.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/module-loader/index.js +23 -158
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.d.ts +20 -0
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.d.ts.map +1 -0
- package/esm/src/rendering/orchestrator/module-loader/module-persistence.js +80 -0
- package/esm/src/rendering/orchestrator/module-loader/module-transform-cache.d.ts +59 -0
- package/esm/src/rendering/orchestrator/module-loader/module-transform-cache.d.ts.map +1 -0
- package/esm/src/rendering/orchestrator/module-loader/module-transform-cache.js +97 -0
- package/esm/src/routing/api/handler.d.ts +2 -1
- package/esm/src/routing/api/handler.d.ts.map +1 -1
- package/esm/src/routing/api/handler.js +2 -1
- package/esm/src/routing/api/route-executor.d.ts +3 -0
- package/esm/src/routing/api/route-executor.d.ts.map +1 -1
- package/esm/src/routing/api/route-executor.js +28 -0
- package/esm/src/runtime/runtime-bridge.js +2 -2
- package/esm/src/security/http/base-handler.d.ts +3 -2
- package/esm/src/security/http/base-handler.d.ts.map +1 -1
- package/esm/src/security/http/base-handler.js +1 -1
- package/esm/src/security/sandbox/project-worker.d.ts +1 -0
- package/esm/src/security/sandbox/project-worker.d.ts.map +1 -1
- package/esm/src/security/sandbox/project-worker.js +17 -1
- package/esm/src/security/sandbox/worker-egress-guard.d.ts +15 -0
- package/esm/src/security/sandbox/worker-egress-guard.d.ts.map +1 -0
- package/esm/src/security/sandbox/worker-egress-guard.js +201 -0
- package/esm/src/security/sandbox/worker-permissions.d.ts +6 -2
- package/esm/src/security/sandbox/worker-permissions.d.ts.map +1 -1
- package/esm/src/security/sandbox/worker-permissions.js +34 -3
- package/esm/src/security/sandbox/worker-pool.d.ts +1 -1
- package/esm/src/security/sandbox/worker-pool.d.ts.map +1 -1
- package/esm/src/security/sandbox/worker-pool.js +35 -9
- package/esm/src/server/handlers/preview/hmr-client-manager.d.ts +3 -2
- package/esm/src/server/handlers/preview/hmr-client-manager.d.ts.map +1 -1
- package/esm/src/server/handlers/preview/hmr.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/preview/hmr.handler.js +4 -1
- package/esm/src/server/handlers/request/api/api-handler-wrapper.js +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/http-fallback.d.ts +32 -0
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/http-fallback.d.ts.map +1 -0
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/http-fallback.js +27 -0
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.js +23 -3
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.d.ts.map +1 -1
- package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.js +15 -15
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Final module-loader persistence phase.
|
|
3
|
+
*
|
|
4
|
+
* @module rendering/orchestrator/module-loader/module-persistence
|
|
5
|
+
*/
|
|
6
|
+
import { join } from "../../../platform/compat/path/index.js";
|
|
7
|
+
import { rendererLogger } from "../../../utils/index.js";
|
|
8
|
+
import { hashCodeHex } from "../../../utils/hash-utils.js";
|
|
9
|
+
import { getModulePathCache, saveModulePathCache, } from "../../../transforms/mdx/esm-module-loader/cache/index.js";
|
|
10
|
+
import { buildMdxEsmPathCacheKey } from "../../../transforms/mdx/esm-module-loader/cache-format.js";
|
|
11
|
+
const logger = rendererLogger.component("module-loader");
|
|
12
|
+
/** Maximum number of directories to track to prevent memory leaks. */
|
|
13
|
+
const MAX_CREATED_DIRS = 5_000;
|
|
14
|
+
/** Cache for created directories to avoid repeated mkdir calls (LRU-style). */
|
|
15
|
+
const createdDirs = new Set();
|
|
16
|
+
/** Prune oldest entries when cache exceeds limit. */
|
|
17
|
+
function pruneCreatedDirs() {
|
|
18
|
+
if (createdDirs.size <= MAX_CREATED_DIRS)
|
|
19
|
+
return;
|
|
20
|
+
const toDelete = createdDirs.size - MAX_CREATED_DIRS;
|
|
21
|
+
let deleted = 0;
|
|
22
|
+
for (const dir of createdDirs) {
|
|
23
|
+
if (deleted >= toDelete)
|
|
24
|
+
break;
|
|
25
|
+
createdDirs.delete(dir);
|
|
26
|
+
deleted++;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function ensureDir(adapter, dir) {
|
|
30
|
+
if (createdDirs.has(dir))
|
|
31
|
+
return;
|
|
32
|
+
try {
|
|
33
|
+
await adapter.fs.mkdir(dir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
catch (_) {
|
|
36
|
+
/* expected: directory might already exist */
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
createdDirs.add(dir);
|
|
40
|
+
pruneCreatedDirs();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Write a transformed module artifact and register cache pointers. */
|
|
44
|
+
export async function persistTransformedModule(input) {
|
|
45
|
+
const transformedHash = hashCodeHex(input.transformedCode).slice(0, 8);
|
|
46
|
+
const relativePath = input.filePath.startsWith(input.projectDir)
|
|
47
|
+
? input.filePath.slice(input.projectDir.length).replace(/^\/+/, "")
|
|
48
|
+
: input.filePath.replace(/^\/+/, "");
|
|
49
|
+
const jsPath = relativePath.replace(/\.(tsx?|jsx|mdx)$/, `.${transformedHash}.js`);
|
|
50
|
+
const tempFilePath = join(input.tmpDir, jsPath);
|
|
51
|
+
const tempDir = tempFilePath.substring(0, tempFilePath.lastIndexOf("/"));
|
|
52
|
+
await ensureDir(input.localAdapter, tempDir);
|
|
53
|
+
try {
|
|
54
|
+
await input.localAdapter.fs.writeFile(tempFilePath, input.transformedCode);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logger.error("Failed to write module:", {
|
|
58
|
+
filePath: input.filePath,
|
|
59
|
+
tempFilePath,
|
|
60
|
+
error: error instanceof Error ? error.message : String(error),
|
|
61
|
+
});
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
if (input.contentSourceId) {
|
|
65
|
+
const normalizedPath = `_vf_modules/${relativePath.replace(/\.(tsx?|jsx|mdx)$/, ".js")}`;
|
|
66
|
+
const mdxCacheKey = buildMdxEsmPathCacheKey(normalizedPath, input.reactVersion);
|
|
67
|
+
const cache = await getModulePathCache(input.tmpDir);
|
|
68
|
+
cache.set(mdxCacheKey, tempFilePath);
|
|
69
|
+
saveModulePathCache(input.tmpDir).catch((err) => {
|
|
70
|
+
logger.debug("Failed to save module cache", { error: String(err) });
|
|
71
|
+
});
|
|
72
|
+
logger.debug("Registered module in MDX-ESM cache", {
|
|
73
|
+
file: input.filePath.slice(-40),
|
|
74
|
+
mdxCacheKey,
|
|
75
|
+
tempFilePath: tempFilePath.slice(-60),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
input.moduleCache.set(input.cacheKey, tempFilePath);
|
|
79
|
+
return tempFilePath;
|
|
80
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform-cache and retry phase for the SSR module loader.
|
|
3
|
+
*
|
|
4
|
+
* @module rendering/orchestrator/module-loader/module-transform-cache
|
|
5
|
+
*/
|
|
6
|
+
import type { RuntimeAdapter } from "../../../platform/adapters/base.js";
|
|
7
|
+
import { initializeTransformCache, setCachedTransformAsync } from "../../../transforms/esm/transform-cache.js";
|
|
8
|
+
import { getHttpBundleCacheDir } from "../../../utils/cache-dir.js";
|
|
9
|
+
/** Pattern to detect unresolved /_vf_modules/ imports that will fail at runtime. */
|
|
10
|
+
export declare const UNRESOLVED_VF_MODULES_RE: RegExp;
|
|
11
|
+
export interface ModuleTransformCacheResult {
|
|
12
|
+
code: string;
|
|
13
|
+
cacheKey: string;
|
|
14
|
+
contentHash: string;
|
|
15
|
+
}
|
|
16
|
+
interface TransformCacheResult {
|
|
17
|
+
code: string;
|
|
18
|
+
cacheHit: boolean;
|
|
19
|
+
bundleManifestId?: string;
|
|
20
|
+
}
|
|
21
|
+
interface BundleValidationResult {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
failedHashes: string[];
|
|
24
|
+
reason?: string;
|
|
25
|
+
source: string;
|
|
26
|
+
}
|
|
27
|
+
interface TransformOptions {
|
|
28
|
+
projectId: string;
|
|
29
|
+
dev: boolean;
|
|
30
|
+
ssr: boolean;
|
|
31
|
+
reactVersion?: string;
|
|
32
|
+
}
|
|
33
|
+
interface PipelineResult {
|
|
34
|
+
code: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ModuleTransformCacheDeps {
|
|
37
|
+
initializeTransformCache: typeof initializeTransformCache;
|
|
38
|
+
getOrComputeTransform: (key: string, compute: () => Promise<string>, ttlSeconds: number) => Promise<TransformCacheResult>;
|
|
39
|
+
transformToESM: (code: string, filePath: string, projectDir: string, adapter: RuntimeAdapter, options: TransformOptions) => Promise<string>;
|
|
40
|
+
validateCachedBundlesByManifestOrCode: (code: string, bundleManifestId: string | undefined, cacheDir: string) => Promise<BundleValidationResult>;
|
|
41
|
+
getHttpBundleCacheDir: typeof getHttpBundleCacheDir;
|
|
42
|
+
setCachedTransformAsync: typeof setCachedTransformAsync;
|
|
43
|
+
runPipeline: (code: string, filePath: string, projectDir: string, options: TransformOptions) => Promise<PipelineResult>;
|
|
44
|
+
}
|
|
45
|
+
export interface TransformModuleCodeWithCacheInput {
|
|
46
|
+
fileContent: string;
|
|
47
|
+
filePath: string;
|
|
48
|
+
projectDir: string;
|
|
49
|
+
effectiveProjectId: string;
|
|
50
|
+
mode: "development" | "production";
|
|
51
|
+
adapter: RuntimeAdapter;
|
|
52
|
+
reactVersion?: string;
|
|
53
|
+
ttlSeconds?: number;
|
|
54
|
+
deps?: ModuleTransformCacheDeps;
|
|
55
|
+
}
|
|
56
|
+
/** Transform module source through the shared cache and stale-cache retry checks. */
|
|
57
|
+
export declare function transformModuleCodeWithCache(input: TransformModuleCodeWithCacheInput): Promise<ModuleTransformCacheResult>;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=module-transform-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-transform-cache.d.ts","sourceRoot":"","sources":["../../../../../src/src/rendering/orchestrator/module-loader/module-transform-cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAIzE,OAAO,EAGL,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAKpE,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,QAA6D,CAAC;AAEnG,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,oBAAoB;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,wBAAwB;IACvC,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;IAC1D,qBAAqB,EAAE,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,EAC9B,UAAU,EAAE,MAAM,KACf,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,cAAc,EAAE,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,qCAAqC,EAAE,CACrC,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrC,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,WAAW,EAAE,CACX,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9B;AAeD,MAAM,WAAW,iCAAiC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAED,qFAAqF;AACrF,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,0BAA0B,CAAC,CAoHrC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform-cache and retry phase for the SSR module loader.
|
|
3
|
+
*
|
|
4
|
+
* @module rendering/orchestrator/module-loader/module-transform-cache
|
|
5
|
+
*/
|
|
6
|
+
import { rendererLogger } from "../../../utils/index.js";
|
|
7
|
+
import { hashCodeHex } from "../../../utils/hash-utils.js";
|
|
8
|
+
import { transformToESM } from "../../../transforms/esm-transform.js";
|
|
9
|
+
import { generateCacheKey as generateTransformCacheKey, getOrComputeTransform, initializeTransformCache, setCachedTransformAsync, } from "../../../transforms/esm/transform-cache.js";
|
|
10
|
+
import { validateCachedBundlesByManifestOrCode } from "../../../transforms/esm/cached-bundle-validation.js";
|
|
11
|
+
import { getHttpBundleCacheDir } from "../../../utils/cache-dir.js";
|
|
12
|
+
import { TRANSFORM_DISTRIBUTED_TTL_SEC } from "../../../utils/constants/cache.js";
|
|
13
|
+
const logger = rendererLogger.component("module-loader");
|
|
14
|
+
/** Pattern to detect unresolved /_vf_modules/ imports that will fail at runtime. */
|
|
15
|
+
export const UNRESOLVED_VF_MODULES_RE = /from\s*["']((?:file:\/\/)?\/?\/?_vf_modules\/[^"']+)["']/;
|
|
16
|
+
const defaultDeps = {
|
|
17
|
+
initializeTransformCache,
|
|
18
|
+
getOrComputeTransform,
|
|
19
|
+
transformToESM,
|
|
20
|
+
validateCachedBundlesByManifestOrCode,
|
|
21
|
+
getHttpBundleCacheDir,
|
|
22
|
+
setCachedTransformAsync,
|
|
23
|
+
runPipeline: async (code, filePath, projectDir, options) => {
|
|
24
|
+
const { runPipeline } = await import("../../../transforms/pipeline/index.js");
|
|
25
|
+
return await runPipeline(code, filePath, projectDir, options);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
/** Transform module source through the shared cache and stale-cache retry checks. */
|
|
29
|
+
export async function transformModuleCodeWithCache(input) {
|
|
30
|
+
const deps = input.deps ?? defaultDeps;
|
|
31
|
+
const ttlSeconds = input.ttlSeconds ?? TRANSFORM_DISTRIBUTED_TTL_SEC;
|
|
32
|
+
const contentHash = hashCodeHex(input.fileContent);
|
|
33
|
+
const scopedPath = `${input.effectiveProjectId}:${input.filePath}`;
|
|
34
|
+
const cacheKey = generateTransformCacheKey(scopedPath, contentHash, true);
|
|
35
|
+
const transformOptions = {
|
|
36
|
+
projectId: input.effectiveProjectId,
|
|
37
|
+
dev: input.mode === "development",
|
|
38
|
+
ssr: true,
|
|
39
|
+
reactVersion: input.reactVersion,
|
|
40
|
+
};
|
|
41
|
+
await deps.initializeTransformCache();
|
|
42
|
+
const transformResult = await deps.getOrComputeTransform(cacheKey, () => {
|
|
43
|
+
logger.debug("Transform cache miss, transforming", { filePath: input.filePath });
|
|
44
|
+
return deps.transformToESM(input.fileContent, input.filePath, input.projectDir, input.adapter, transformOptions);
|
|
45
|
+
}, ttlSeconds);
|
|
46
|
+
let transformedCode = transformResult.code;
|
|
47
|
+
if (transformResult.cacheHit) {
|
|
48
|
+
const validation = await deps.validateCachedBundlesByManifestOrCode(transformedCode, transformResult.bundleManifestId, deps.getHttpBundleCacheDir());
|
|
49
|
+
if (!validation.valid) {
|
|
50
|
+
logger.warn("Cached HTTP bundle validation failed, re-transforming", {
|
|
51
|
+
filePath: input.filePath,
|
|
52
|
+
manifestId: transformResult.bundleManifestId?.slice(0, 12),
|
|
53
|
+
failedHashes: validation.failedHashes,
|
|
54
|
+
reason: validation.reason,
|
|
55
|
+
source: validation.source,
|
|
56
|
+
});
|
|
57
|
+
transformedCode = await deps.transformToESM(input.fileContent, input.filePath, input.projectDir, input.adapter, transformOptions);
|
|
58
|
+
deps.setCachedTransformAsync(cacheKey, transformedCode, contentHash, ttlSeconds).catch((error) => {
|
|
59
|
+
logger.debug("Failed to update transform cache after re-transform", {
|
|
60
|
+
filePath: input.filePath,
|
|
61
|
+
error,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// CRITICAL: Validate that no unresolved /_vf_modules/ imports remain after transform.
|
|
67
|
+
// These imports should have been resolved to file:// paths by ssrVfModulesPlugin.
|
|
68
|
+
// If they're still present, retry the transform bypassing all caches.
|
|
69
|
+
if (UNRESOLVED_VF_MODULES_RE.test(transformedCode)) {
|
|
70
|
+
const match = transformedCode.match(UNRESOLVED_VF_MODULES_RE);
|
|
71
|
+
const unresolvedImport = match?.[1] || "unknown";
|
|
72
|
+
logger.warn("[ModuleLoader] Transform has unresolved _vf_modules import, retrying without cache", {
|
|
73
|
+
filePath: input.filePath.slice(-60),
|
|
74
|
+
unresolvedImport: unresolvedImport.slice(0, 80),
|
|
75
|
+
cacheHit: transformResult.cacheHit,
|
|
76
|
+
});
|
|
77
|
+
const pipelineResult = await deps.runPipeline(input.fileContent, input.filePath, input.projectDir, transformOptions);
|
|
78
|
+
transformedCode = pipelineResult.code;
|
|
79
|
+
if (UNRESOLVED_VF_MODULES_RE.test(transformedCode)) {
|
|
80
|
+
const retryMatch = transformedCode.match(UNRESOLVED_VF_MODULES_RE);
|
|
81
|
+
logger.error("Transform still has unresolved _vf_modules after retry", {
|
|
82
|
+
filePath: input.filePath.slice(-60),
|
|
83
|
+
unresolvedImport: retryMatch?.[1]?.slice(0, 80) || "unknown",
|
|
84
|
+
hint: "Check that framework sources exist in dist/framework-src/ and ssrVfModulesPlugin is running",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
deps.setCachedTransformAsync(cacheKey, transformedCode, hashCodeHex(transformedCode).slice(0, 16), ttlSeconds).catch((error) => {
|
|
89
|
+
logger.debug("Failed to update cache after retry", {
|
|
90
|
+
filePath: input.filePath,
|
|
91
|
+
error,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { code: transformedCode, cacheKey, contentHash };
|
|
97
|
+
}
|
|
@@ -4,6 +4,7 @@ import { type APIContext } from "./context-builder.js";
|
|
|
4
4
|
import type { APIRoute } from "./module-loader/types.js";
|
|
5
5
|
import { loadHandlerModule } from "./module-loader/loader.js";
|
|
6
6
|
import { discoverAppRoutes, discoverPagesRoutes } from "./route-discovery.js";
|
|
7
|
+
import type { HandlerContext } from "../../types/index.js";
|
|
7
8
|
export type { APIContext, APIRoute };
|
|
8
9
|
/**
|
|
9
10
|
* Injection interface for testing APIRouteHandler dependencies
|
|
@@ -40,7 +41,7 @@ export declare class APIRouteHandler {
|
|
|
40
41
|
private configPromise;
|
|
41
42
|
constructor(projectDir: string, adapter?: RuntimeAdapter);
|
|
42
43
|
initialize(): Promise<void>;
|
|
43
|
-
handle(request: Request): Promise<Response | null>;
|
|
44
|
+
handle(request: Request, ctx?: HandlerContext): Promise<Response | null>;
|
|
44
45
|
private loadHandler;
|
|
45
46
|
clearCache(): void;
|
|
46
47
|
destroy(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMlD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAMlD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAErC;;GAEG;AACH,UAAU,mBAAmB;IAC3B,iBAAiB,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAC7C,mBAAmB,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACjD,iBAAiB,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAC7C,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;CAC9B;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAE3E;AAWD,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAE3E,qBAAa,eAAe;IAgBxB,OAAO,CAAC,UAAU;IAfpB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,UAAU,CAA6E;IAC/F,OAAO,CAAC,gBAAgB,CAAuB;IAE/C,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,iBAAiB,CAA8B;IAEvD,OAAO,CAAC,MAAM,CAAsD;IACpE,OAAO,CAAC,aAAa,CAA8B;gBAGzC,UAAU,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,cAAc;IAM1B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAgD3B,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA0FxE,OAAO,CAAC,WAAW;IAuCnB,UAAU,IAAI,IAAI;IAKlB,OAAO,IAAI,IAAI;YAKD,aAAa;YAsBb,gBAAgB;YAOhB,cAAc;YAcd,YAAY;YAOZ,cAAc;CAW7B;AAED,OAAO,EACL,UAAU,EACV,SAAS,EACT,mBAAmB,IAAI,WAAW,EAClC,YAAY,IAAI,IAAI,EACpB,QAAQ,EACR,gBAAgB,IAAI,QAAQ,EAC5B,YAAY,GACb,MAAM,yCAAyC,CAAC"}
|
|
@@ -79,7 +79,7 @@ export class APIRouteHandler {
|
|
|
79
79
|
logger.debug("Route handler initialized");
|
|
80
80
|
}, { "api.projectDir": this.projectDir });
|
|
81
81
|
}
|
|
82
|
-
handle(request) {
|
|
82
|
+
handle(request, ctx) {
|
|
83
83
|
const { pathname } = new URL(request.url);
|
|
84
84
|
return withSpan("api.handle", async () => {
|
|
85
85
|
const adapter = await this.ensureAdapter();
|
|
@@ -132,6 +132,7 @@ export class APIRouteHandler {
|
|
|
132
132
|
const isolationOptions = {
|
|
133
133
|
modulePath: match.route.page,
|
|
134
134
|
projectDir: this.projectDir,
|
|
135
|
+
isLocalProject: ctx?.isLocalProject,
|
|
135
136
|
};
|
|
136
137
|
const response = isAppRoute
|
|
137
138
|
? await executeAppRoute(handler, request, match, pathname, adapter, isolationOptions)
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { RuntimeAdapter } from "../../platform/adapters/base.js";
|
|
2
2
|
import type { RouteMatch } from "./api-route-matcher.js";
|
|
3
3
|
import type { APIRoute } from "./module-loader/types.js";
|
|
4
|
+
export declare function __resetInProcessIsolationWarningForTests(): void;
|
|
4
5
|
export interface ExecuteRouteOptions {
|
|
5
6
|
/** Absolute path to the handler module on disk (for isolated execution) */
|
|
6
7
|
modulePath?: string;
|
|
7
8
|
/** Project directory (for isolated execution scope) */
|
|
8
9
|
projectDir?: string;
|
|
10
|
+
/** Whether the handler module belongs to a trusted local development project. */
|
|
11
|
+
isLocalProject?: boolean;
|
|
9
12
|
}
|
|
10
13
|
export declare function executeAppRoute(handler: APIRoute, request: Request, match: RouteMatch, pathname: string, adapter: RuntimeAdapter, options?: ExecuteRouteOptions): Promise<Response>;
|
|
11
14
|
export declare function executePagesRoute(handler: APIRoute, request: Request, match: RouteMatch, pathname: string, adapter: RuntimeAdapter, projectDir?: string, options?: ExecuteRouteOptions): Promise<Response>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-executor.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/route-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EACV,QAAQ,EAKT,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"route-executor.d.ts","sourceRoot":"","sources":["../../../../src/src/routing/api/route-executor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,KAAK,EACV,QAAQ,EAKT,MAAM,0BAA0B,CAAC;AAoJlC,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D;AAqND,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CA8CnB;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAwCnB"}
|
|
@@ -106,6 +106,32 @@ function checkContentLengthLimit(request) {
|
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
let warnedUntrustedInProcessExecution = false;
|
|
110
|
+
export function __resetInProcessIsolationWarningForTests() {
|
|
111
|
+
warnedUntrustedInProcessExecution = false;
|
|
112
|
+
}
|
|
113
|
+
function warnIfUntrustedInProcessExecution(routeKind, pathname, options) {
|
|
114
|
+
if (options?.isLocalProject !== false)
|
|
115
|
+
return;
|
|
116
|
+
if (isWorkerIsolationEnabled())
|
|
117
|
+
return;
|
|
118
|
+
if (warnedUntrustedInProcessExecution)
|
|
119
|
+
return;
|
|
120
|
+
warnedUntrustedInProcessExecution = true;
|
|
121
|
+
try {
|
|
122
|
+
logger.warn("Untrusted project code is executing in-process with worker isolation disabled. Enable WORKER_ISOLATION_ENABLED=1 and WORKER_ISOLATION_API=1 to run project routes in a permission-restricted worker.", {
|
|
123
|
+
modulePath: options.modulePath,
|
|
124
|
+
pathname,
|
|
125
|
+
projectDir: options.projectDir,
|
|
126
|
+
requiredEnv: ["WORKER_ISOLATION_ENABLED", "WORKER_ISOLATION_API"],
|
|
127
|
+
routeKind,
|
|
128
|
+
workerIsolationEnabled: false,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// A diagnostic warning must not prevent the API route from running.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
109
135
|
async function readBodyWithSizeGuard(request) {
|
|
110
136
|
if (!request.body)
|
|
111
137
|
return null;
|
|
@@ -237,6 +263,7 @@ export function executeAppRoute(handler, request, match, pathname, adapter, opti
|
|
|
237
263
|
return executeAppRouteIsolated(options.modulePath, request, match, pathname, adapter, options.projectDir);
|
|
238
264
|
}
|
|
239
265
|
// Default path: execute in main process (existing behavior)
|
|
266
|
+
warnIfUntrustedInProcessExecution("app", pathname, options);
|
|
240
267
|
const method = request.method.toUpperCase();
|
|
241
268
|
return withSpan("api.executeAppRoute", async () => {
|
|
242
269
|
const handlerModule = handler;
|
|
@@ -266,6 +293,7 @@ export function executePagesRoute(handler, request, match, pathname, adapter, pr
|
|
|
266
293
|
return executePagesRouteIsolated(options.modulePath, request, match, pathname, adapter, options.projectDir ?? projectDir);
|
|
267
294
|
}
|
|
268
295
|
// Default path: execute in main process (existing behavior)
|
|
296
|
+
warnIfUntrustedInProcessExecution("pages", pathname, options);
|
|
269
297
|
const method = request.method;
|
|
270
298
|
return withSpan("api.executePagesRoute", async () => {
|
|
271
299
|
const methodHandler = handler[method] ?? handler.default;
|
|
@@ -271,7 +271,7 @@ export function generateText(options) {
|
|
|
271
271
|
return resolveDirectTools(options.tools).then((tools) => options.model.doGenerate({
|
|
272
272
|
prompt: toRuntimePrompt(normalizeSystemPrompt(options.system), options.messages),
|
|
273
273
|
maxOutputTokens: options.maxOutputTokens,
|
|
274
|
-
temperature: options.temperature,
|
|
274
|
+
...(options.temperature === undefined ? {} : { temperature: options.temperature }),
|
|
275
275
|
topP: options.topP,
|
|
276
276
|
topK: options.topK,
|
|
277
277
|
stopSequences: options.stopSequences,
|
|
@@ -293,7 +293,7 @@ export function streamText(options) {
|
|
|
293
293
|
const directResultPromise = resolveDirectTools(options.tools).then((tools) => options.model.doStream({
|
|
294
294
|
prompt: toRuntimePrompt(normalizeSystemPrompt(options.system), options.messages),
|
|
295
295
|
maxOutputTokens: options.maxOutputTokens,
|
|
296
|
-
temperature: options.temperature,
|
|
296
|
+
...(options.temperature === undefined ? {} : { temperature: options.temperature }),
|
|
297
297
|
topP: options.topP,
|
|
298
298
|
topK: options.topK,
|
|
299
299
|
stopSequences: options.stopSequences,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Handler, HandlerContext, HandlerMetadata, HandlerResult } from "../../types/index.js";
|
|
2
|
+
import type { WebSocketUpgradeResponse } from "../../platform/adapters/base.js";
|
|
2
3
|
import { ResponseBuilder } from "./response/index.js";
|
|
3
4
|
export interface HandlerHelpers {
|
|
4
5
|
createResponseBuilder: (ctx: HandlerContext, nonce?: string) => ResponseBuilder;
|
|
5
|
-
respond: (response: Response, metadata?: Record<string, unknown>) => HandlerResult;
|
|
6
|
+
respond: (response: Response | WebSocketUpgradeResponse, metadata?: Record<string, unknown>) => HandlerResult;
|
|
6
7
|
logDebug: (message: string, extra?: Record<string, unknown>, ctx?: HandlerContext) => void;
|
|
7
8
|
getErrorMessage: (error: unknown) => string;
|
|
8
9
|
continue: () => HandlerResult;
|
|
@@ -19,7 +20,7 @@ export declare abstract class BaseHandler implements Handler {
|
|
|
19
20
|
protected logInfo(message: string, extra?: Record<string, unknown>, _ctx?: HandlerContext): void;
|
|
20
21
|
protected getErrorMessage(error: unknown): string;
|
|
21
22
|
protected continue(): HandlerResult;
|
|
22
|
-
protected respond(response: Response, metadata?: Record<string, unknown>): HandlerResult;
|
|
23
|
+
protected respond(response: Response | WebSocketUpgradeResponse, metadata?: Record<string, unknown>): HandlerResult;
|
|
23
24
|
protected withProxyContext<T>(ctx: HandlerContext, fn: () => Promise<T>, options?: {
|
|
24
25
|
requireToken?: boolean;
|
|
25
26
|
}): Promise<T>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/security/http/base-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,eAAe,EACf,aAAa,EAEd,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"base-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/security/http/base-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,eAAe,EACf,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,qBAAqB,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,eAAe,CAAC;IAChF,OAAO,EAAE,CACP,QAAQ,EAAE,QAAQ,GAAG,wBAAwB,EAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,aAAa,CAAC;IACnB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3F,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;IAC5C,QAAQ,EAAE,MAAM,aAAa,CAAC;CAC/B;AAED,8BAAsB,WAAY,YAAW,OAAO;IAClD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IAEnC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAMxC;IAEF,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAE1E,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IAYlE,OAAO,CAAC,cAAc;IAmBtB,SAAS,CAAC,qBAAqB,CAC7B,GAAG,EAAE,cAAc,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,eAAe;IAWlB,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,cAAc,GAAG,IAAI;IAKhG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI;IAIhG,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI;IAIhG,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAKjD,SAAS,CAAC,QAAQ,IAAI,aAAa;IAInC,SAAS,CAAC,OAAO,CACf,QAAQ,EAAE,QAAQ,GAAG,wBAAwB,EAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,aAAa;IAIhB,SAAS,CAAC,gBAAgB,CAAC,CAAC,EAC1B,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAO,GACvC,OAAO,CAAC,CAAC,CAAC;CAyEd"}
|
|
@@ -64,7 +64,7 @@ export class BaseHandler {
|
|
|
64
64
|
return { continue: true };
|
|
65
65
|
}
|
|
66
66
|
respond(response, metadata) {
|
|
67
|
-
return { response, continue: false, metadata };
|
|
67
|
+
return { response: response, continue: false, metadata };
|
|
68
68
|
}
|
|
69
69
|
withProxyContext(ctx, fn, options = {}) {
|
|
70
70
|
// Framework-owned token: bypass project env overlay so proxy mode works
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-worker.d.ts","sourceRoot":"","sources":["../../../../src/src/security/sandbox/project-worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"project-worker.d.ts","sourceRoot":"","sources":["../../../../src/src/security/sandbox/project-worker.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAGf,MAAM,mBAAmB,CAAC;AAa3B,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAcD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;AAEtE,qBAAa,aAAa;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,cAAc,CAAoC;IAC1D,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,EAAE,oBAAoB;IAOzC,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,IAAI,kBAAkB,IAAI,OAAO,CAEhC;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;IA8Bb;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAqCxD;;;;;;;OAOG;IACH,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC,UAAU,CAAC;IA+FjE;;OAEG;IACG,SAAS,CAAC,SAAS,SAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BpD;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAKxB;;OAEG;IACH,SAAS,IAAI,IAAI;IAuBjB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;IA+CrB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,gBAAgB;CAazB"}
|
|
@@ -12,8 +12,11 @@ import { serverLogger } from "../../utils/index.js";
|
|
|
12
12
|
import { isCompiledBinary } from "../../utils/index.js";
|
|
13
13
|
import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
14
14
|
import { TIMEOUT_ERROR, UNKNOWN_ERROR } from "../../errors/index.js";
|
|
15
|
+
import { getHostEnv } from "../../platform/compat/process.js";
|
|
16
|
+
import { isInternalEgressOverrideEnabled, WORKER_INTERNAL_EGRESS_OVERRIDE_ENV, } from "./worker-egress-guard.js";
|
|
15
17
|
const logger = serverLogger.component("project-worker");
|
|
16
18
|
const textEncoder = new TextEncoder();
|
|
19
|
+
const WORKER_ALLOW_INTERNAL_EGRESS_PARAM = "allowInternalEgress";
|
|
17
20
|
export class ProjectWorker {
|
|
18
21
|
projectId;
|
|
19
22
|
worker = null;
|
|
@@ -262,7 +265,20 @@ export class ProjectWorker {
|
|
|
262
265
|
}
|
|
263
266
|
// Use import.meta.resolve to get the absolute URL of the worker script.
|
|
264
267
|
// This works in both `deno run` and `deno compile` contexts.
|
|
265
|
-
return globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).resolve("./worker-script.ts");
|
|
268
|
+
return this.withEgressPolicy(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).resolve("./worker-script.ts"));
|
|
269
|
+
}
|
|
270
|
+
withEgressPolicy(workerScriptUrl) {
|
|
271
|
+
if (!isInternalEgressOverrideEnabled(getHostEnv(WORKER_INTERNAL_EGRESS_OVERRIDE_ENV))) {
|
|
272
|
+
return workerScriptUrl;
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
const url = new URL(workerScriptUrl);
|
|
276
|
+
url.searchParams.set(WORKER_ALLOW_INTERNAL_EGRESS_PARAM, "1");
|
|
277
|
+
return url.toString();
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return workerScriptUrl;
|
|
281
|
+
}
|
|
266
282
|
}
|
|
267
283
|
handleMessage(data) {
|
|
268
284
|
if (data.type === "pong") {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const WORKER_INTERNAL_EGRESS_OVERRIDE_ENV = "VERYFRONT_WORKER_ALLOW_INTERNAL_EGRESS";
|
|
2
|
+
export declare class WorkerEgressBlockedError extends Error {
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export type ResolveWorkerHost = (hostname: string) => Promise<string[]>;
|
|
6
|
+
export interface WorkerEgressGuardOptions {
|
|
7
|
+
allowInternalEgress?: boolean;
|
|
8
|
+
resolveHost?: ResolveWorkerHost;
|
|
9
|
+
}
|
|
10
|
+
export declare function isInternalEgressOverrideEnabled(value: string | undefined): boolean;
|
|
11
|
+
export declare function isInternalEgressIp(address: string): boolean;
|
|
12
|
+
export declare function assertWorkerEgressAllowed(target: string | URL | Request, options?: WorkerEgressGuardOptions): Promise<void>;
|
|
13
|
+
export declare function assertWorkerHostEgressAllowed(hostname: string, options?: WorkerEgressGuardOptions): Promise<void>;
|
|
14
|
+
export declare function installWorkerEgressGuard(options?: WorkerEgressGuardOptions): void;
|
|
15
|
+
//# sourceMappingURL=worker-egress-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-egress-guard.d.ts","sourceRoot":"","sources":["../../../../src/src/security/sandbox/worker-egress-guard.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,mCAAmC,2CAA2C,CAAC;AAE5F,qBAAa,wBAAyB,SAAQ,KAAK;IACxC,IAAI,SAA8B;CAC5C;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAExE,MAAM,WAAW,wBAAwB;IACvC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAWD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAWlF;AAuDD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAK3D;AA4CD,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC9B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,6BAA6B,CACjD,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAgBD,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,wBAA6B,GAAG,IAAI,CA+CrF"}
|