@agimon-ai/po-artifact 0.0.0-alpha.39 → 0.0.0-alpha.40

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.
@@ -21,6 +21,8 @@ function artifactMimeType(relativePath) {
21
21
  }
22
22
  //#endregion
23
23
  //#region src/services/artifactFiles/index.ts
24
+ /** A copy still being written: promoters write `.<name>.tmp` and rename it into place. */
25
+ const IN_FLIGHT_COPY = /^\..+\.tmp$/u;
24
26
  function inside(root, candidate) {
25
27
  const relative = path.relative(root, candidate);
26
28
  return relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
@@ -224,7 +226,7 @@ async function listArtifacts(root, workflowVisible) {
224
226
  if (!stat.isDirectory() || stat.isSymbolicLink()) continue;
225
227
  const real = await fs.realpath(location);
226
228
  if (inside(realRoot, real)) await visit(real);
227
- } else if (entry.isFile()) try {
229
+ } else if (entry.isFile() && !IN_FLIGHT_COPY.test(entry.name)) try {
228
230
  const file = await openArtifact(root, relativePath, workflowVisible);
229
231
  try {
230
232
  items.push({
@@ -256,4 +258,4 @@ async function listArtifacts(root, workflowVisible) {
256
258
  //#endregion
257
259
  export { readArtifactBytes as a, ArtifactAccessError as c, openArtifact as i, artifactRoot as l, listArtifactSessions as n, removeArtifact as o, listArtifacts as r, writeArtifactText as s, ensureArtifactRoot as t };
258
260
 
259
- //# sourceMappingURL=artifactFiles-DyIkevXc.mjs.map
261
+ //# sourceMappingURL=artifactFiles-BJL1H1QG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifactFiles-BJL1H1QG.mjs","names":[],"sources":["../src/services/artifactFiles/artifactPaths.ts","../src/services/artifactFiles/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { piAgentDirectory } from '@agimon-ai/po-core/piSettings';\n\nimport { ARTIFACT_CONTENT_TYPES, ARTIFACT_DIRECTORY } from '../../constants/artifacts';\n\nexport class ArtifactAccessError extends Error {\n constructor(\n message: string,\n readonly status: 400 | 403 | 404 | 413,\n ) {\n super(message);\n }\n}\n\nexport function artifactRoot(sessionId: string, environment: Readonly<Record<string, string | undefined>>): string {\n if (!/^[a-zA-Z0-9_-]+$/u.test(sessionId)) throw new ArtifactAccessError('Invalid artifact session identity.', 400);\n return path.join(piAgentDirectory(environment, environment.HOME), ARTIFACT_DIRECTORY, sessionId);\n}\n\nexport function artifactMimeType(relativePath: string): string {\n return ARTIFACT_CONTENT_TYPES[path.extname(relativePath).toLowerCase()] ?? 'application/octet-stream';\n}\n","import { randomUUID } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { WORKFLOW_ARTIFACT_DIRECTORY } from '../../constants/artifacts';\nimport type { ArtifactItem, ArtifactSnapshot, ArtifactWorkflowVisibility } from '../../types/artifacts';\nimport { ArtifactAccessError, artifactMimeType, artifactRoot } from './artifactPaths';\n\nexport { ArtifactAccessError, artifactMimeType, artifactRoot } from './artifactPaths';\n\n/** A copy still being written: promoters write `.<name>.tmp` and rename it into place. */\nconst IN_FLIGHT_COPY = /^\\..+\\.tmp$/u;\nfunction inside(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n}\n\nfunction codeOf(error: unknown): string | undefined {\n return error instanceof Error && 'code' in error ? String(error.code) : undefined;\n}\n\n/** The owned directories must not redirect artifact access through a symlink. */\nasync function checkedRoot(root: string): Promise<string> {\n const base = path.dirname(root);\n for (const directory of [base, root]) {\n const stat = await fs.lstat(directory);\n if (!stat.isDirectory() || stat.isSymbolicLink())\n throw new ArtifactAccessError('The artifact folder is unavailable.', 403);\n }\n const realBase = await fs.realpath(base);\n const realRoot = await fs.realpath(root);\n if (!inside(realBase, realRoot))\n throw new ArtifactAccessError('The artifact folder is outside its storage directory.', 403);\n return realRoot;\n}\n\nexport async function ensureArtifactRoot(root: string): Promise<void> {\n await fs.mkdir(path.dirname(root), { recursive: true, mode: 0o700 });\n await fs.mkdir(root, { recursive: true, mode: 0o700 });\n await checkedRoot(root);\n}\n\n/** Open without following mutable ancestors. Node exposes no portable openat API. */\nasync function openContained(root: string, segments: string[]): Promise<fs.FileHandle> {\n if (process.platform === 'darwin') {\n // Darwin O_NOFOLLOW_ANY checks every component atomically. Do not combine it with O_NOFOLLOW.\n return fs.open(path.join(root, ...segments), constants.O_RDONLY | constants.O_NONBLOCK | 0x20000000);\n }\n if (process.platform !== 'linux') throw new ArtifactAccessError('Secure artifact reads require macOS or Linux.', 403);\n const flags = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;\n let directory = await fs.open(path.dirname(root), flags);\n try {\n for (const segment of [path.basename(root), ...segments.slice(0, -1)]) {\n const child = await fs.open(`/proc/self/fd/${directory.fd}/${segment}`, flags);\n await directory.close();\n directory = child;\n }\n return await fs.open(\n `/proc/self/fd/${directory.fd}/${segments.at(-1)!}`,\n constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,\n );\n } finally {\n await directory.close();\n }\n}\n\nfunction artifactSegments(requested: string | undefined): string[] {\n if (\n !requested ||\n requested.includes('\\0') ||\n requested.includes('\\\\') ||\n path.isAbsolute(requested) ||\n requested.split('/').some((part) => part === '..' || part === '.' || part === '')\n )\n throw new ArtifactAccessError('Invalid artifact path.', 400);\n return requested.split('/');\n}\n\nfunction accessError(error: unknown, action: string): unknown {\n if (error instanceof ArtifactAccessError) return error;\n if (codeOf(error) === 'ENOENT' || codeOf(error) === 'ENOTDIR')\n return new ArtifactAccessError('The artifact no longer exists.', 404);\n if (codeOf(error) === 'EACCES' || codeOf(error) === 'EPERM' || codeOf(error) === 'ELOOP')\n return new ArtifactAccessError(`The artifact cannot be ${action}.`, 403);\n return error;\n}\n\n/** One guarded open shared by metadata, text and byte reads. The caller closes the handle. */\nexport async function openArtifact(\n root: string,\n requested: string | undefined,\n workflowVisible?: ArtifactWorkflowVisibility,\n) {\n const segments = artifactSegments(requested);\n if (segments[0] === WORKFLOW_ARTIFACT_DIRECTORY && !workflowVisible?.(segments.slice(1).join('/'), 'file'))\n throw new ArtifactAccessError('This workflow file is private.', 403);\n try {\n const realRoot = await checkedRoot(root);\n const candidate = path.resolve(realRoot, requested!);\n if (!inside(realRoot, candidate))\n throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n let current = realRoot;\n for (let index = 0; index < segments.length; index += 1) {\n current = path.join(current, segments[index]!);\n const stat = await fs.lstat(current);\n if (stat.isSymbolicLink()) throw new ArtifactAccessError('Artifact symlinks cannot be read.', 403);\n if (index < segments.length - 1 ? !stat.isDirectory() : !stat.isFile())\n throw new ArtifactAccessError('The artifact is not a regular file.', 404);\n }\n const real = await fs.realpath(candidate);\n if (!inside(realRoot, real)) throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n const expected = await fs.lstat(real);\n const handle = await openContained(realRoot, segments);\n try {\n const stat = await handle.stat();\n if (!stat.isFile() || stat.dev !== expected.dev || stat.ino !== expected.ino)\n throw new ArtifactAccessError('The artifact changed while it was opened. Try again.', 403);\n return { handle, stat, path: requested!, mimeType: artifactMimeType(requested!) };\n } catch (error) {\n await handle.close();\n throw error;\n }\n } catch (error) {\n throw accessError(error, 'read');\n }\n}\n\n/** Bound allocation and read length even when the file grows after its metadata was read. */\nexport async function readArtifactBytes(handle: fs.FileHandle, size: number, offset = 0): Promise<Uint8Array> {\n const bytes = new Uint8Array(size);\n let read = 0;\n while (read < size) {\n const result = await handle.read(bytes, read, size - read, offset + read);\n if (result.bytesRead === 0) break;\n read += result.bytesRead;\n }\n return bytes.subarray(0, read);\n}\n\n/** Walk to the parent folder without following symlinks, creating missing folders on request. */\nasync function containedParent(realRoot: string, segments: string[], create: boolean): Promise<string> {\n let directory = realRoot;\n for (const segment of segments.slice(0, -1)) {\n directory = path.join(directory, segment);\n if (create)\n await fs.mkdir(directory, { mode: 0o700 }).catch((error: unknown) => {\n if (codeOf(error) !== 'EEXIST') throw error;\n });\n const stat = await fs.lstat(directory);\n if (stat.isSymbolicLink() || !stat.isDirectory())\n throw new ArtifactAccessError('The artifact folder is not a directory.', 403);\n }\n return directory;\n}\n\nasync function sameText(root: string, requested: string, bytes: Buffer): Promise<boolean> {\n try {\n const file = await openArtifact(root, requested);\n try {\n if (file.stat.size !== bytes.length) return false;\n return bytes.equals(await readArtifactBytes(file.handle, file.stat.size));\n } finally {\n await file.handle.close();\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError) return false;\n throw error;\n }\n}\n\n/**\n * Publish text through a same-folder temp file and rename, skipping identical content so mtimes stay stable.\n * ponytail: best-effort same-user guards, not race-resistant. Linux checks ancestors with lstat only;\n * walk with openat-style /proc/self/fd handles like openContained if artifacts cross a trust boundary.\n */\nexport async function writeArtifactText(root: string, requested: string, text: string): Promise<void> {\n const segments = artifactSegments(requested);\n if (process.platform !== 'darwin' && process.platform !== 'linux')\n throw new ArtifactAccessError('Secure artifact writes require macOS or Linux.', 403);\n const bytes = Buffer.from(text, 'utf8');\n try {\n await ensureArtifactRoot(root);\n const directory = await containedParent(await checkedRoot(root), segments, true);\n if (await sameText(root, requested, bytes)) return;\n const temp = path.join(directory, `.${segments.at(-1)!}.${randomUUID()}.tmp`);\n // Darwin O_NOFOLLOW_ANY refuses a symlink in any component; O_EXCL refuses one at the leaf.\n const flags =\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (process.platform === 'darwin' ? 0x20000000 : 0);\n const handle = await fs.open(temp, flags, 0o600);\n try {\n await handle.writeFile(bytes);\n await handle.close();\n await fs.rename(temp, path.join(directory, segments.at(-1)!));\n } catch (error) {\n await handle.close().catch(() => undefined);\n await fs.unlink(temp).catch(() => undefined);\n throw error;\n }\n } catch (error) {\n throw accessError(error, 'written');\n }\n}\n\n/** Remove one file or one empty folder. A missing target is already removed; nothing is deleted recursively. */\nexport async function removeArtifact(root: string, requested: string): Promise<void> {\n const segments = artifactSegments(requested);\n try {\n const target = path.join(await containedParent(await checkedRoot(root), segments, false), segments.at(-1)!);\n const stat = await fs.lstat(target);\n if (stat.isFile()) await fs.unlink(target);\n else if (!stat.isDirectory()) throw new ArtifactAccessError('The artifact is not a file or folder.', 403);\n else\n await fs.rmdir(target).catch((error: unknown) => {\n if (codeOf(error) !== 'ENOTEMPTY' && codeOf(error) !== 'EEXIST') throw error;\n });\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return;\n throw accessError(error, 'removed');\n }\n}\n/** Discover persisted session roots without admitting symlinked or malformed owners. */\nexport async function listArtifactSessions(\n environment: Readonly<Record<string, string | undefined>>,\n): Promise<readonly string[]> {\n const parent = path.dirname(artifactRoot('discovery', environment));\n try {\n const stat = await fs.lstat(parent);\n if (!stat.isDirectory() || stat.isSymbolicLink())\n throw new ArtifactAccessError('The artifact storage directory is unavailable.', 403);\n const entries = await fs.readdir(parent, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && /^[a-zA-Z0-9_-]+$/u.test(entry.name))\n .map((entry) => entry.name);\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return [];\n throw error;\n }\n}\n\nexport async function listArtifacts(\n root: string,\n workflowVisible?: ArtifactWorkflowVisibility,\n): Promise<ArtifactSnapshot> {\n const items: ArtifactItem[] = [];\n try {\n const realRoot = await checkedRoot(root);\n const visit = async (directory: string): Promise<void> => {\n for (const entry of await fs.readdir(directory, { withFileTypes: true })) {\n const location = path.join(directory, entry.name);\n const relativePath = path.relative(realRoot, location).split(path.sep).join('/');\n const segments = relativePath.split('/');\n if (\n segments[0] === WORKFLOW_ARTIFACT_DIRECTORY &&\n !workflowVisible?.(segments.slice(1).join('/'), entry.isDirectory() ? 'directory' : 'file')\n )\n continue;\n if (entry.isDirectory()) {\n // Recheck each directory rather than trusting a readdir entry across a rename.\n const stat = await fs.lstat(location);\n if (!stat.isDirectory() || stat.isSymbolicLink()) continue;\n const real = await fs.realpath(location);\n if (inside(realRoot, real)) await visit(real);\n } else if (entry.isFile() && !IN_FLIGHT_COPY.test(entry.name)) {\n try {\n const file = await openArtifact(root, relativePath, workflowVisible);\n try {\n items.push({ path: relativePath, name: entry.name, size: file.stat.size, modifiedAt: file.stat.mtimeMs });\n } finally {\n await file.handle.close();\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError && (error.status === 404 || error.status === 403)) continue;\n throw error;\n }\n }\n }\n };\n await visit(realRoot);\n items.sort(\n (left, right) =>\n right.modifiedAt - left.modifiedAt || (left.path < right.path ? -1 : left.path > right.path ? 1 : 0),\n );\n return { items };\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return { items: [] };\n return { items: [], error: error instanceof Error ? error.message : 'The artifact folder could not be read.' };\n }\n}\n"],"mappings":"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"}
@@ -45,6 +45,8 @@ function artifactMimeType(relativePath) {
45
45
  }
46
46
  //#endregion
47
47
  //#region src/services/artifactFiles/index.ts
48
+ /** A copy still being written: promoters write `.<name>.tmp` and rename it into place. */
49
+ const IN_FLIGHT_COPY = /^\..+\.tmp$/u;
48
50
  function inside(root, candidate) {
49
51
  const relative = node_path.default.relative(root, candidate);
50
52
  return relative !== ".." && !relative.startsWith(`..${node_path.default.sep}`) && !node_path.default.isAbsolute(relative);
@@ -248,7 +250,7 @@ async function listArtifacts(root, workflowVisible) {
248
250
  if (!stat.isDirectory() || stat.isSymbolicLink()) continue;
249
251
  const real = await node_fs_promises.default.realpath(location);
250
252
  if (inside(realRoot, real)) await visit(real);
251
- } else if (entry.isFile()) try {
253
+ } else if (entry.isFile() && !IN_FLIGHT_COPY.test(entry.name)) try {
252
254
  const file = await openArtifact(root, relativePath, workflowVisible);
253
255
  try {
254
256
  items.push({
@@ -339,4 +341,4 @@ Object.defineProperty(exports, "writeArtifactText", {
339
341
  }
340
342
  });
341
343
 
342
- //# sourceMappingURL=artifactFiles-BmBU9Olm.cjs.map
344
+ //# sourceMappingURL=artifactFiles-C8dqPVra.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifactFiles-C8dqPVra.cjs","names":["path","piAgentDirectory","ARTIFACT_DIRECTORY","ARTIFACT_CONTENT_TYPES","path","fs","constants","randomUUID"],"sources":["../src/services/artifactFiles/artifactPaths.ts","../src/services/artifactFiles/index.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { piAgentDirectory } from '@agimon-ai/po-core/piSettings';\n\nimport { ARTIFACT_CONTENT_TYPES, ARTIFACT_DIRECTORY } from '../../constants/artifacts';\n\nexport class ArtifactAccessError extends Error {\n constructor(\n message: string,\n readonly status: 400 | 403 | 404 | 413,\n ) {\n super(message);\n }\n}\n\nexport function artifactRoot(sessionId: string, environment: Readonly<Record<string, string | undefined>>): string {\n if (!/^[a-zA-Z0-9_-]+$/u.test(sessionId)) throw new ArtifactAccessError('Invalid artifact session identity.', 400);\n return path.join(piAgentDirectory(environment, environment.HOME), ARTIFACT_DIRECTORY, sessionId);\n}\n\nexport function artifactMimeType(relativePath: string): string {\n return ARTIFACT_CONTENT_TYPES[path.extname(relativePath).toLowerCase()] ?? 'application/octet-stream';\n}\n","import { randomUUID } from 'node:crypto';\nimport { constants } from 'node:fs';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { WORKFLOW_ARTIFACT_DIRECTORY } from '../../constants/artifacts';\nimport type { ArtifactItem, ArtifactSnapshot, ArtifactWorkflowVisibility } from '../../types/artifacts';\nimport { ArtifactAccessError, artifactMimeType, artifactRoot } from './artifactPaths';\n\nexport { ArtifactAccessError, artifactMimeType, artifactRoot } from './artifactPaths';\n\n/** A copy still being written: promoters write `.<name>.tmp` and rename it into place. */\nconst IN_FLIGHT_COPY = /^\\..+\\.tmp$/u;\nfunction inside(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);\n}\n\nfunction codeOf(error: unknown): string | undefined {\n return error instanceof Error && 'code' in error ? String(error.code) : undefined;\n}\n\n/** The owned directories must not redirect artifact access through a symlink. */\nasync function checkedRoot(root: string): Promise<string> {\n const base = path.dirname(root);\n for (const directory of [base, root]) {\n const stat = await fs.lstat(directory);\n if (!stat.isDirectory() || stat.isSymbolicLink())\n throw new ArtifactAccessError('The artifact folder is unavailable.', 403);\n }\n const realBase = await fs.realpath(base);\n const realRoot = await fs.realpath(root);\n if (!inside(realBase, realRoot))\n throw new ArtifactAccessError('The artifact folder is outside its storage directory.', 403);\n return realRoot;\n}\n\nexport async function ensureArtifactRoot(root: string): Promise<void> {\n await fs.mkdir(path.dirname(root), { recursive: true, mode: 0o700 });\n await fs.mkdir(root, { recursive: true, mode: 0o700 });\n await checkedRoot(root);\n}\n\n/** Open without following mutable ancestors. Node exposes no portable openat API. */\nasync function openContained(root: string, segments: string[]): Promise<fs.FileHandle> {\n if (process.platform === 'darwin') {\n // Darwin O_NOFOLLOW_ANY checks every component atomically. Do not combine it with O_NOFOLLOW.\n return fs.open(path.join(root, ...segments), constants.O_RDONLY | constants.O_NONBLOCK | 0x20000000);\n }\n if (process.platform !== 'linux') throw new ArtifactAccessError('Secure artifact reads require macOS or Linux.', 403);\n const flags = constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW;\n let directory = await fs.open(path.dirname(root), flags);\n try {\n for (const segment of [path.basename(root), ...segments.slice(0, -1)]) {\n const child = await fs.open(`/proc/self/fd/${directory.fd}/${segment}`, flags);\n await directory.close();\n directory = child;\n }\n return await fs.open(\n `/proc/self/fd/${directory.fd}/${segments.at(-1)!}`,\n constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,\n );\n } finally {\n await directory.close();\n }\n}\n\nfunction artifactSegments(requested: string | undefined): string[] {\n if (\n !requested ||\n requested.includes('\\0') ||\n requested.includes('\\\\') ||\n path.isAbsolute(requested) ||\n requested.split('/').some((part) => part === '..' || part === '.' || part === '')\n )\n throw new ArtifactAccessError('Invalid artifact path.', 400);\n return requested.split('/');\n}\n\nfunction accessError(error: unknown, action: string): unknown {\n if (error instanceof ArtifactAccessError) return error;\n if (codeOf(error) === 'ENOENT' || codeOf(error) === 'ENOTDIR')\n return new ArtifactAccessError('The artifact no longer exists.', 404);\n if (codeOf(error) === 'EACCES' || codeOf(error) === 'EPERM' || codeOf(error) === 'ELOOP')\n return new ArtifactAccessError(`The artifact cannot be ${action}.`, 403);\n return error;\n}\n\n/** One guarded open shared by metadata, text and byte reads. The caller closes the handle. */\nexport async function openArtifact(\n root: string,\n requested: string | undefined,\n workflowVisible?: ArtifactWorkflowVisibility,\n) {\n const segments = artifactSegments(requested);\n if (segments[0] === WORKFLOW_ARTIFACT_DIRECTORY && !workflowVisible?.(segments.slice(1).join('/'), 'file'))\n throw new ArtifactAccessError('This workflow file is private.', 403);\n try {\n const realRoot = await checkedRoot(root);\n const candidate = path.resolve(realRoot, requested!);\n if (!inside(realRoot, candidate))\n throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n let current = realRoot;\n for (let index = 0; index < segments.length; index += 1) {\n current = path.join(current, segments[index]!);\n const stat = await fs.lstat(current);\n if (stat.isSymbolicLink()) throw new ArtifactAccessError('Artifact symlinks cannot be read.', 403);\n if (index < segments.length - 1 ? !stat.isDirectory() : !stat.isFile())\n throw new ArtifactAccessError('The artifact is not a regular file.', 404);\n }\n const real = await fs.realpath(candidate);\n if (!inside(realRoot, real)) throw new ArtifactAccessError('The artifact is outside this session folder.', 403);\n const expected = await fs.lstat(real);\n const handle = await openContained(realRoot, segments);\n try {\n const stat = await handle.stat();\n if (!stat.isFile() || stat.dev !== expected.dev || stat.ino !== expected.ino)\n throw new ArtifactAccessError('The artifact changed while it was opened. Try again.', 403);\n return { handle, stat, path: requested!, mimeType: artifactMimeType(requested!) };\n } catch (error) {\n await handle.close();\n throw error;\n }\n } catch (error) {\n throw accessError(error, 'read');\n }\n}\n\n/** Bound allocation and read length even when the file grows after its metadata was read. */\nexport async function readArtifactBytes(handle: fs.FileHandle, size: number, offset = 0): Promise<Uint8Array> {\n const bytes = new Uint8Array(size);\n let read = 0;\n while (read < size) {\n const result = await handle.read(bytes, read, size - read, offset + read);\n if (result.bytesRead === 0) break;\n read += result.bytesRead;\n }\n return bytes.subarray(0, read);\n}\n\n/** Walk to the parent folder without following symlinks, creating missing folders on request. */\nasync function containedParent(realRoot: string, segments: string[], create: boolean): Promise<string> {\n let directory = realRoot;\n for (const segment of segments.slice(0, -1)) {\n directory = path.join(directory, segment);\n if (create)\n await fs.mkdir(directory, { mode: 0o700 }).catch((error: unknown) => {\n if (codeOf(error) !== 'EEXIST') throw error;\n });\n const stat = await fs.lstat(directory);\n if (stat.isSymbolicLink() || !stat.isDirectory())\n throw new ArtifactAccessError('The artifact folder is not a directory.', 403);\n }\n return directory;\n}\n\nasync function sameText(root: string, requested: string, bytes: Buffer): Promise<boolean> {\n try {\n const file = await openArtifact(root, requested);\n try {\n if (file.stat.size !== bytes.length) return false;\n return bytes.equals(await readArtifactBytes(file.handle, file.stat.size));\n } finally {\n await file.handle.close();\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError) return false;\n throw error;\n }\n}\n\n/**\n * Publish text through a same-folder temp file and rename, skipping identical content so mtimes stay stable.\n * ponytail: best-effort same-user guards, not race-resistant. Linux checks ancestors with lstat only;\n * walk with openat-style /proc/self/fd handles like openContained if artifacts cross a trust boundary.\n */\nexport async function writeArtifactText(root: string, requested: string, text: string): Promise<void> {\n const segments = artifactSegments(requested);\n if (process.platform !== 'darwin' && process.platform !== 'linux')\n throw new ArtifactAccessError('Secure artifact writes require macOS or Linux.', 403);\n const bytes = Buffer.from(text, 'utf8');\n try {\n await ensureArtifactRoot(root);\n const directory = await containedParent(await checkedRoot(root), segments, true);\n if (await sameText(root, requested, bytes)) return;\n const temp = path.join(directory, `.${segments.at(-1)!}.${randomUUID()}.tmp`);\n // Darwin O_NOFOLLOW_ANY refuses a symlink in any component; O_EXCL refuses one at the leaf.\n const flags =\n constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (process.platform === 'darwin' ? 0x20000000 : 0);\n const handle = await fs.open(temp, flags, 0o600);\n try {\n await handle.writeFile(bytes);\n await handle.close();\n await fs.rename(temp, path.join(directory, segments.at(-1)!));\n } catch (error) {\n await handle.close().catch(() => undefined);\n await fs.unlink(temp).catch(() => undefined);\n throw error;\n }\n } catch (error) {\n throw accessError(error, 'written');\n }\n}\n\n/** Remove one file or one empty folder. A missing target is already removed; nothing is deleted recursively. */\nexport async function removeArtifact(root: string, requested: string): Promise<void> {\n const segments = artifactSegments(requested);\n try {\n const target = path.join(await containedParent(await checkedRoot(root), segments, false), segments.at(-1)!);\n const stat = await fs.lstat(target);\n if (stat.isFile()) await fs.unlink(target);\n else if (!stat.isDirectory()) throw new ArtifactAccessError('The artifact is not a file or folder.', 403);\n else\n await fs.rmdir(target).catch((error: unknown) => {\n if (codeOf(error) !== 'ENOTEMPTY' && codeOf(error) !== 'EEXIST') throw error;\n });\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return;\n throw accessError(error, 'removed');\n }\n}\n/** Discover persisted session roots without admitting symlinked or malformed owners. */\nexport async function listArtifactSessions(\n environment: Readonly<Record<string, string | undefined>>,\n): Promise<readonly string[]> {\n const parent = path.dirname(artifactRoot('discovery', environment));\n try {\n const stat = await fs.lstat(parent);\n if (!stat.isDirectory() || stat.isSymbolicLink())\n throw new ArtifactAccessError('The artifact storage directory is unavailable.', 403);\n const entries = await fs.readdir(parent, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory() && /^[a-zA-Z0-9_-]+$/u.test(entry.name))\n .map((entry) => entry.name);\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return [];\n throw error;\n }\n}\n\nexport async function listArtifacts(\n root: string,\n workflowVisible?: ArtifactWorkflowVisibility,\n): Promise<ArtifactSnapshot> {\n const items: ArtifactItem[] = [];\n try {\n const realRoot = await checkedRoot(root);\n const visit = async (directory: string): Promise<void> => {\n for (const entry of await fs.readdir(directory, { withFileTypes: true })) {\n const location = path.join(directory, entry.name);\n const relativePath = path.relative(realRoot, location).split(path.sep).join('/');\n const segments = relativePath.split('/');\n if (\n segments[0] === WORKFLOW_ARTIFACT_DIRECTORY &&\n !workflowVisible?.(segments.slice(1).join('/'), entry.isDirectory() ? 'directory' : 'file')\n )\n continue;\n if (entry.isDirectory()) {\n // Recheck each directory rather than trusting a readdir entry across a rename.\n const stat = await fs.lstat(location);\n if (!stat.isDirectory() || stat.isSymbolicLink()) continue;\n const real = await fs.realpath(location);\n if (inside(realRoot, real)) await visit(real);\n } else if (entry.isFile() && !IN_FLIGHT_COPY.test(entry.name)) {\n try {\n const file = await openArtifact(root, relativePath, workflowVisible);\n try {\n items.push({ path: relativePath, name: entry.name, size: file.stat.size, modifiedAt: file.stat.mtimeMs });\n } finally {\n await file.handle.close();\n }\n } catch (error) {\n if (error instanceof ArtifactAccessError && (error.status === 404 || error.status === 403)) continue;\n throw error;\n }\n }\n }\n };\n await visit(realRoot);\n items.sort(\n (left, right) =>\n right.modifiedAt - left.modifiedAt || (left.path < right.path ? -1 : left.path > right.path ? 1 : 0),\n );\n return { items };\n } catch (error) {\n if (codeOf(error) === 'ENOENT') return { items: [] };\n return { items: [], error: error instanceof Error ? error.message : 'The artifact folder could not be read.' };\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_artifactFiles = require("./artifactFiles-BmBU9Olm.cjs");
2
+ const require_artifactFiles = require("./artifactFiles-C8dqPVra.cjs");
3
3
  const require_artifacts = require("./artifacts-DG_b7DZH.cjs");
4
4
  exports.ArtifactAccessError = require_artifactFiles.ArtifactAccessError;
5
5
  exports.COMPACTION_ARTIFACT_DIRECTORY = require_artifacts.COMPACTION_ARTIFACT_DIRECTORY;
@@ -1 +1 @@
1
- {"version":3,"file":"artifactFiles.d.mts","names":[],"sources":["../src/services/artifactFiles/artifactPaths.ts","../src/services/artifactFiles/index.ts"],"mappings":";;;qBAMa,4BAA4B;WAG5B;EAFX,YACE,iBACS;;wBAMG,aAAa,mBAAmB,aAAa,SAAS;;;;wBCwEhD,aACpB,cACA,+BACA,kBAAkB,6BAA0B;;;;;;;wBAqCxB,kBAAkB,QAAQ,GAAG,YAAY,cAAc,kBAAa,QAAQ;;;;;;wBA+C5E,kBAAkB,cAAc,mBAAmB,eAAe;;wBA6BlE,eAAe,cAAc,oBAAoB;;wBAiBjD,qBACpB,aAAa,SAAS,sCACrB;wBAgBmB,cACpB,cACA,kBAAkB,6BACjB,QAAQ"}
1
+ {"version":3,"file":"artifactFiles.d.mts","names":[],"sources":["../src/services/artifactFiles/artifactPaths.ts","../src/services/artifactFiles/index.ts"],"mappings":";;;qBAMa,4BAA4B;WAG5B;EAFX,YACE,iBACS;;wBAMG,aAAa,mBAAmB,aAAa,SAAS;;;;wBC0EhD,aACpB,cACA,+BACA,kBAAkB,6BAA0B;;;;;;;wBAqCxB,kBAAkB,QAAQ,GAAG,YAAY,cAAc,kBAAa,QAAQ;;;;;;wBA+C5E,kBAAkB,cAAc,mBAAmB,eAAe;;wBA6BlE,eAAe,cAAc,oBAAoB;;wBAiBjD,qBACpB,aAAa,SAAS,sCACrB;wBAgBmB,cACpB,cACA,kBAAkB,6BACjB,QAAQ"}
@@ -1,3 +1,3 @@
1
1
  import { a as COMPACTION_ARTIFACT_DIRECTORY } from "./artifacts-Bhobz1nK.mjs";
2
- import { a as readArtifactBytes, c as ArtifactAccessError, i as openArtifact, l as artifactRoot, n as listArtifactSessions, o as removeArtifact, r as listArtifacts, s as writeArtifactText } from "./artifactFiles-DyIkevXc.mjs";
2
+ import { a as readArtifactBytes, c as ArtifactAccessError, i as openArtifact, l as artifactRoot, n as listArtifactSessions, o as removeArtifact, r as listArtifacts, s as writeArtifactText } from "./artifactFiles-BJL1H1QG.mjs";
3
3
  export { ArtifactAccessError, COMPACTION_ARTIFACT_DIRECTORY, artifactRoot, listArtifactSessions, listArtifacts, openArtifact, readArtifactBytes, removeArtifact, writeArtifactText };