veryfront 0.1.246 → 0.1.248

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 (160) hide show
  1. package/esm/cli/mcp/tools/project-tools.d.ts +1 -1
  2. package/esm/cli/mcp/tools/scaffold-tools.d.ts +2 -2
  3. package/esm/cli/shared/server-startup.d.ts.map +1 -1
  4. package/esm/cli/shared/server-startup.js +8 -0
  5. package/esm/deno.d.ts +0 -9
  6. package/esm/deno.js +5 -12
  7. package/esm/src/agent/durable.d.ts +67 -0
  8. package/esm/src/agent/durable.d.ts.map +1 -1
  9. package/esm/src/agent/durable.js +134 -0
  10. package/esm/src/agent/index.d.ts +1 -1
  11. package/esm/src/agent/index.d.ts.map +1 -1
  12. package/esm/src/agent/index.js +1 -1
  13. package/esm/src/embedding/upload-loader.d.ts +2 -2
  14. package/esm/src/embedding/upload-loader.d.ts.map +1 -1
  15. package/esm/src/embedding/upload-loader.js +11 -48
  16. package/esm/src/errors/middleware/cli-error-boundary.js +1 -1
  17. package/esm/src/errors/middleware/http-error-boundary.js +1 -1
  18. package/esm/src/errors/tracing.d.ts +3 -3
  19. package/esm/src/errors/tracing.d.ts.map +1 -1
  20. package/esm/src/errors/tracing.js +3 -3
  21. package/esm/src/extensions/interfaces/index.d.ts +2 -2
  22. package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
  23. package/esm/src/extensions/interfaces/node-compat.d.ts +68 -10
  24. package/esm/src/extensions/interfaces/node-compat.d.ts.map +1 -1
  25. package/esm/src/extensions/interfaces/tracing-exporter.d.ts +35 -1
  26. package/esm/src/extensions/interfaces/tracing-exporter.d.ts.map +1 -1
  27. package/esm/src/integrations/schema.d.ts +10 -10
  28. package/esm/src/mcp/index.d.ts +7 -2
  29. package/esm/src/mcp/index.d.ts.map +1 -1
  30. package/esm/src/mcp/index.js +7 -2
  31. package/esm/src/mcp/schemas/index.d.ts +1 -1
  32. package/esm/src/mcp/schemas/index.d.ts.map +1 -1
  33. package/esm/src/mcp/schemas/index.js +1 -1
  34. package/esm/src/mcp/schemas/mcp.schema.d.ts +13 -7
  35. package/esm/src/mcp/schemas/mcp.schema.d.ts.map +1 -1
  36. package/esm/src/mcp/schemas/mcp.schema.js +17 -7
  37. package/esm/src/mcp/server.d.ts +13 -0
  38. package/esm/src/mcp/server.d.ts.map +1 -1
  39. package/esm/src/mcp/server.js +43 -6
  40. package/esm/src/observability/auto-instrument/http-instrumentation.js +1 -1
  41. package/esm/src/observability/auto-instrument/react-instrumentation.js +1 -1
  42. package/esm/src/observability/instruments/build-instruments.d.ts +1 -1
  43. package/esm/src/observability/instruments/build-instruments.d.ts.map +1 -1
  44. package/esm/src/observability/instruments/cache-instruments.d.ts +1 -1
  45. package/esm/src/observability/instruments/cache-instruments.d.ts.map +1 -1
  46. package/esm/src/observability/instruments/data-instruments.d.ts +1 -1
  47. package/esm/src/observability/instruments/data-instruments.d.ts.map +1 -1
  48. package/esm/src/observability/instruments/error-instruments.d.ts +1 -1
  49. package/esm/src/observability/instruments/error-instruments.d.ts.map +1 -1
  50. package/esm/src/observability/instruments/http-instruments.d.ts +1 -1
  51. package/esm/src/observability/instruments/http-instruments.d.ts.map +1 -1
  52. package/esm/src/observability/instruments/instruments-factory.d.ts +1 -1
  53. package/esm/src/observability/instruments/instruments-factory.d.ts.map +1 -1
  54. package/esm/src/observability/instruments/memory-instruments.d.ts +1 -1
  55. package/esm/src/observability/instruments/memory-instruments.d.ts.map +1 -1
  56. package/esm/src/observability/instruments/render-instruments.d.ts +1 -1
  57. package/esm/src/observability/instruments/render-instruments.d.ts.map +1 -1
  58. package/esm/src/observability/instruments/rsc-instruments.d.ts +1 -1
  59. package/esm/src/observability/instruments/rsc-instruments.d.ts.map +1 -1
  60. package/esm/src/observability/metrics/manager.d.ts.map +1 -1
  61. package/esm/src/observability/metrics/manager.js +10 -2
  62. package/esm/src/observability/metrics/types.d.ts +1 -1
  63. package/esm/src/observability/metrics/types.d.ts.map +1 -1
  64. package/esm/src/observability/simple-metrics/otel-instruments.d.ts.map +1 -1
  65. package/esm/src/observability/simple-metrics/otel-instruments.js +7 -2
  66. package/esm/src/observability/simple-metrics/types.d.ts +1 -1
  67. package/esm/src/observability/simple-metrics/types.d.ts.map +1 -1
  68. package/esm/src/observability/tracing/api-shim.d.ts +177 -0
  69. package/esm/src/observability/tracing/api-shim.d.ts.map +1 -0
  70. package/esm/src/observability/tracing/api-shim.js +234 -0
  71. package/esm/src/observability/tracing/manager.d.ts.map +1 -1
  72. package/esm/src/observability/tracing/manager.js +29 -4
  73. package/esm/src/observability/tracing/otlp-setup.d.ts +12 -8
  74. package/esm/src/observability/tracing/otlp-setup.d.ts.map +1 -1
  75. package/esm/src/observability/tracing/otlp-setup.js +59 -136
  76. package/esm/src/observability/tracing/types.d.ts +1 -1
  77. package/esm/src/observability/tracing/types.d.ts.map +1 -1
  78. package/esm/src/platform/compat/kv/factory.d.ts.map +1 -1
  79. package/esm/src/platform/compat/kv/factory.js +15 -6
  80. package/esm/src/platform/compat/opaque-deps.d.ts +6 -5
  81. package/esm/src/platform/compat/opaque-deps.d.ts.map +1 -1
  82. package/esm/src/platform/compat/opaque-deps.js +13 -37
  83. package/esm/src/proxy/tracing.d.ts +7 -2
  84. package/esm/src/proxy/tracing.d.ts.map +1 -1
  85. package/esm/src/proxy/tracing.js +31 -96
  86. package/esm/src/rendering/rsc/client-module-strategy.d.ts.map +1 -1
  87. package/esm/src/rendering/rsc/client-module-strategy.js +9 -1
  88. package/esm/src/server/bootstrap.d.ts.map +1 -1
  89. package/esm/src/server/bootstrap.js +27 -1
  90. package/esm/src/server/context/request-context.d.ts.map +1 -1
  91. package/esm/src/server/context/request-context.js +7 -4
  92. package/esm/src/server/dev-server/middleware.js +1 -1
  93. package/esm/src/server/handlers/dev/files/dev-file.handler.d.ts.map +1 -1
  94. package/esm/src/server/handlers/dev/files/dev-file.handler.js +4 -14
  95. package/esm/src/server/services/rendering/ssr.service.d.ts.map +1 -1
  96. package/esm/src/server/services/rendering/ssr.service.js +4 -1
  97. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +1 -1
  98. package/esm/src/utils/version-constant.d.ts +1 -1
  99. package/esm/src/utils/version-constant.js +1 -1
  100. package/esm/src/workflow/claude-code/workspace-sync.d.ts +17 -2
  101. package/esm/src/workflow/claude-code/workspace-sync.d.ts.map +1 -1
  102. package/esm/src/workflow/claude-code/workspace-sync.js +106 -19
  103. package/esm/src/workflow/schemas/workflow.schema.d.ts +3 -3
  104. package/package.json +1 -9
  105. package/src/cli/shared/server-startup.ts +8 -0
  106. package/src/deno.js +5 -12
  107. package/src/src/agent/durable.ts +237 -0
  108. package/src/src/agent/index.ts +4 -0
  109. package/src/src/cache/backends/factory.ts +1 -1
  110. package/src/src/cache/backends/redis.ts +1 -1
  111. package/src/src/cache/keys/utils.ts +1 -1
  112. package/src/src/cache/registry.ts +1 -1
  113. package/src/src/data/static-paths-fetcher.ts +1 -1
  114. package/src/src/embedding/upload-loader.ts +14 -63
  115. package/src/src/errors/middleware/cli-error-boundary.ts +1 -1
  116. package/src/src/errors/middleware/http-error-boundary.ts +1 -1
  117. package/src/src/errors/tracing.ts +4 -4
  118. package/src/src/extensions/interfaces/index.ts +7 -2
  119. package/src/src/extensions/interfaces/node-compat.ts +74 -10
  120. package/src/src/extensions/interfaces/tracing-exporter.ts +36 -1
  121. package/src/src/mcp/index.ts +7 -2
  122. package/src/src/mcp/schemas/index.ts +1 -0
  123. package/src/src/mcp/schemas/mcp.schema.ts +20 -7
  124. package/src/src/mcp/server.ts +60 -6
  125. package/src/src/observability/auto-instrument/http-instrumentation.ts +1 -1
  126. package/src/src/observability/auto-instrument/react-instrumentation.ts +1 -1
  127. package/src/src/observability/auto-instrument/wrappers.ts +1 -1
  128. package/src/src/observability/instruments/build-instruments.ts +1 -1
  129. package/src/src/observability/instruments/cache-instruments.ts +6 -1
  130. package/src/src/observability/instruments/data-instruments.ts +1 -1
  131. package/src/src/observability/instruments/error-instruments.ts +1 -1
  132. package/src/src/observability/instruments/http-instruments.ts +6 -1
  133. package/src/src/observability/instruments/instruments-factory.ts +1 -1
  134. package/src/src/observability/instruments/memory-instruments.ts +5 -1
  135. package/src/src/observability/instruments/render-instruments.ts +1 -1
  136. package/src/src/observability/instruments/rsc-instruments.ts +1 -1
  137. package/src/src/observability/metrics/manager.ts +11 -3
  138. package/src/src/observability/metrics/types.ts +7 -1
  139. package/src/src/observability/simple-metrics/otel-instruments.ts +7 -2
  140. package/src/src/observability/simple-metrics/types.ts +1 -1
  141. package/src/src/observability/tracing/api-shim.ts +409 -0
  142. package/src/src/observability/tracing/manager.ts +29 -4
  143. package/src/src/observability/tracing/otlp-setup.ts +76 -168
  144. package/src/src/observability/tracing/types.ts +1 -1
  145. package/src/src/platform/compat/kv/factory.ts +18 -7
  146. package/src/src/platform/compat/opaque-deps.ts +16 -44
  147. package/src/src/proxy/tracing.ts +43 -117
  148. package/src/src/rendering/rsc/client-module-strategy.ts +9 -1
  149. package/src/src/server/bootstrap.ts +38 -1
  150. package/src/src/server/context/request-context.ts +10 -7
  151. package/src/src/server/dev-server/middleware.ts +1 -1
  152. package/src/src/server/handlers/dev/files/dev-file.handler.ts +4 -22
  153. package/src/src/server/services/rendering/ssr.service.ts +4 -1
  154. package/src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +1 -1
  155. package/src/src/utils/version-constant.ts +1 -1
  156. package/src/src/workflow/claude-code/workspace-sync.ts +109 -20
  157. package/esm/src/utils/logger/trace-bridge.d.ts +0 -11
  158. package/esm/src/utils/logger/trace-bridge.d.ts.map +0 -1
  159. package/esm/src/utils/logger/trace-bridge.js +0 -12
  160. package/src/src/utils/logger/trace-bridge.ts +0 -14
@@ -15,8 +15,9 @@ import * as dntShim from "../../../_dnt.shims.js";
15
15
  import { logger as baseLogger } from "../../utils/index.js";
16
16
  import { api } from "../api.js";
17
17
  import type { CapturedTenantContext } from "../types.js";
18
- import { join, relative, resolve } from "../../../deps/jsr.io/@std/path/1.1.4/mod.js";
18
+ import { dirname, join, relative, resolve } from "../../../deps/jsr.io/@std/path/1.1.4/mod.js";
19
19
  import { INITIALIZATION_ERROR, INVALID_ARGUMENT, SECURITY_VIOLATION } from "../../errors/index.js";
20
+ import { isWithinDirectory } from "../../utils/path-utils.js";
20
21
 
21
22
  const logger = baseLogger.component("workspace-sync");
22
23
 
@@ -230,8 +231,8 @@ export class WorkspaceSync {
230
231
  this.fileChecksums.set(path, hash);
231
232
 
232
233
  // Write to local filesystem (use safe path resolution)
233
- const localPath = this.resolveSafePath(path);
234
- const dir = localPath.substring(0, localPath.lastIndexOf("/"));
234
+ const localPath = await this.resolveSafePath(path);
235
+ const dir = dirname(localPath);
235
236
  await dntShim.Deno.mkdir(dir, { recursive: true });
236
237
  await dntShim.Deno.writeTextFile(localPath, content);
237
238
 
@@ -295,7 +296,7 @@ export class WorkspaceSync {
295
296
  // Check for deleted files
296
297
  for (const [path, originalHash] of this.fileChecksums) {
297
298
  try {
298
- const localPath = this.resolveSafePath(path);
299
+ const localPath = await this.resolveSafePath(path);
299
300
  await dntShim.Deno.stat(localPath);
300
301
  } catch (_) {
301
302
  // File was deleted
@@ -315,14 +316,26 @@ export class WorkspaceSync {
315
316
  }
316
317
 
317
318
  /**
318
- * Recursively walk directory and detect changes
319
+ * Recursively walk directory and detect changes.
320
+ *
321
+ * SECURITY: Uses lstat (not stat) and skips any symlink it finds, so a
322
+ * symlink planted inside the workspace cannot cause us to descend into —
323
+ * or read the contents of — files outside the workspace (VULN-FS-4).
319
324
  */
320
325
  private async walkAndDetect(
321
326
  localPath: string,
322
327
  relativePath: string,
323
328
  changes: FileChange[],
324
329
  ): Promise<void> {
325
- const stat = await dntShim.Deno.stat(localPath);
330
+ const stat = await dntShim.Deno.lstat(localPath);
331
+
332
+ // Ignore symlinks outright — we never treat them as real files here.
333
+ if (stat.isSymlink) {
334
+ if (this.config.debug) {
335
+ logger.info("Skipping symlink during change detection", { localPath });
336
+ }
337
+ return;
338
+ }
326
339
 
327
340
  if (stat.isDirectory) {
328
341
  for await (const entry of dntShim.Deno.readDir(localPath)) {
@@ -335,7 +348,7 @@ export class WorkspaceSync {
335
348
  return;
336
349
  }
337
350
 
338
- // It's a file - check for changes
351
+ // It's a regular file - check for changes
339
352
  const content = await dntShim.Deno.readTextFile(localPath);
340
353
  const newHash = await checksum(content);
341
354
  const originalHash = this.fileChecksums.get(relativePath);
@@ -390,7 +403,7 @@ export class WorkspaceSync {
390
403
  }
391
404
 
392
405
  try {
393
- const localPath = this.resolveSafePath(change.path);
406
+ const localPath = await this.resolveSafePath(change.path);
394
407
  const content = await dntShim.Deno.readTextFile(localPath);
395
408
 
396
409
  if (options.onUpload) {
@@ -420,21 +433,97 @@ export class WorkspaceSync {
420
433
  }
421
434
 
422
435
  /**
423
- * Safely resolve a path within the workspace, preventing path traversal attacks
436
+ * Safely resolve a path within the workspace, preventing path traversal
437
+ * and symlink-based escapes (VULN-FS-4).
438
+ *
439
+ * - Rejects NUL bytes outright.
440
+ * - Rejects any intermediate path segment that is a symlink.
441
+ * - Re-checks containment by realpath-ing the parent directory after the
442
+ * segment walk, so a symlink that resolves through a non-symlink directory
443
+ * chain still cannot escape the workspace.
444
+ *
445
+ * Note: this deliberately rejects ALL symlinks inside the workspace — even
446
+ * those whose targets remain within it — because the race window between
447
+ * resolution and use is not worth the complexity for our use-case.
424
448
  */
425
- private resolveSafePath(path: string): string {
426
- // Normalize the input path
449
+ private async resolveSafePath(path: string): Promise<string> {
450
+ // Reject NUL bytes — they confuse filesystem APIs and are never legitimate.
451
+ if (path.includes("\0")) {
452
+ throw SECURITY_VIOLATION.create({ detail: `NUL byte in path` });
453
+ }
454
+
455
+ // Workspace-relative paths only. A single leading "/" is the canonical
456
+ // API form for "the project root" (e.g. "/src/foo.ts") and is accepted;
457
+ // anything that syntactically looks like a system-absolute path beyond
458
+ // that one-slash convention is rejected.
459
+ //
460
+ // - Windows drive letters (C:\...) — rejected.
461
+ // - UNC paths (//host/share) — rejected.
462
+ // - Unix absolute paths with a leading slash are treated as
463
+ // workspace-relative, but any component that tries to escape the
464
+ // workspace is still caught by the traversal / realpath checks below.
465
+ if (/^[A-Za-z]:[\\/]/.test(path)) {
466
+ throw SECURITY_VIOLATION.create({ detail: `Absolute path not allowed: ${path}` });
467
+ }
468
+ if (path.startsWith("//")) {
469
+ throw SECURITY_VIOLATION.create({ detail: `Absolute path not allowed: ${path}` });
470
+ }
471
+
472
+ // Normalize the input path (treat leading "/" as workspace-relative).
427
473
  const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
428
474
 
429
- // Resolve the full path
430
- const fullPath = resolve(join(this.workspaceDir, normalizedPath));
475
+ // Empty path resolves to the workspace dir itself — writing to it would
476
+ // clobber the workspace as a regular file. Reject explicitly.
477
+ if (normalizedPath === "") {
478
+ throw SECURITY_VIOLATION.create({ detail: `Empty path not allowed` });
479
+ }
431
480
 
432
- // Verify the resolved path is within the workspace
481
+ // Resolve the full path lexically first (catches literal "..").
482
+ const fullPath = resolve(join(this.workspaceDir, normalizedPath));
433
483
  const relativePath = relative(this.workspaceDir, fullPath);
434
- if (relativePath.startsWith("..") || !relativePath || relativePath === "..") {
484
+ if (!relativePath || relativePath.startsWith("..") || relativePath === "..") {
435
485
  throw SECURITY_VIOLATION.create({ detail: `Path traversal detected: ${path}` });
436
486
  }
437
487
 
488
+ // Walk each segment and reject any existing symlink along the way.
489
+ // A segment that does not yet exist is fine — it will be created later.
490
+ const relSegments = relativePath === "" ? [] : relativePath.split(/[\\/]/).filter(Boolean);
491
+ let cursor = this.workspaceDir;
492
+ for (const seg of relSegments) {
493
+ cursor = join(cursor, seg);
494
+ try {
495
+ const info = await dntShim.Deno.lstat(cursor);
496
+ if (info.isSymlink) {
497
+ throw SECURITY_VIOLATION.create({
498
+ detail: `Refusing to traverse symlink: ${cursor}`,
499
+ });
500
+ }
501
+ } catch (e) {
502
+ if (e instanceof dntShim.Deno.errors.NotFound) {
503
+ // Segment doesn't exist yet — the rest of the chain will be
504
+ // created under a verified-non-symlink parent, so stop walking.
505
+ break;
506
+ }
507
+ throw e;
508
+ }
509
+ }
510
+
511
+ // Final containment check against the realpath of the parent directory,
512
+ // to defeat any symlink-in-parent we might have missed (e.g. one that
513
+ // appeared mid-walk). If the parent doesn't exist yet, that's fine —
514
+ // the segment walk above already proved every existing ancestor is real.
515
+ try {
516
+ const parentReal = await dntShim.Deno.realPath(dirname(fullPath));
517
+ const workspaceReal = await dntShim.Deno.realPath(this.workspaceDir);
518
+ if (!isWithinDirectory(workspaceReal, parentReal)) {
519
+ throw SECURITY_VIOLATION.create({
520
+ detail: `Resolved parent outside workspace: ${parentReal}`,
521
+ });
522
+ }
523
+ } catch (e) {
524
+ if (!(e instanceof dntShim.Deno.errors.NotFound)) throw e;
525
+ }
526
+
438
527
  return fullPath;
439
528
  }
440
529
 
@@ -442,7 +531,7 @@ export class WorkspaceSync {
442
531
  * Read a file from the workspace
443
532
  */
444
533
  async readFile(path: string): Promise<string> {
445
- const localPath = this.resolveSafePath(path);
534
+ const localPath = await this.resolveSafePath(path);
446
535
  return await dntShim.Deno.readTextFile(localPath);
447
536
  }
448
537
 
@@ -450,10 +539,10 @@ export class WorkspaceSync {
450
539
  * Write a file to the workspace
451
540
  */
452
541
  async writeFile(path: string, content: string): Promise<void> {
453
- const localPath = this.resolveSafePath(path);
542
+ const localPath = await this.resolveSafePath(path);
454
543
 
455
544
  // Ensure directory exists
456
- const dir = localPath.substring(0, localPath.lastIndexOf("/"));
545
+ const dir = dirname(localPath);
457
546
  await dntShim.Deno.mkdir(dir, { recursive: true });
458
547
 
459
548
  await dntShim.Deno.writeTextFile(localPath, content);
@@ -463,7 +552,7 @@ export class WorkspaceSync {
463
552
  * Delete a file from the workspace
464
553
  */
465
554
  async deleteFile(path: string): Promise<void> {
466
- const localPath = this.resolveSafePath(path);
555
+ const localPath = await this.resolveSafePath(path);
467
556
  await dntShim.Deno.remove(localPath);
468
557
  }
469
558
 
@@ -472,7 +561,7 @@ export class WorkspaceSync {
472
561
  */
473
562
  async fileExists(path: string): Promise<boolean> {
474
563
  try {
475
- const localPath = this.resolveSafePath(path);
564
+ const localPath = await this.resolveSafePath(path);
476
565
  await dntShim.Deno.stat(localPath);
477
566
  return true;
478
567
  } catch (_) {
@@ -1,11 +0,0 @@
1
- /**
2
- * Bridges OpenTelemetry trace context into the logger.
3
- *
4
- * Import this module as a side-effect after OTLP initialization to
5
- * automatically populate `traceId` and `spanId` in every JSON log entry
6
- * when an OTel span is active.
7
- *
8
- * @module
9
- */
10
- export {};
11
- //# sourceMappingURL=trace-bridge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"trace-bridge.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/logger/trace-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Bridges OpenTelemetry trace context into the logger.
3
- *
4
- * Import this module as a side-effect after OTLP initialization to
5
- * automatically populate `traceId` and `spanId` in every JSON log entry
6
- * when an OTel span is active.
7
- *
8
- * @module
9
- */
10
- import { getTraceContext } from "../../observability/tracing/otlp-setup.js";
11
- import { __registerTraceContextGetter } from "./logger.js";
12
- __registerTraceContextGetter(getTraceContext);
@@ -1,14 +0,0 @@
1
- /**
2
- * Bridges OpenTelemetry trace context into the logger.
3
- *
4
- * Import this module as a side-effect after OTLP initialization to
5
- * automatically populate `traceId` and `spanId` in every JSON log entry
6
- * when an OTel span is active.
7
- *
8
- * @module
9
- */
10
-
11
- import { getTraceContext } from "../../observability/tracing/otlp-setup.js";
12
- import { __registerTraceContextGetter } from "./logger.js";
13
-
14
- __registerTraceContextGetter(getTraceContext);