mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-18 14:13:34 +00:00
fix(collaboration): harden delegated task isolation (#1486)
* feat(collaboration): isolate delegated artifacts and child runs Isolate delegated inputs and outputs behind secure artifact exchange lifecycles. Scope Agent Link tasks by tenant and root agent, and enforce delegation spawn-tree boundaries. Add process-wide child-run admission and preserve logical media paths across native, MCP, and sandbox execution. * fix(collaboration): harden delegated task isolation Enforce tenant and root-agent task scope across migrations and stores. Add exactly-once async completion delivery, delegated sandbox boundaries, and confined artifact and media recovery across runtime surfaces. * fix(collaboration): recover interrupted async tasks * fix(collaboration): normalize persisted child-run status --------- Co-authored-by: ntduc <ntduc@cpp.ai.vn>
This commit is contained in:
1 parent
496b7ffce6
commit
bb7712a9ff
186 files changed
+18858
-1233
No files matched your search
@@ -42,9 +42,15 @@ func TestResolveDocumentFileAcceptsWorkspacePath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDocumentFileMatchesUploadedFilenameAlias(t *testing.T) {
|
||||
func TestResolveDocumentFileRequiresExactMediaID(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
docPath := filepath.Join(workspace, ".uploads", "codex-9c8914a5.zip")
|
||||
if err := os.MkdirAll(filepath.Dir(docPath), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(docPath, []byte("zip bytes"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
refs := []providers.MediaRef{{
|
||||
ID: uuid.NewString(),
|
||||
Kind: "document",
|
||||
@@ -53,13 +59,22 @@ func TestResolveDocumentFileMatchesUploadedFilenameAlias(t *testing.T) {
|
||||
}}
|
||||
|
||||
tool := NewReadDocumentTool(nil, nil)
|
||||
ctx := WithMediaDocRefs(context.Background(), refs)
|
||||
gotPath, gotMime, err := tool.resolveDocumentFile(ctx, "codex.zip", "")
|
||||
if err != nil {
|
||||
t.Fatalf("resolveDocumentFile returned error: %v", err)
|
||||
ctx := WithToolWorkspace(context.Background(), workspace)
|
||||
ctx = WithMediaDocRefs(ctx, refs)
|
||||
if gotPath, _, err := tool.resolveDocumentFile(ctx, "codex.zip", ""); err == nil {
|
||||
t.Fatalf("filename alias resolved to %q, want exact media_id error", gotPath)
|
||||
}
|
||||
if gotPath != docPath {
|
||||
t.Fatalf("path = %q, want %q", gotPath, docPath)
|
||||
|
||||
gotPath, gotMime, err := tool.resolveDocumentFile(ctx, refs[0].ID, "")
|
||||
if err != nil {
|
||||
t.Fatalf("exact media_id returned error: %v", err)
|
||||
}
|
||||
wantPath, err := filepath.EvalSymlinks(docPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if gotPath != wantPath {
|
||||
t.Fatalf("path = %q, want %q", gotPath, wantPath)
|
||||
}
|
||||
if gotMime != "application/zip" {
|
||||
t.Fatalf("mime = %q, want application/zip", gotMime)
|
||||
@@ -84,19 +99,85 @@ func TestResolveDocumentFileInvalidMediaIDReturnsError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestResolveDocumentFileOmittedMediaIDUsesLastRef(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
oldPath := filepath.Join(workspace, ".uploads", "old.pdf")
|
||||
latestPath := filepath.Join(workspace, ".uploads", "latest.pdf")
|
||||
if err := os.MkdirAll(filepath.Dir(oldPath), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, path := range []string{oldPath, latestPath} {
|
||||
if err := os.WriteFile(path, []byte("pdf"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
refs := []providers.MediaRef{
|
||||
{ID: uuid.NewString(), Kind: "document", Path: "/workspace/.uploads/old.pdf", MimeType: "application/pdf"},
|
||||
{ID: uuid.NewString(), Kind: "document", Path: "/workspace/.uploads/latest.pdf", MimeType: "application/pdf"},
|
||||
{ID: uuid.NewString(), Kind: "document", Path: oldPath, MimeType: "application/pdf"},
|
||||
{ID: uuid.NewString(), Kind: "document", Path: latestPath, MimeType: "application/pdf"},
|
||||
}
|
||||
|
||||
tool := NewReadDocumentTool(nil, nil)
|
||||
ctx := WithMediaDocRefs(context.Background(), refs)
|
||||
ctx := WithToolWorkspace(context.Background(), workspace)
|
||||
ctx = WithMediaDocRefs(ctx, refs)
|
||||
gotPath, _, err := tool.resolveDocumentFile(ctx, "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("resolveDocumentFile returned error: %v", err)
|
||||
}
|
||||
if gotPath != refs[1].Path {
|
||||
t.Fatalf("path = %q, want most recent %q", gotPath, refs[1].Path)
|
||||
wantPath, err := filepath.EvalSymlinks(refs[1].Path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if gotPath != wantPath {
|
||||
t.Fatalf("path = %q, want most recent %q", gotPath, wantPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDocumentFileRejectsRefPathOutsideWorkspace(t *testing.T) {
|
||||
workspace := t.TempDir()
|
||||
outsideDir := t.TempDir()
|
||||
outsidePath := filepath.Join(outsideDir, "secret.pdf")
|
||||
if err := os.WriteFile(outsidePath, []byte("secret"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ref := providers.MediaRef{
|
||||
ID: uuid.NewString(),
|
||||
Kind: "document",
|
||||
Path: outsidePath,
|
||||
MimeType: "application/pdf",
|
||||
}
|
||||
|
||||
ctx := WithToolWorkspace(context.Background(), workspace)
|
||||
ctx = WithToolTeamWorkspace(ctx, outsideDir)
|
||||
ctx = WithMediaDocRefs(ctx, []providers.MediaRef{ref})
|
||||
gotPath, _, err := NewReadDocumentTool(nil, nil).resolveDocumentFile(ctx, ref.ID, "")
|
||||
if err == nil {
|
||||
t.Fatalf("outside ref path resolved to %q, want containment error", gotPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDocumentFileAcceptsDelegationInputRef(t *testing.T) {
|
||||
ctx, inputs, _ := delegationArtifactToolContext(t)
|
||||
docPath := filepath.Join(inputs, "brief.pdf")
|
||||
if err := os.WriteFile(docPath, []byte("pdf"), 0o440); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ref := providers.MediaRef{
|
||||
ID: uuid.NewString(),
|
||||
Kind: "document",
|
||||
Path: "inputs/brief.pdf",
|
||||
MimeType: "application/pdf",
|
||||
}
|
||||
ctx = WithMediaDocRefs(ctx, []providers.MediaRef{ref})
|
||||
|
||||
gotPath, _, err := NewReadDocumentTool(nil, nil).resolveDocumentFile(ctx, ref.ID, "")
|
||||
if err != nil {
|
||||
t.Fatalf("delegation input ref returned error: %v", err)
|
||||
}
|
||||
wantPath, err := filepath.EvalSymlinks(docPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if gotPath != wantPath {
|
||||
t.Fatalf("path = %q, want staged input %q", gotPath, wantPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +202,24 @@ func TestReadDocumentArchiveReturnsExecHint(t *testing.T) {
|
||||
if result.IsError {
|
||||
t.Fatalf("expected archive hint, got error: %s", result.ForLLM)
|
||||
}
|
||||
if !strings.Contains(result.ForLLM, "unzip -l") || !strings.Contains(result.ForLLM, docPath) {
|
||||
t.Fatalf("expected unzip hint with path, got: %s", result.ForLLM)
|
||||
if !strings.Contains(result.ForLLM, "unzip -l") ||
|
||||
!strings.Contains(result.ForLLM, ".uploads/codex-9c8914a5.zip") {
|
||||
t.Fatalf("expected unzip hint with logical path, got: %s", result.ForLLM)
|
||||
}
|
||||
if strings.Contains(result.ForLLM, workspace) || strings.Contains(result.ForLLM, docPath) {
|
||||
t.Fatalf("archive hint leaked physical workspace path: %s", result.ForLLM)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadDocumentRejectsMediaIDAndPathTogether(t *testing.T) {
|
||||
tool := NewReadDocumentTool(nil, nil)
|
||||
result := tool.Execute(context.Background(), map[string]any{
|
||||
"prompt": "Inspect",
|
||||
"media_id": uuid.NewString(),
|
||||
"path": ".uploads/document.pdf",
|
||||
})
|
||||
|
||||
if !result.IsError || !strings.Contains(result.ForLLM, "either media_id or path") {
|
||||
t.Fatalf("result = %#v, want mutually exclusive argument error", result)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user