Skip to content
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a451533
feat(vfs): chat-scoped outputs/ namespace for one-off generated files
Jul 1, 2026
f132892
feat(chat): duplicate a chat as a self-contained copy
Jul 2, 2026
8f99fba
test(vfs): track generalized outputs/ grep message; biome formatting
Jul 2, 2026
c52b06e
feat(chat): fork a chat from any message, replacing whole-chat duplicate
Jul 3, 2026
834dc2e
fix(chat): stop phantom-stream reconnect wedge after a failed send
Jul 3, 2026
bcb3c2b
feat(scout): add scout agent
Sg312 Jul 3, 2026
bffdeec
fix(contracts): update contracts to include scout agent
Sg312 Jul 3, 2026
3e43b48
feat(copilot): search agent (research+scout merge) + read-only table/…
Sg312 Jul 3, 2026
e4200af
feat(copilot): run_code compute-only handler; docs lint fix
Sg312 Jul 3, 2026
f104cff
fix(copilot): failed tool calls must surface their error in terminal …
Sg312 Jul 3, 2026
d10be73
feat(chat): duplicate a chat via whole-chat fork mode
j15z Jul 3, 2026
e4f59b3
fix(chat): delete dead file rows when a fork blob copy fails
j15z Jul 3, 2026
dff00cb
Merge branch 'dev' into feat/chat-scoped-outputs-and-duplicate
j15z Jul 3, 2026
6e48db6
chore(db): biome-format drizzle artifacts for migration 0254
j15z Jul 3, 2026
9d8756c
fix(files): require chat ownership for output file access; duplicate …
j15z Jul 3, 2026
4e82a25
chore(api): bump route-count baseline for the chat outputs route
j15z Jul 4, 2026
e43fe9c
fix(copilot): harden chat-scoped outputs (write-once, resolution, forks)
j15z Jul 4, 2026
573a425
chore(db): biome-format drizzle artifacts for migration 0255
j15z Jul 4, 2026
4abf5d8
fix(db): build the 0255 output-name index CONCURRENTLY
j15z Jul 4, 2026
18a2beb
fix(copilot): babysit-pr iteration 1 — review-verified fixes + ISSUES.md
j15z Jul 5, 2026
ab643ae
fix(copilot): babysit-pr iteration 2 — two self-review findings
j15z Jul 5, 2026
1ff7ba6
fix(copilot): materialize import resolves outputs/ like save (Bugbot)
j15z Jul 5, 2026
fe81038
fix(contracts): sync the twin resource schema families (drift audit)
j15z Jul 6, 2026
8afecd5
test(contracts): pin mothership↔copilot resource schema parity
j15z Jul 6, 2026
f1ed5c7
docs(contracts): scope the resource-enum parity claim to remove/reorder
j15z Jul 6, 2026
86369dd
fix(copilot): babysit round 5 — four Bugbot findings from auto-push r…
j15z Jul 6, 2026
4a2333a
fix(copilot): complete the round-5 fixes (Bugbot follow-ons)
j15z Jul 6, 2026
63dd122
test(copilot): backfill regression tests for the two untested round f…
j15z Jul 6, 2026
e2300e4
docs(issues): record the release triage decision — all 11 findings sh…
j15z Jul 6, 2026
8a7ea85
fix(copilot): output rows visible to every read path; probe ambiguous…
j15z Jul 6, 2026
116c429
docs(issues): fold the max-effort review results into the triage — 5 …
j15z Jul 6, 2026
6029b98
fix(copilot): gate re-review corrections — revert unsound send-probe,…
j15z Jul 6, 2026
12a600b
docs(issues): 2026-07-05 audit — all 40 tracked items re-verified aga…
j15z Jul 6, 2026
812d2a8
docs(testing): manual test plan for chat-scoped outputs + fork/duplicate
j15z Jul 6, 2026
66db2e3
docs(issues): R8 — flag-on create_file schema contradicts the sim out…
j15z Jul 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions apps/docs/components/workflow-preview/format-references.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ export function formatReferences(text: string): ReactNode[] {
const isReference =
(part.startsWith('<') && part.endsWith('>')) || (part.startsWith('{{') && part.endsWith('}}'))
return isReference ? (
// biome-ignore lint/suspicious/noArrayIndexKey: static, never reordered
<span key={index} className='text-[var(--brand-secondary)]'>
{part}
</span>
) : (
// biome-ignore lint/suspicious/noArrayIndexKey: static, never reordered
<span key={index}>{part}</span>
)
})
Expand Down
28 changes: 26 additions & 2 deletions apps/sim/app/api/files/authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ import { isUuid } from '@/executor/constants'

const logger = createLogger('FileAuthorization')

/**
* Contexts this key lookup resolves for workspace-membership authorization:
* `workspace` (durable UI files) and `output` (chat-scoped agent outputs). Both
* share the `workspace/<id>/...` key shape and are authorized by workspace
* membership, so a by-key match on either is safe to grant to any member.
*
* `mothership` chat uploads ALSO share the bucket/key shape but are deliberately
* left OUT: today they authorize via the Priority-2 object-metadata fallback, and
* moving them onto this Priority-1 DB path would change how uploads work — an
* unrelated change deferred to its own PR (see outputs-vfs-followups.md #2).
* Owner-scoped contexts that also live in `workspace_files` (`copilot`,
* `knowledge-base`, `workspace-logos`) are excluded too: they have stricter
* per-owner rules and must never be granted through workspace membership on a
* key collision.
*/
const WORKSPACE_FILE_LOOKUP_CONTEXTS: StorageContext[] = ['workspace', 'output']

/** Thrown by utility functions when file access is denied, so route handlers can return 404. */
export class FileAccessDeniedError extends Error {
constructor() {
Expand Down Expand Up @@ -54,8 +71,15 @@ async function lookupWorkspaceFileByKey(
): Promise<{ workspaceId: string; uploadedBy: string } | null> {
try {
const { includeDeleted = false } = options ?? {}
// Priority 1: Check new workspaceFiles table
const fileRecord = await getFileMetadataByKey(key, 'workspace', { includeDeleted })
// Priority 1: Check new workspaceFiles table. Look up by key across
// WORKSPACE_FILE_LOOKUP_CONTEXTS (`workspace` + `output`): both share the
// `workspace/<id>/...` key shape and authorize by workspace membership. Filtering
// to `workspace` alone made `output` files unservable (broken previews); scoping to
// this explicit set (rather than dropping the filter) keeps outputs servable while
// leaving upload (`mothership`) authorization and the owner-scoped contexts untouched.
const fileRecord = await getFileMetadataByKey(key, WORKSPACE_FILE_LOOKUP_CONTEXTS, {
includeDeleted,
})
Comment thread
cursor[bot] marked this conversation as resolved.

if (fileRecord) {
return {
Expand Down
14 changes: 8 additions & 6 deletions apps/sim/app/api/files/view/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ export const GET = withRouteHandler(
return NextResponse.json({ error: 'Not found' }, { status: 404 })
}

// Only workspace-scoped files are embeddable/viewable here. Other contexts (e.g. chat-scoped
// `mothership` uploads) are not durable workspace artifacts; now that the caller is known to have
// access, reject with a legible 422 so the embed fails cleanly and the file agent can self-correct.
if (record.context !== 'workspace') {
logger.warn('Rejected non-workspace file view', { id, context: record.context })
// Embeddable contexts: durable `workspace` files and chat-scoped `output` files
// (agent-generated one-offs the user previews inline before optionally saving to
// the workspace). Other contexts (e.g. `mothership` user uploads) are not embeddable
// here; now that the caller is known to have access, reject with a legible 422 so the
// embed fails cleanly and the file agent can self-correct.
if (record.context !== 'workspace' && record.context !== 'output') {
logger.warn('Rejected non-embeddable file view', { id, context: record.context })
return NextResponse.json(
{
error: `File ${id} has context "${record.context}" and is not embeddable. Only workspace files can be viewed via /api/files/view. Save it into the workspace and reference the workspace copy.`,
error: `File ${id} has context "${record.context}" and is not embeddable. Only workspace and output files can be viewed via /api/files/view. Save it into the workspace and reference the workspace copy.`,
},
{ status: 422 }
)
Expand Down
Loading
Loading