package workspace import ( "context" "os" "path/filepath" "testing" "chat-agent-system/internal/app/uow" ) func issued(t *testing.T, cap *Capability, id string, project int64) WorkspaceRef { t.Helper() ref, err := cap.Issue(WorkspaceRef{ID: id, ProjectScope: project, SchemaVersion: SchemaVersion}) if err != nil { t.Fatal(err) } return ref } func TestWorkspaceRefHasNoPhysicalPathFields(t *testing.T) { var ref WorkspaceRef _ = ref.ID _ = ref.SchemaVersion _ = ref.FencingToken _ = ref.ProjectScope _ = ref.RunID _ = ref.Environment } func TestCapabilityRejectsBadKeys(t *testing.T) { cap := NewCapability(t.TempDir(), nil) ref := issued(t, cap, "ws1", 7) ctx := context.Background() for _, key := range []string{"", "../etc/passwd", "/etc/passwd", "..", "a/../b", "a//b", "%2e%2e/secret", "ok/%2fetc"} { if _, err := cap.ReadArtifact(ctx, ref, key); err == nil { t.Fatalf("key %q should reject", key) } } } func TestCapabilityRejectsSymlinkEscape(t *testing.T) { root := t.TempDir() cap := NewCapability(root, nil) ref := issued(t, cap, "ws1", 7) outside := filepath.Join(t.TempDir(), "secret") if err := os.WriteFile(outside, []byte("nope"), 0o644); err != nil { t.Fatal(err) } wsDir := filepath.Join(root, "workspaces", "ws1") if err := os.MkdirAll(wsDir, 0o755); err != nil { t.Fatal(err) } link := filepath.Join(wsDir, "leak") if err := os.Symlink(outside, link); err != nil { t.Fatal(err) } if _, err := cap.ReadArtifact(context.Background(), ref, "leak"); err != ErrPathEscape { t.Fatalf("symlink: %v", err) } } func TestStaleFencingRejected(t *testing.T) { cap := NewCapability(t.TempDir(), nil) old := issued(t, cap, "ws1", 3) _ = issued(t, cap, "ws1", 3) ctx := context.Background() if err := cap.WriteArtifact(ctx, old, "output.md", []byte("stale")); err != ErrStaleFencing { t.Fatalf("old writer: %v", err) } fresh := issued(t, cap, "ws1", 3) if err := cap.WriteArtifact(ctx, fresh, "output.md", []byte("ok")); err != nil { t.Fatal(err) } } func TestUnknownSchemaRejected(t *testing.T) { cap := NewCapability(t.TempDir(), nil) _, err := cap.Issue(WorkspaceRef{ID: "ws1", SchemaVersion: 99}) if err != ErrUnknownSchema { t.Fatalf("got %v", err) } } func TestNoFileIOInsideUnitOfWork(t *testing.T) { cap := NewCapability(t.TempDir(), nil) ref := issued(t, cap, "ws1", 1) ctx := uow.WithScope(context.Background(), stubScope{}) if err := cap.WriteArtifact(ctx, ref, "output.md", []byte("x")); err != ErrIOInTransaction { t.Fatalf("got %v", err) } } func TestCommitProjectionCompleteMarker(t *testing.T) { cap := NewCapability(t.TempDir(), nil) ref := issued(t, cap, "ws1", 1) ctx := context.Background() if err := cap.WriteArtifact(ctx, ref, "output.md", []byte("hello")); err != nil { t.Fatal(err) } if err := cap.CommitProjection(ctx, ref, "output.md", ""); err != nil { t.Fatal(err) } got, err := cap.ReadArtifact(ctx, ref, "output.md.complete") if err != nil { t.Fatal(err) } if !containsComplete(got) { t.Fatalf("marker %q", got) } } func containsComplete(b []byte) bool { return string(b) != "" && (string(b)[len(b)-1] == '\n') } type stubScope struct{} func (stubScope) Context() context.Context { return context.Background() }