[codex] Extract filesystem safety primitives (#77918)

* refactor: extract filesystem safety primitives

* refactor: use fs-safe for file access helpers

* refactor: reuse fs-safe for media reads

* refactor: use fs-safe for image reads

* refactor: reuse fs-safe in qqbot media opener

* refactor: reuse fs-safe for local media checks

* refactor: consume cleaner fs-safe api

* refactor: align fs-safe json option names

* fix: preserve fs-safe migration contracts

* refactor: use fs-safe primitive subpaths

* refactor: use grouped fs-safe subpaths

* refactor: align fs-safe api usage

* refactor: adapt private state store api

* chore: refresh proof gate

* refactor: follow fs-safe json api split

* refactor: follow reduced fs-safe surface

* build: default fs-safe python helper off

* fix: preserve fs-safe plugin sdk aliases

* refactor: consolidate fs-safe usage

* refactor: unify fs-safe store usage

* refactor: trim fs-safe temp workspace usage

* refactor: hide low-level fs-safe primitives

* build: use published fs-safe package

* fix: preserve outbound recovery durability after rebase

* chore: refresh pr checks
This commit is contained in:
Peter Steinberger
2026-05-06 02:15:17 +01:00
committed by GitHub
parent 61481eb34f
commit 538605ff44
356 changed files with 4918 additions and 11913 deletions

View File

@@ -1,6 +1,7 @@
import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { root as fsRoot } from "openclaw/plugin-sdk/security-runtime";
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import type { PluginLogger } from "../api.js";
import type { DiffArtifactContext, DiffArtifactMeta, DiffOutputFormat } from "./types.js";
@@ -36,6 +37,7 @@ type StandaloneFileMeta = {
};
type ArtifactMetaFileName = "meta.json" | "file-meta.json";
type ArtifactRoot = Awaited<ReturnType<typeof fsRoot>>;
export class DiffArtifactStore {
private readonly rootDir: string;
@@ -76,8 +78,9 @@ export class DiffArtifactStore {
...(params.context ? { context: params.context } : {}),
};
await fs.mkdir(artifactDir, { recursive: true });
await fs.writeFile(htmlPath, params.html, "utf8");
const root = await this.artifactRoot();
await root.mkdir(id);
await root.write(path.posix.join(id, "viewer.html"), params.html);
await this.writeMeta(meta);
this.scheduleCleanup();
return meta;
@@ -104,7 +107,7 @@ export class DiffArtifactStore {
throw new Error(`Diff artifact not found: ${id}`);
}
const htmlPath = this.normalizeStoredPath(meta.htmlPath, "htmlPath");
return await fs.readFile(htmlPath, "utf8");
return await (await this.artifactRoot()).readText(this.relativeStoredPath(htmlPath));
}
async updateFilePath(id: string, filePath: string): Promise<DiffArtifactMeta> {
@@ -151,7 +154,7 @@ export class DiffArtifactStore {
...(params.context ? { context: params.context } : {}),
};
await fs.mkdir(artifactDir, { recursive: true });
await (await this.artifactRoot()).mkdir(id);
await this.writeStandaloneMeta(meta);
this.scheduleCleanup();
return {
@@ -212,6 +215,11 @@ export class DiffArtifactStore {
await fs.mkdir(this.rootDir, { recursive: true });
}
private async artifactRoot(): Promise<ArtifactRoot> {
await this.ensureRoot();
return await fsRoot(this.rootDir);
}
private maybeCleanupExpired(): void {
const now = Date.now();
if (this.cleanupInFlight || now < this.nextCleanupAt) {
@@ -283,16 +291,12 @@ export class DiffArtifactStore {
}
}
private metaFilePath(id: string, fileName: ArtifactMetaFileName): string {
return path.join(this.artifactDir(id), fileName);
}
private async writeJsonMeta(
id: string,
fileName: ArtifactMetaFileName,
data: unknown,
): Promise<void> {
await fs.writeFile(this.metaFilePath(id, fileName), JSON.stringify(data, null, 2), "utf8");
await (await this.artifactRoot()).writeJson(path.posix.join(id, fileName), data, { space: 2 });
}
private async readJsonMeta(
@@ -301,7 +305,7 @@ export class DiffArtifactStore {
context: string,
): Promise<unknown> {
try {
const raw = await fs.readFile(this.metaFilePath(id, fileName), "utf8");
const raw = await (await this.artifactRoot()).readText(path.posix.join(id, fileName));
return JSON.parse(raw) as unknown;
} catch (error) {
if (isFileNotFound(error)) {
@@ -330,6 +334,11 @@ export class DiffArtifactStore {
return candidate;
}
private relativeStoredPath(storedPath: string): string {
const relativePath = path.relative(this.rootDir, this.normalizeStoredPath(storedPath, "path"));
return relativePath.split(path.sep).join(path.posix.sep);
}
private assertWithinRoot(candidate: string, label = "path"): void {
const relative = path.relative(this.rootDir, candidate);
if (
@@ -362,7 +371,8 @@ function isExpired(meta: { expiresAt: string }): boolean {
}
function isFileNotFound(error: unknown): boolean {
return error instanceof Error && "code" in error && error.code === "ENOENT";
const code = error instanceof Error && "code" in error ? error.code : undefined;
return code === "ENOENT" || code === "not-found";
}
function normalizeArtifactContext(value: unknown): DiffArtifactContext | undefined {