Skip to content

feat(#3996): keep generated media workspace-only with portable session copies - #4026

Open
aheritier wants to merge 2 commits into
workspace-media-materializationfrom
workspace-media-escape-confirm
Open

feat(#3996): keep generated media workspace-only with portable session copies#4026
aheritier wants to merge 2 commits into
workspace-media-materializationfrom
workspace-media-escape-confirm

Conversation

@aheritier

@aheritier aheritier commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

What and why

Keep all generated-media writes inside the owning workspace. Absolute, traversal, home-relative, external, and symlink-escaping requests are redirected to a sanitized basename in the workspace with a bounded warning; there is no external-write behavior, confirmation/dialog/schema, or ArtifactRootExternal path. ACP foreground sessions complete and persist assistant text plus workspace artifact metadata without an elicitation consumer. After file and manifest recording, optionally store the complete bytes as a portable session blob without an application-level cap; blob failure warns and preserves the workspace file. Deleting a session removes manifest/blob rows, never workspace files. The root-kind migration remains for compatibility, and old unknown/external rows fail closed.

Part of #3996. Review this PR against its immediate parent, #4025, rather than the aggregate stack against main.

Commit inventory

Head: 1409e8b414370be9a472cad3d889d0cc8a2316c9; parent SHA: 9d7da808954352fc5fd7c54aeeacc8240c0bcc2d.

Validation

Build, test compilation, owning-package tests and the named fixture passed at this PR head.

Exact deterministic fixture command:

go test -v -count=1 ./pkg/runtime ./pkg/acp ./pkg/session ./pkg/workspacemedia ./pkg/cli -run 'TestMaterializeGeneratedMedia_Redirect|TestRunStream_EscapingGeneratedMediaCompletesWithoutElicitation|TestPrompt_EscapingGeneratedMediaCompletesWithoutElicitation|TestGeneratedMediaBlobStore|TestGeneratedMediaManifest_DeleteSessionPrunesBlob|TestRequestedBasename|TestClassifyRequestedPath|TestNonOAuthElicitationDeclinedAndStreamDrained'

Matched top-level tests: pkg/acp: 1; pkg/cli: 1; pkg/runtime: 4; pkg/session: 2; pkg/workspacemedia: 2.

Deterministic scope: the named local fixture exercises this PR boundary with disposable configuration/stores and fake or loopback providers as applicable. Every listed package ran nonzero matching top-level tests.

Deferred/live scope: No active database was read, copied, migrated, or mutated. The final stack head passed build, lint, full tests, an uncached full suite, focused race tests and documentation checks in disposable environments. Remote CI is tracked by the checks below; no new paid-provider or active-database validation was run.

@aheritier aheritier added area/cli CLI commands, flags, output formatting area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only. labels Aug 22, 2026
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 9b6e49d to 8e76a13 Compare August 24, 2026 15:13
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 8e76a13 to 871dd1e Compare August 25, 2026 08:00
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch 2 times, most recently from e76fa5b to 0fe2b64 Compare August 25, 2026 08:32
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 0fe2b64 to d6b3c12 Compare August 25, 2026 20:24
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from d6b3c12 to 9a926c1 Compare August 26, 2026 11:09
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch 2 times, most recently from 426aea6 to 9a926c1 Compare September 1, 2026 16:10
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 9a926c1 to c442c63 Compare September 1, 2026 16:30
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from c442c63 to 161aaa6 Compare September 1, 2026 19:58
aheritier

This comment was marked as resolved.

@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 161aaa6 to 5b26f97 Compare September 6, 2026 16:14
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 5b26f97 to ffb1c83 Compare September 7, 2026 11:19
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from f5cc603 to 32b0b74 Compare September 8, 2026 06:17
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 32b0b74 to 94da09d Compare September 8, 2026 07:57
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 94da09d to 69f32a6 Compare September 8, 2026 17:31
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 69f32a6 to 1409e8b Compare September 8, 2026 20:35
@aheritier aheritier changed the title feat(#3996): gate workspace-escaping generated-media paths behind user confirmation feat(#3996): keep generated media workspace-only with portable session copies Sep 8, 2026
@aheritier
aheritier marked this pull request as ready for review September 8, 2026 20:39
@aheritier
aheritier requested a review from a team as a code owner September 8, 2026 20:39
@dgageot
dgageot force-pushed the workspace-media-escape-confirm branch from 1409e8b to 54fae97 Compare September 9, 2026 07:41
dgageot
dgageot previously approved these changes Sep 9, 2026
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 54fae97 to a457e35 Compare September 9, 2026 11:56
@dgageot
dgageot force-pushed the workspace-media-escape-confirm branch from a457e35 to 8540d7e Compare September 9, 2026 12:15
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 8540d7e to 0eb0403 Compare September 9, 2026 12:56
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from 0eb0403 to ddd1977 Compare September 9, 2026 13:32
@aheritier
aheritier force-pushed the workspace-media-escape-confirm branch from ddd1977 to 0089fb8 Compare September 9, 2026 14:07
Redirect absolute, traversal, home-relative and symlink-escaping targets to a sanitized workspace basename with a bounded warning. Generated media never elicits a path decision or writes externally; normal ACP and CLI turns complete without a form consumer. Preserve MIME correction, collision-safe atomic writes, partial success, owning-session provenance and workspace-only manifest authorization. Keep the pinned root-kind migration for database compatibility.
After successful workspace materialization and manifest recording, store
the bytes under the owning session and final artifact identity. Add the
SQLite blob table as migration 029 and place the manifest root-kind
migration at 030. The workspace deliverable remains available at its
requested or collision-adjusted path; the session copy enables portable
resolution without embedding generated base64 in session JSON.

Blob writes are all-or-error without a per-item byte cap. A failed blob
write preserves the workspace file and emits a safe portability warning.
DeleteSession removes both manifest and blob rows. The in-memory store
mirrors add, lookup, defensive copying, overwrite, and cleanup semantics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli CLI commands, flags, output formatting area/runtime Runtime engine, agent loop execution, tool dispatch, loop detection area/sessions For features/issues/fixes related to session lifecycle (resume, persistence, export) area/tui For features/issues/fixes related to the TUI kind/feat PR adds a new feature (maps to feat:). Use on PRs only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants