podd Native Streaming Archive-Sync and Process Output Tail Enhancements
Source:
docs/enhancements/0006-podd-archive-sync/README.md· Status:implemented· Area:core· Milestone:—| Field | Value | | :--- | :--- | | CEP Number |0006| | Title |poddNative Streamingarchive-syncand Process Output Tail Enhancements | | Authors |@cubeplex-arch| | Status |implemented| | Target Version |v0.2.0| | Created |2026-11-10| | Last Updated |2026-11-10|
Summary
Section titled “Summary”This CEP extends the in-guest Rust daemon podd (crates/podd) with a native POST /v1/files/archive-sync endpoint so that .tar.gz and .tar workspace synchronization archives are unpacked directly inside the sandbox guest (Kata MicroVM or Docker container) with path-traversal protection, optional pre-extraction file removal (remove_paths), and automatic 1000:1000 (cubeplex:cubeplex) ownership assignment.
Motivation
Section titled “Motivation”In v0.1.0, POST /sandboxes/{sandboxID}/files/archive-sync was unpacked by cubepod-gateway into a local workspace directory. In production Kubernetes (Kata + CSI) and isolated Docker containers, cubepod-gateway has no direct host filesystem access to the sandbox’s /workspace or / mount namespace; all file synchronization must travel over HTTP to podd (:49983) inside the guest.
- Implement
POST /v1/files/archive-sync?dest=/workspace&uid=1000&gid=1000&remove_paths=a,bincrates/podd/src/main.rs. - Support both
.tar.gz(application/gzipor magic bytes0x1f 0x8b) and uncompressed.tar(application/x-tar) payloads. - Reject any archive entry containing
..components or absolute paths (400 Bad Request) before modifying disk state. - Apply
chown(uid, gid)to extracted files and directories whengeteuid() == 0. - Support
DELETE /v1/files?path=/workspace/fooso individual files or directories can be removed viapodd.
Non-Goals
Section titled “Non-Goals”- Adding external Rust crate dependencies (
flate2/tar);podduses either safe in-tree IEEE POSIX ustar parsing + systemtar/gzipfallback so the binary stays zero-dependency and tiny (<400 KB).
Proposal
Section titled “Proposal”User Stories
Section titled “User Stories”Story 1: Remote Multi-File Sync into Isolated MicroVM
Section titled “Story 1: Remote Multi-File Sync into Isolated MicroVM”As cubepod-gateway, when a user calls archive_sync() via the Python SDK, I can forward the raw .tar.gz HTTP request body directly to http://<sandbox-ip>:49983/v1/files/archive-sync?dest=/workspace&uid=1000&gid=1000 and receive {"status":"synced","dest":"/workspace","extracted":N}.
Risks and Mitigations
Section titled “Risks and Mitigations”| Risk | Impact | Likelihood | Mitigation |
|---|---|---|---|
Malicious tar entry (../../etc/shadow or symlink escape) |
High | Medium | Inspect every tar entry header prior to extraction; reject any entry with .., leading /, or symlink/hardlink type pointing outside dest with 400 Bad Request. |
Design Details
Section titled “Design Details”API / Wire Contract on podd (:49983)
Section titled “API / Wire Contract on podd (:49983)”POST /v1/files/archive-sync:- Query params:
dest(default/workspace)uid(default1000)gid(default1000)remove_paths(optional comma-separated relative paths underdestto remove before extraction)
- Request body: raw
.tar.gz(magic bytes0x1f 0x8b) or.tarbytes. - Validation:
- Parse tar entries (decompressing via
gzip -dcpipe when gzip magic bytes0x1f 0x8bare present, or pure-Rust tar block reader) and validate every entry path before writing todest. - If any entry path is absolute or contains
..path segments, abort immediately and return400 Bad Request({"error":"invalid_archive_path"}).
- Parse tar entries (decompressing via
- Response (
200 OK):{"status":"synced","dest":"/workspace","extracted":3}
- Query params:
DELETE /v1/files?path=/workspace/old.txt:- Removes a file or directory tree (
remove_file/remove_dir_all) inside the guest and returns200 OK({"deleted":"/workspace/old.txt"}), or404 Not Foundif missing.
- Removes a file or directory tree (
Runtime Behavior (Production Kubernetes vs. Local Development)
Section titled “Runtime Behavior (Production Kubernetes vs. Local Development)”- Production Mode (
Kata + CSI Raw Block): Unpacks archives directly onto the mounted/dev/cubepod-workspace(ext4) or persistent RootFSupperdirinside the MicroVM. - Local Development Mode (
Docker + Loopback ext4): Identical behavior inside the Docker container.
Test Plan
Section titled “Test Plan”- Unit & Integration Tests (
crates/podd/src/main.rs):test_archive_sync_tar_gz_and_remove_paths: Create a real.tar.gzarchive containing nested files (src/main.py,README.md), upload toPOST /v1/files/archive-sync?dest=<tmp>&remove_paths=stale.txt, verifystale.txtis removed,src/main.pyandREADME.mdare extracted with exact contents, andextracted == 2.test_archive_sync_rejects_path_traversal: Craft a tar archive containing../escape.txtand verifyPOST /v1/files/archive-syncreturns400 Bad Requestand does not create the file.test_file_delete_endpoint: VerifyDELETE /v1/files?path=...deletes files and returns404on missing paths.
Graduation Criteria
Section titled “Graduation Criteria”cargo test -p poddandcargo clippy -p podd -- -D warningspass with 0 warnings.
Upgrade / Downgrade Strategy
Section titled “Upgrade / Downgrade Strategy”- Backward-compatible additive endpoints on
podd.
Production Readiness Review (PRR)
Section titled “Production Readiness Review (PRR)”- Observability: Returns structured JSON counts of extracted files and error codes.
- Security: Strict pre-extraction tar header path traversal validation.
Alternatives Considered
Section titled “Alternatives Considered”- Multiple
PUT /v1/filescalls from Gateway: Rejected because high-latency per-file round-trips degrade agent workspace initialization when syncing dozens of source files.