Feat v0.8.1 workspace module
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 3s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m47s
CI/CD / test-sqlite (pull_request) Successful in 2m55s
CI/CD / build-and-deploy (pull_request) Successful in 1m10s

Managed disk directories for extensions needing real filesystem access
(git, compilers, media tools). Five builtins: create, path, list,
delete, usage. Extension-scoped to {WORKSPACE_ROOT}/{packageID}/{name}/.

- New sandbox/workspace_module.go with path traversal + symlink protection
- Permission: workspace.manage; config: WORKSPACE_ROOT, WORKSPACE_QUOTA_MB
- Runner wiring with graceful degradation (module absent if root unwritable)
- 16 new tests, all passing with -race

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 00:33:43 +00:00
parent 694779fac6
commit 7a47ce8557
9 changed files with 681 additions and 6 deletions

View File

@@ -47,6 +47,12 @@ type Config struct {
S3Prefix string // optional key prefix within bucket (e.g. "armature/")
S3ForcePathStyle bool // use path-style URLs (required for MinIO, most self-hosted)
// Extension workspaces
// WORKSPACE_ROOT: mount point for extension-managed directories (default /data/workspaces).
// WORKSPACE_QUOTA_MB: per-extension quota in MB (default 0 = unlimited).
WorkspaceRoot string
WorkspaceQuotaMB int
// Structured logging
// LOG_FORMAT: "text" (default, backward-compatible) or "json" (structured).
// LOG_LEVEL: "debug", "info" (default), "warn", "error".
@@ -143,6 +149,9 @@ func Load() *Config {
S3Prefix: getEnv("S3_PREFIX", ""),
S3ForcePathStyle: getEnv("S3_FORCE_PATH_STYLE", "true") == "true",
WorkspaceRoot: getEnv("WORKSPACE_ROOT", "/data/workspaces"),
WorkspaceQuotaMB: getEnvInt("WORKSPACE_QUOTA_MB", 0),
SkipBundledPackages: getEnvBool("SKIP_BUNDLED_PACKAGES", false),
BundledPackagesDir: getEnv("BUNDLED_PACKAGES_DIR", "/app/bundled-packages"),
BundledPackages: getEnv("BUNDLED_PACKAGES", ""),