veryfront 0.1.74 → 0.1.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/README.md +2 -0
  2. package/esm/cli/commands/files/command.d.ts +3 -3
  3. package/esm/cli/commands/knowledge/command.d.ts +2 -0
  4. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  5. package/esm/cli/commands/knowledge/command.js +64 -1
  6. package/esm/deno.d.ts +7 -0
  7. package/esm/deno.js +13 -6
  8. package/esm/src/data/data-fetcher.d.ts +11 -1
  9. package/esm/src/data/data-fetcher.d.ts.map +1 -1
  10. package/esm/src/data/data-fetcher.js +5 -2
  11. package/esm/src/data/index.d.ts +1 -1
  12. package/esm/src/data/index.d.ts.map +1 -1
  13. package/esm/src/data/server-data-fetcher.d.ts +14 -1
  14. package/esm/src/data/server-data-fetcher.d.ts.map +1 -1
  15. package/esm/src/data/server-data-fetcher.js +65 -3
  16. package/esm/src/jobs/index.d.ts +34 -0
  17. package/esm/src/jobs/index.d.ts.map +1 -0
  18. package/esm/src/jobs/index.js +33 -0
  19. package/esm/src/jobs/jobs-client.d.ts +134 -0
  20. package/esm/src/jobs/jobs-client.d.ts.map +1 -0
  21. package/esm/src/jobs/jobs-client.js +218 -0
  22. package/esm/src/jobs/schemas.d.ts +1304 -0
  23. package/esm/src/jobs/schemas.d.ts.map +1 -0
  24. package/esm/src/jobs/schemas.js +159 -0
  25. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts +4 -0
  26. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.d.ts.map +1 -1
  27. package/esm/src/platform/adapters/veryfront-api-client/retry-handler.js +12 -6
  28. package/esm/src/proxy/handler.d.ts.map +1 -1
  29. package/esm/src/proxy/handler.js +21 -21
  30. package/esm/src/rendering/orchestrator/lifecycle.d.ts +4 -0
  31. package/esm/src/rendering/orchestrator/lifecycle.d.ts.map +1 -1
  32. package/esm/src/rendering/orchestrator/lifecycle.js +8 -0
  33. package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
  34. package/esm/src/rendering/orchestrator/pipeline.js +6 -1
  35. package/esm/src/rendering/orchestrator/ssr-orchestrator.d.ts +26 -1
  36. package/esm/src/rendering/orchestrator/ssr-orchestrator.d.ts.map +1 -1
  37. package/esm/src/rendering/orchestrator/ssr-orchestrator.js +77 -1
  38. package/esm/src/routing/api/handler.d.ts.map +1 -1
  39. package/esm/src/routing/api/handler.js +6 -2
  40. package/esm/src/routing/api/route-executor.d.ts +8 -2
  41. package/esm/src/routing/api/route-executor.d.ts.map +1 -1
  42. package/esm/src/routing/api/route-executor.js +158 -3
  43. package/esm/src/security/deno-permissions.d.ts +7 -1
  44. package/esm/src/security/deno-permissions.d.ts.map +1 -1
  45. package/esm/src/security/deno-permissions.js +12 -1
  46. package/esm/src/security/sandbox/project-worker.d.ts +61 -0
  47. package/esm/src/security/sandbox/project-worker.d.ts.map +1 -0
  48. package/esm/src/security/sandbox/project-worker.js +318 -0
  49. package/esm/src/security/sandbox/worker-permissions.d.ts +30 -0
  50. package/esm/src/security/sandbox/worker-permissions.d.ts.map +1 -0
  51. package/esm/src/security/sandbox/worker-permissions.js +63 -0
  52. package/esm/src/security/sandbox/worker-pool.d.ts +87 -0
  53. package/esm/src/security/sandbox/worker-pool.d.ts.map +1 -0
  54. package/esm/src/security/sandbox/worker-pool.js +359 -0
  55. package/esm/src/security/sandbox/worker-types.d.ts +167 -0
  56. package/esm/src/security/sandbox/worker-types.d.ts.map +1 -0
  57. package/esm/src/security/sandbox/worker-types.js +19 -0
  58. package/esm/src/server/handlers/request/internal-tasks-list.handler.d.ts +11 -0
  59. package/esm/src/server/handlers/request/internal-tasks-list.handler.d.ts.map +1 -0
  60. package/esm/src/server/handlers/request/internal-tasks-list.handler.js +72 -0
  61. package/esm/src/server/project-env/storage.d.ts +6 -0
  62. package/esm/src/server/project-env/storage.d.ts.map +1 -1
  63. package/esm/src/server/project-env/storage.js +8 -0
  64. package/esm/src/server/runtime-handler/index.d.ts +1 -1
  65. package/esm/src/server/runtime-handler/index.d.ts.map +1 -1
  66. package/esm/src/server/runtime-handler/index.js +3 -0
  67. package/esm/src/server/runtime-handler/project-isolation.d.ts +5 -0
  68. package/esm/src/server/runtime-handler/project-isolation.d.ts.map +1 -1
  69. package/esm/src/server/runtime-handler/project-isolation.js +44 -0
  70. package/esm/src/server/shared/renderer/memory/pressure.d.ts +7 -0
  71. package/esm/src/server/shared/renderer/memory/pressure.d.ts.map +1 -1
  72. package/esm/src/server/shared/renderer/memory/pressure.js +7 -0
  73. package/esm/src/task/control-plane.d.ts +105 -0
  74. package/esm/src/task/control-plane.d.ts.map +1 -0
  75. package/esm/src/task/control-plane.js +52 -0
  76. package/esm/src/task/types.d.ts +6 -0
  77. package/esm/src/task/types.d.ts.map +1 -1
  78. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts +4 -4
  79. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts.map +1 -1
  80. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.js +15 -15
  81. package/esm/src/utils/index.d.ts +10 -1
  82. package/esm/src/utils/index.d.ts.map +1 -1
  83. package/esm/src/utils/index.js +9 -1
  84. package/esm/src/utils/logger/index.d.ts +1 -1
  85. package/esm/src/utils/logger/index.d.ts.map +1 -1
  86. package/esm/src/utils/logger/index.js +1 -1
  87. package/esm/src/utils/logger/logger.d.ts +14 -0
  88. package/esm/src/utils/logger/logger.d.ts.map +1 -1
  89. package/esm/src/utils/logger/logger.js +17 -0
  90. package/esm/src/workflow/claude-code/tool.d.ts +5 -5
  91. package/package.json +8 -1
  92. package/src/cli/commands/knowledge/command.ts +76 -1
  93. package/src/deno.js +13 -6
  94. package/src/src/data/data-fetcher.ts +18 -2
  95. package/src/src/data/index.ts +1 -1
  96. package/src/src/data/server-data-fetcher.ts +106 -3
  97. package/src/src/jobs/index.ts +85 -0
  98. package/src/src/jobs/jobs-client.ts +503 -0
  99. package/src/src/jobs/schemas.ts +202 -0
  100. package/src/src/platform/adapters/veryfront-api-client/retry-handler.ts +15 -6
  101. package/src/src/proxy/handler.ts +27 -19
  102. package/src/src/rendering/orchestrator/lifecycle.ts +11 -0
  103. package/src/src/rendering/orchestrator/pipeline.ts +7 -2
  104. package/src/src/rendering/orchestrator/ssr-orchestrator.ts +119 -0
  105. package/src/src/routing/api/handler.ts +16 -3
  106. package/src/src/routing/api/route-executor.ts +258 -1
  107. package/src/src/security/deno-permissions.ts +13 -1
  108. package/src/src/security/sandbox/project-worker.ts +416 -0
  109. package/src/src/security/sandbox/worker-permissions.ts +77 -0
  110. package/src/src/security/sandbox/worker-pool.ts +459 -0
  111. package/src/src/security/sandbox/worker-types.ts +212 -0
  112. package/src/src/server/handlers/request/internal-tasks-list.handler.ts +103 -0
  113. package/src/src/server/project-env/storage.ts +9 -0
  114. package/src/src/server/runtime-handler/index.ts +3 -0
  115. package/src/src/server/runtime-handler/project-isolation.ts +53 -0
  116. package/src/src/server/shared/renderer/memory/pressure.ts +8 -0
  117. package/src/src/task/control-plane.ts +76 -0
  118. package/src/src/task/types.ts +6 -0
  119. package/src/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.ts +18 -12
  120. package/src/src/utils/index.ts +11 -0
  121. package/src/src/utils/logger/index.ts +1 -0
  122. package/src/src/utils/logger/logger.ts +34 -0
@@ -1,11 +1,22 @@
1
1
  import { withSpan } from "../observability/tracing/otlp-setup.js";
2
2
  import { SpanNames } from "../observability/tracing/span-names.js";
3
3
  import { CacheManager } from "./data-fetching-cache.js";
4
- import { ServerDataFetcher } from "./server-data-fetcher.js";
4
+ import { ServerDataFetcher, type ServerDataFetchOptions } from "./server-data-fetcher.js";
5
5
  import { StaticDataFetcher } from "./static-data-fetcher.js";
6
6
  import { StaticPathsFetcher } from "./static-paths-fetcher.js";
7
7
  import type { DataContext, DataResult, PageWithData, StaticPathsResult } from "./types.js";
8
8
 
9
+ /**
10
+ * Options for isolated data fetching. Passed through to ServerDataFetcher
11
+ * when worker isolation is enabled.
12
+ */
13
+ export interface FetchDataOptions {
14
+ /** Absolute path to the module containing getServerData */
15
+ modulePath?: string;
16
+ /** Project directory for worker scoping */
17
+ projectDir?: string;
18
+ }
19
+
9
20
  export class DataFetcher {
10
21
  private cacheManager: CacheManager;
11
22
  private serverFetcher: ServerDataFetcher;
@@ -23,6 +34,7 @@ export class DataFetcher {
23
34
  pageModule: PageWithData,
24
35
  context: DataContext,
25
36
  mode: "development" | "production" = "development",
37
+ options?: FetchDataOptions,
26
38
  ): Promise<DataResult> {
27
39
  const preferServerData = mode === "development" || !pageModule.getStaticData;
28
40
  const useServer = preferServerData && !!pageModule.getServerData;
@@ -34,10 +46,14 @@ export class DataFetcher {
34
46
  ? "static"
35
47
  : "none";
36
48
 
49
+ const isolationOptions: ServerDataFetchOptions | undefined = options
50
+ ? { modulePath: options.modulePath, projectDir: options.projectDir }
51
+ : undefined;
52
+
37
53
  return withSpan(
38
54
  SpanNames.DATA_FETCH,
39
55
  () => {
40
- if (useServer) return this.serverFetcher.fetch(pageModule, context);
56
+ if (useServer) return this.serverFetcher.fetch(pageModule, context, isolationOptions);
41
57
  if (useStatic) return this.staticFetcher.fetch(pageModule, context);
42
58
  return Promise.resolve({ props: {} });
43
59
  },
@@ -13,5 +13,5 @@ export type {
13
13
  PageWithData,
14
14
  StaticPathsResult,
15
15
  } from "./types.js";
16
- export { DataFetcher } from "./data-fetcher.js";
16
+ export { DataFetcher, type FetchDataOptions } from "./data-fetcher.js";
17
17
  export { notFound, redirect } from "./helpers.js";
@@ -1,12 +1,32 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
1
2
  import type { DataContext, DataResult, PageWithData } from "./types.js";
2
3
  import { serverLogger } from "../utils/index.js";
3
4
  import { DATA_FETCH_TIMEOUT_MS } from "../config/defaults.js";
4
5
  import { TimeoutError, withTimeoutThrow } from "../rendering/utils/stream-utils.js";
5
6
  import { withSpan } from "../observability/tracing/otlp-setup.js";
6
7
  import { CircuitBreakerOpen, getCircuitBreaker } from "../utils/circuit-breaker.js";
8
+ import { getWorkerPool, isDataIsolationEnabled } from "../security/sandbox/worker-pool.js";
9
+ import {
10
+ MAX_WORKER_BODY_BYTES,
11
+ type WorkerResponse,
12
+ } from "../security/sandbox/worker-types.js";
13
+
14
+ /**
15
+ * Options for isolated data fetching through Worker pool.
16
+ */
17
+ export interface ServerDataFetchOptions {
18
+ /** Absolute path to the module containing getServerData */
19
+ modulePath?: string;
20
+ /** Project directory for worker scoping */
21
+ projectDir?: string;
22
+ }
7
23
 
8
24
  export class ServerDataFetcher {
9
- fetch(pageModule: PageWithData, context: DataContext): Promise<DataResult> {
25
+ fetch(
26
+ pageModule: PageWithData,
27
+ context: DataContext,
28
+ options?: ServerDataFetchOptions,
29
+ ): Promise<DataResult> {
10
30
  if (typeof pageModule.getServerData !== "function") {
11
31
  return Promise.resolve({ props: {} });
12
32
  }
@@ -20,6 +40,11 @@ export class ServerDataFetcher {
20
40
  successThreshold: 2,
21
41
  });
22
42
 
43
+ // Choose isolated or direct execution
44
+ const useIsolation = isDataIsolationEnabled() &&
45
+ !!options?.modulePath &&
46
+ !!options?.projectDir;
47
+
23
48
  return withSpan(
24
49
  "data.fetch_server",
25
50
  async () => {
@@ -28,7 +53,9 @@ export class ServerDataFetcher {
28
53
  try {
29
54
  const result = await circuitBreaker.execute(() =>
30
55
  withTimeoutThrow(
31
- Promise.resolve(pageModule.getServerData!(context)),
56
+ useIsolation
57
+ ? this.fetchIsolated(options!.modulePath!, options!.projectDir!, context)
58
+ : Promise.resolve(pageModule.getServerData!(context)),
32
59
  DATA_FETCH_TIMEOUT_MS,
33
60
  `getServerData for ${pathname}`,
34
61
  )
@@ -59,7 +86,11 @@ export class ServerDataFetcher {
59
86
  throw error;
60
87
  }
61
88
 
62
- this.logError("DATA_FETCH_ERROR getServerData failed", error, { pathname, durationMs });
89
+ this.logError("DATA_FETCH_ERROR getServerData failed", error, {
90
+ pathname,
91
+ durationMs,
92
+ isolated: useIsolation,
93
+ });
63
94
  throw error;
64
95
  }
65
96
  },
@@ -68,10 +99,82 @@ export class ServerDataFetcher {
68
99
  "data.pathname": pathname,
69
100
  "data.timeout_ms": DATA_FETCH_TIMEOUT_MS,
70
101
  "data.project_id": projectId,
102
+ "data.isolated": useIsolation,
71
103
  },
72
104
  );
73
105
  }
74
106
 
107
+ /**
108
+ * Execute getServerData in a per-project Worker.
109
+ */
110
+ private async fetchIsolated(
111
+ modulePath: string,
112
+ projectDir: string,
113
+ context: DataContext,
114
+ ): Promise<DataResult> {
115
+ const pool = getWorkerPool();
116
+ let body: Uint8Array | null = null;
117
+ if (context.request?.body) {
118
+ // Fast path: reject before buffering if Content-Length is known
119
+ const contentLength = context.request.headers?.get("content-length");
120
+ if (contentLength) {
121
+ const bytes = parseInt(contentLength, 10);
122
+ if (bytes > MAX_WORKER_BODY_BYTES) {
123
+ throw new Error(
124
+ `Request body too large for isolated data fetch (${
125
+ (bytes / 1024 / 1024).toFixed(1)
126
+ } MB, limit ${MAX_WORKER_BODY_BYTES / 1024 / 1024} MB)`,
127
+ );
128
+ }
129
+ }
130
+
131
+ body = new Uint8Array(await context.request.arrayBuffer());
132
+
133
+ // Fallback: check actual size for chunked/streaming bodies
134
+ if (body.byteLength > MAX_WORKER_BODY_BYTES) {
135
+ throw new Error(
136
+ `Request body too large for isolated data fetch (${
137
+ (body.byteLength / 1024 / 1024).toFixed(1)
138
+ } MB, limit ${MAX_WORKER_BODY_BYTES / 1024 / 1024} MB)`,
139
+ );
140
+ }
141
+ }
142
+
143
+ const workerResponse: WorkerResponse = await pool.execute(
144
+ projectDir,
145
+ [projectDir],
146
+ {
147
+ type: "fetch-data",
148
+ id: dntShim.crypto.randomUUID(),
149
+ modulePath,
150
+ context: {
151
+ params: context.params,
152
+ query: context.query?.toString() ?? "",
153
+ request: {
154
+ url: context.request?.url ?? context.url?.toString() ?? "http://localhost",
155
+ method: context.request?.method ?? "GET",
156
+ headers: context.request ? [...context.request.headers.entries()] : [],
157
+ body,
158
+ },
159
+ url: context.url?.toString() ?? "http://localhost",
160
+ },
161
+ },
162
+ );
163
+
164
+ if (workerResponse.type === "error") {
165
+ const err = new Error(workerResponse.error.message);
166
+ err.name = workerResponse.error.name;
167
+ throw err;
168
+ }
169
+
170
+ if (workerResponse.type === "data-result") {
171
+ return workerResponse.result as DataResult;
172
+ }
173
+
174
+ // Unexpected response type — shouldn't happen but be defensive
175
+ throw new Error(`Unexpected worker response type: ${workerResponse.type}`);
176
+ }
177
+
75
178
  /**
76
179
  * Log errors unconditionally. Production errors should always be logged.
77
180
  * @see plans/architecture-audit/010-error-handling.md
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Jobs module for durable project-scoped background execution.
3
+ *
4
+ * Provides a public SDK surface for one-off jobs, cron jobs, batch summaries,
5
+ * job target discovery, and the canonical split between user-visible `events`
6
+ * and raw debugging `logs`.
7
+ *
8
+ * @module
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { VeryfrontJobsClient } from "veryfront/jobs";
13
+ *
14
+ * const jobs = new VeryfrontJobsClient({
15
+ * authToken: process.env.VERYFRONT_API_TOKEN,
16
+ * projectReference: "my-project",
17
+ * });
18
+ *
19
+ * const job = await jobs.create({
20
+ * name: "Ingest 1 file",
21
+ * target: "task:knowledge-ingest",
22
+ * config: {
23
+ * file_count: 1,
24
+ * upload_ids: ["00000000-0000-0000-0000-000000000000"],
25
+ * },
26
+ * });
27
+ *
28
+ * const events = await jobs.events(job.id);
29
+ * ```
30
+ */
31
+ import "../../_dnt.polyfills.js";
32
+
33
+
34
+ export {
35
+ type CreateCronJobInput,
36
+ type CreateJobInput,
37
+ createJobsClient,
38
+ type ListBatchJobsOptions,
39
+ type ListCronJobsOptions,
40
+ type ListJobEventsOptions,
41
+ type ListJobsOptions,
42
+ type ProjectScopedOptions,
43
+ type UpdateCronJobInput,
44
+ VeryfrontJobsClient,
45
+ type VeryfrontJobsClientConfig,
46
+ } from "./jobs-client.js";
47
+ export {
48
+ type CronJob,
49
+ CronJobSchema,
50
+ type CronJobStatus,
51
+ CronJobStatusSchema,
52
+ type Job,
53
+ type JobBatch,
54
+ type JobBatchResult,
55
+ JobBatchResultSchema,
56
+ JobBatchSchema,
57
+ type JobBatchStatusCounts,
58
+ JobBatchStatusCountsSchema,
59
+ type JobEvent,
60
+ JobEventSchema,
61
+ type JobEventsResponse,
62
+ JobEventsResponseSchema,
63
+ type JobLogsResponse,
64
+ JobLogsResponseSchema,
65
+ type JobResult,
66
+ JobResultSchema,
67
+ JobSchema,
68
+ type JobStatus,
69
+ JobStatusSchema,
70
+ type JobTargetDefinition,
71
+ JobTargetDefinitionSchema,
72
+ type JobTargetDefinitionsResponse,
73
+ JobTargetDefinitionsResponseSchema,
74
+ type KnowledgeIngestBatchSource,
75
+ KnowledgeIngestBatchSourceSchema,
76
+ type KnowledgeIngestFileResult,
77
+ KnowledgeIngestFileResultSchema,
78
+ PageInfoSchema,
79
+ type PaginatedCronJobsResponse,
80
+ PaginatedCronJobsResponseSchema,
81
+ type PaginatedJobsResponse,
82
+ PaginatedJobsResponseSchema,
83
+ type ReservedJobTargetFamily,
84
+ ReservedJobTargetFamilySchema,
85
+ } from "./schemas.js";