Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
56246d8
feat(dashboards): add table-backed dashboard resources behind rollout…
TheodoreSpeaks Sep 25, 2026
90bbd59
refactor(files): separate discovery from storage context
TheodoreSpeaks Sep 25, 2026
a6e0941
fix(charts): keep pie labels readable and separate neutral colors
TheodoreSpeaks Sep 25, 2026
f894b9e
feat(dashboards): compute percentages from row conditions
TheodoreSpeaks Sep 25, 2026
743b0e3
refactor(dashboards): store dashboards as workspace files
TheodoreSpeaks Sep 26, 2026
0dc3b9d
Merge origin/staging into codex/research-sim-dashboards
TheodoreSpeaks Sep 26, 2026
26a9dd2
fix(dashboards): address review findings on chart layout and precision
TheodoreSpeaks Sep 26, 2026
6c58c01
fix(charts): size grouped bar rows and keep the row highlight through…
TheodoreSpeaks Sep 26, 2026
3d630db
Merge remote-tracking branch 'origin/staging' into codex/research-sim…
TheodoreSpeaks Sep 26, 2026
af21484
fix(charts): keep authored tooltip arrays and drop the v2 chat mode o…
TheodoreSpeaks Sep 26, 2026
bf3243c
fix(charts): reserve the authored bar gap between grouped bars
TheodoreSpeaks Sep 26, 2026
4f1b0e0
fix(charts): format index-encoded pie tooltips and test dashboard ref…
TheodoreSpeaks Sep 26, 2026
d736526
Merge remote-tracking branch 'origin/staging' into codex/research-sim…
TheodoreSpeaks Sep 26, 2026
8e34901
fix(charts): format bar tooltip values with each series' own value axis
TheodoreSpeaks Sep 26, 2026
bb59bdf
test(dashboards): drop mock-call and rendered-text assertions
TheodoreSpeaks Sep 26, 2026
dd4b207
Merge remote-tracking branch 'origin/staging' into codex/research-sim…
TheodoreSpeaks Sep 26, 2026
0958aab
test(dashboards): drop redundant mock resets and default environment …
TheodoreSpeaks Sep 26, 2026
a3e287e
refactor(dashboards): move authoring guidance to Mothership like Sim …
TheodoreSpeaks Sep 27, 2026
c2207cf
Merge remote-tracking branch 'origin/staging' into codex/research-sim…
TheodoreSpeaks Sep 27, 2026
54dfd1b
refactor(dashboards): give DashboardFeatureGate a props interface
TheodoreSpeaks Sep 27, 2026
4cc80af
feat(dashboards): report dashboard parse errors on file writes
TheodoreSpeaks Sep 27, 2026
5d0e7e4
fix(dashboards): split diagnostics, switch panel query modes, return …
TheodoreSpeaks Sep 27, 2026
68e8448
fix(dashboards): drop inherited ordering on query-mode switches and c…
TheodoreSpeaks Sep 27, 2026
470b450
feat(playground): org-level project view prototype
TheodoreSpeaks Sep 29, 2026
301c682
feat(playground): Supabase-style full view, settings in the sidebar, …
TheodoreSpeaks Sep 29, 2026
8548821
feat(playground): wire the org project view to real workspaces
mzxchandra Sep 30, 2026
cb12e31
fix(playground): pick overlay packs by workflow names, thread project…
mzxchandra Sep 30, 2026
ad5a255
fix(playground): defer the handed-off first message, share the projec…
mzxchandra Sep 30, 2026
c76aa17
fix(playground): wait for the overlay pack before 404ing an issue
mzxchandra Sep 30, 2026
8db9094
feat(playground): mock projects beside real ones, Connectors as the o…
mzxchandra Sep 30, 2026
224d287
feat(playground): forked workspaces are one project with environments
mzxchandra Sep 30, 2026
ac1905c
feat(projects): shared lineage model, org-project-view flag, Environm…
mzxchandra Sep 30, 2026
2af068d
feat(playground): Environments tab manages the project's fork lineage…
mzxchandra Sep 30, 2026
794e8fe
feat(playground): Build opens the workspace routes, Issues per lineag…
mzxchandra Sep 30, 2026
5291156
feat(workspace): project Build sidebar and Workflows index page behin…
mzxchandra Sep 30, 2026
d921f6c
feat(playground): project rows with the workspace sidebar's ergonomic…
mzxchandra Sep 30, 2026
f51110a
feat(playground): org sidebar account footer, fork from any environment
mzxchandra Sep 30, 2026
d00e347
feat(playground): New chat is the product's org Home plus a project p…
mzxchandra Sep 30, 2026
bc5bf6e
feat(workspace): workflow location bar above the canvas in the Build …
mzxchandra Sep 30, 2026
9c398c1
feat(org): project view moves onto the organization surface behind or…
mzxchandra Sep 30, 2026
3dab93c
feat(workflows): describe container changes and build a canvas diff o…
mzxchandra Sep 30, 2026
d5a6030
feat(preview): paint comparison status on the read-only canvas
mzxchandra Sep 30, 2026
5438d26
feat(workflows): version diff view with a field-level change list
mzxchandra Sep 30, 2026
c4bb130
feat(deploy): compare deployment versions and the draft
mzxchandra Sep 30, 2026
02c29ab
feat(forks): preview one workflow's block-level changes before a sync
mzxchandra Sep 30, 2026
778636a
fix(workflows): harden the version diff after review
mzxchandra Sep 30, 2026
9b55e84
fix(workflows): scope the fork preview to one workflow and close revi…
mzxchandra Sep 30, 2026
babdccc
test(forks): use a neutral workflow name in preview fixtures
mzxchandra Sep 30, 2026
0ab7772
fix(forks): offer "View changes" only on workflows the sync changes
mzxchandra Sep 30, 2026
53d1b70
fix(workflows): bound the sync change check and tighten diff rendering
mzxchandra Sep 30, 2026
e84728d
fix(workflows): mask message text, count all block columns, reset sel…
mzxchandra Sep 30, 2026
3278348
fix(workflows): scope selection reset to picked versions and test out…
mzxchandra Sep 30, 2026
43bb39e
fix(workflows): only call a message change masked when the message ex…
mzxchandra Sep 30, 2026
5d319f5
test(workflows): use absolute imports in new tests
mzxchandra Sep 30, 2026
2672611
feat(org): promote and refresh between environments from the project'…
mzxchandra Sep 30, 2026
6a215b1
feat(org): every chat in one Chats section, marked with its projects;…
mzxchandra Sep 30, 2026
905a58f
feat(projects): a projects table every workspace belongs to, with bac…
mzxchandra Sep 30, 2026
c4c1d08
feat(projects): read projects from the projects API; environment labe…
mzxchandra Sep 30, 2026
da7d9a2
fix(chats): move only org members' workspace chats to the organization
mzxchandra Oct 1, 2026
6f42b47
fix(chats): keep moved workspace chats in agent mode
mzxchandra Oct 1, 2026
63d595e
feat(projects): name a project after its root workspace with a " - Pr…
mzxchandra Oct 1, 2026
b45a6ba
feat(projects): checkpoint project UI and environment settings redesign
mzxchandra Oct 2, 2026
fb86acf
feat(chat): show sub-agent activity and cited sources
mzxchandra Oct 3, 2026
574eb19
Merge origin/staging into feat/org-project-routes
TheodoreSpeaks Oct 12, 2026
82c3dc0
feat(org): project view reads Projects from the Project API
TheodoreSpeaks Oct 12, 2026
90086de
fix(projects): return a Project's environments in fork order
TheodoreSpeaks Oct 12, 2026
abd0d0e
Merge Marcus's feat/org-project-routes onto staging's Project model
TheodoreSpeaks Oct 12, 2026
1c9b78f
feat(org): project creation, pane polish, and smoother resource panel
TheodoreSpeaks Oct 13, 2026
25892eb
fix(org): drop the organization row from the project picker
TheodoreSpeaks Oct 13, 2026
a69c2ac
Merge origin/staging into feat/org-project-routes
TheodoreSpeaks Oct 13, 2026
3482f70
feat(org): use the changelog empty-state graphic in the project view
TheodoreSpeaks Oct 13, 2026
0c379a1
fix(org): tidy project sidebar rows, workflow status, and expand befo…
TheodoreSpeaks Oct 13, 2026
4850e67
fix(mothership): grant gated entitlements to organization Build chats
TheodoreSpeaks Oct 13, 2026
99bbd3e
feat(org): environments canvas, per-pair sync view, and settings rail
TheodoreSpeaks Oct 14, 2026
e2b84f4
feat(org): open each environment sync as a step-by-step pane tab
TheodoreSpeaks Oct 14, 2026
9fe2883
Merge remote-tracking branch 'origin/staging' into feat/org-project-r…
TheodoreSpeaks Oct 14, 2026
ab32934
feat(org): host the full workflow editor in the project pane
TheodoreSpeaks Oct 14, 2026
0b8ec7a
feat(org): open and close the project pane through a swell
TheodoreSpeaks Oct 15, 2026
c199254
feat(org): show a release-pipeline empty state for a project with one…
TheodoreSpeaks Oct 15, 2026
a6ae731
feat(org): keep the project header mounted across environments
TheodoreSpeaks Oct 15, 2026
88c65cb
feat(org): keyboard-driven new tab and block search in the project pane
TheodoreSpeaks Oct 15, 2026
be0aa6c
fix(org): highlight no New tab row until an arrow key picks one
TheodoreSpeaks Oct 15, 2026
d113498
feat(org): search a project's resources from the New tab, server-side
TheodoreSpeaks Oct 16, 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
64 changes: 64 additions & 0 deletions apps/sim/app/api/organizations/[id]/resources/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { searchOrganizationResourcesContract } from '@/lib/api/contracts/resource-search'
import { cursorRoute, cursorScopeKey } from '@/lib/api/cursor-binding'
import {
defineInternalJsonRoute,
internalOrchestrationErrorPolicy,
internalRateLimits,
internalSessionAuth,
} from '@/lib/api/server/routes'
import {
organizationResourceOperations,
searchOrganizationResources,
} from '@/lib/workspaces/application/search-organization-resources'
import { readSortedCursor, writeSortedCursor } from '@/app/api/v2/lib/response'

export const dynamic = 'force-dynamic'

/** Match position, then name: the one order this search pages in. */
const SEARCH_SORT = 'relevance'

/** Binds a cursor to the search it was minted for, so it cannot resume a different one. */
function cursorScope(
organizationId: string,
search: string | undefined,
types: readonly string[] | undefined,
workspaceIds: readonly string[] | undefined
) {
return cursorScopeKey(cursorRoute(searchOrganizationResourcesContract, { id: organizationId }), {
search,
types: types ? [...types].sort().join(',') : undefined,
workspaceIds: workspaceIds ? [...workspaceIds].sort().join(',') : undefined,
})
}

/** GET /api/organizations/[id]/resources/search — Resources named like `q` across the viewer's workspaces. */
export const GET = defineInternalJsonRoute({
contract: searchOrganizationResourcesContract,
auth: internalSessionAuth,
operation: organizationResourceOperations.search,
rateLimit: internalRateLimits.user({ bucketName: 'organization-resource-search' }),
errorPolicy: internalOrchestrationErrorPolicy,
mapInput: ({ params, query }) => ({
organizationId: params.id,
search: query.q,
types: query.types,
workspaceIds: query.workspaceIds,
limit: query.limit,
cursorKeys: readSortedCursor(
query.cursor,
SEARCH_SORT,
'asc',
cursorScope(params.id, query.q, query.types, query.workspaceIds)
),
}),
useCase: searchOrganizationResources,
present: ({ items, nextCursorKeys }, { input }) => ({
items,
nextCursor: writeSortedCursor(
nextCursorKeys,
SEARCH_SORT,
'asc',
cursorScope(input.organizationId, input.search, input.types, input.workspaceIds)
),
}),
})
13 changes: 13 additions & 0 deletions apps/sim/app/api/workspaces/[id]/fork/mapping/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
createForkSecretMappingContract,
getForkMappingContract,
updateForkMappingContract,
} from '@/lib/api/contracts/workspace-fork'
Expand All @@ -8,6 +9,7 @@ import {
internalSessionAuth,
} from '@/lib/api/server/routes'
import { internalForkErrorPolicy } from '@/ee/workspace-forking/api/route-policies'
import { createWorkspaceForkSecretMapping } from '@/ee/workspace-forking/application/create-secret-mapping'
import { getWorkspaceForkMappingDetails } from '@/ee/workspace-forking/application/mapping-details'
import { forkOperations } from '@/ee/workspace-forking/application/operations'
import { updateWorkspaceForkMappings } from '@/ee/workspace-forking/application/recovery-and-mappings'
Expand Down Expand Up @@ -38,3 +40,14 @@ export const PUT = defineInternalJsonRoute({
useCase: updateWorkspaceForkMappings,
present: (result) => ({ success: true as const, ...result }),
})

export const POST = defineInternalJsonRoute({
contract: createForkSecretMappingContract,
auth: internalSessionAuth,
operation: forkOperations.createSecretMapping,
rateLimit: internalRateLimits.none({ reason: 'Preserve existing internal fork request policy' }),
errorPolicy: internalForkErrorPolicy,
mapInput: ({ params, body }) => ({ workspaceId: params.id, ...body }),
useCase: createWorkspaceForkSecretMapping,
present: ({ name }) => ({ name }),
})
24 changes: 24 additions & 0 deletions apps/sim/app/api/workspaces/[id]/settings-navigation/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getWorkspaceSettingsNavigationContract } from '@/lib/api/contracts/workspace-settings'
import {
defineInternalJsonRoute,
internalOrchestrationErrorPolicy,
internalRateLimits,
internalSessionAuth,
} from '@/lib/api/server/routes'
import {
readWorkspaceSettingsNavigation,
readWorkspaceSettingsNavigationOperation,
} from '@/lib/settings/application/workspace-navigation'

export const GET = defineInternalJsonRoute({
contract: getWorkspaceSettingsNavigationContract,
auth: internalSessionAuth,
operation: readWorkspaceSettingsNavigationOperation,
rateLimit: internalRateLimits.none({
reason: 'Read-only settings navigation, matching existing settings-page admission',
}),
errorPolicy: internalOrchestrationErrorPolicy,
mapInput: ({ params }) => ({ workspaceId: params.id }),
useCase: readWorkspaceSettingsNavigation,
staticResponseHeaders: { 'Cache-Control': 'private, no-store' },
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client'

import { useRouter } from 'next/navigation'
import { organizationRoutes } from '@/lib/navigation/paths'
import { CreateWorkspaceModal } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/create-workspace-modal/create-workspace-modal'
import { useCreateProject } from '@/hooks/queries/projects'
import { useWorkspaceCreationPolicy } from '@/hooks/queries/workspace'

/** Whether the viewer may create a project in this organization, and why not. */
export function useProjectCreationPolicy(organizationId: string) {
const { data: policy } = useWorkspaceCreationPolicy()
const canCreate = Boolean(policy?.canCreate && policy.organizationId === organizationId)
return {
canCreate,
disabledReason: canCreate ? null : (policy?.reason ?? 'Project creation is unavailable.'),
}
}

interface CreateProjectModalProps {
organizationId: string
open: boolean
onOpenChange: (open: boolean) => void
}

/** Names a new project, creates it, and opens its pane on organization Home. */
export function CreateProjectModal({
organizationId,
open,
onOpenChange,
}: CreateProjectModalProps) {
const router = useRouter()
const { mutateAsync: createProject, isPending } = useCreateProject()
return (
<CreateWorkspaceModal
resource='project'
open={open}
onOpenChange={onOpenChange}
isCreating={isPending}
onConfirm={async (name) => {
const { initialEnvironment } = await createProject({ organizationId, name })
onOpenChange(false)
router.push(
`${organizationRoutes(organizationId).home}?project=${encodeURIComponent(initialEnvironment.id)}&pane=project`
)
}}
/>
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client'

import type { ReactNode } from 'react'
import {
chipVariants,
cn,
Expand Down Expand Up @@ -28,6 +29,8 @@ import {

interface ChatRowProps {
chat: OrganizationChat
/** Shown before the title, such as the projects the chat worked in. */
leading?: ReactNode
isCurrentRoute: boolean
isSelected: boolean
isMenuOpen: boolean
Expand All @@ -39,6 +42,7 @@ interface ChatRowProps {

function ChatRow({
chat,
leading,
isCurrentRoute,
isSelected,
isMenuOpen,
Expand Down Expand Up @@ -66,6 +70,7 @@ function ChatRow({
onContextMenu={(e) => onContextMenu(e, chat.id)}
onSelectChat={onSelectChat}
>
{leading}
<OverflowText label={chat.name} className='flex-1 text-[var(--text-body)]' />
<RowActions
open={isMenuOpen}
Expand Down Expand Up @@ -103,6 +108,8 @@ interface ChatsSectionProps {
isLoading: boolean
isCollapsed: boolean
pathname: string | null
/** Renders before each chat's title; the org project view shows the chat's projects. */
leadingFor?: (chat: OrganizationChat) => ReactNode
}

export function ChatsSection({
Expand All @@ -111,6 +118,7 @@ export function ChatsSection({
isLoading,
isCollapsed,
pathname,
leadingFor,
}: ChatsSectionProps) {
const actions = useOrganizationChatActions({ organizationId, chats })
const { menu, hover, rename, selectedChat, selectedChats, menuOpenChatId } = actions
Expand Down Expand Up @@ -140,7 +148,7 @@ export function ChatsSection({
<CollapsedChatFlyoutItem
key={chat.id}
chat={chat}
isCurrentRoute={pathname === chat.href}
isCurrentRoute={pathname === chat.href.split('?')[0]}
isSelected={selectedChats.size > 1 && selectedChats.has(chat.id)}
onSelectChat={actions.handleChatClick}
isMenuOpen={menuOpenChatId === chat.id}
Expand Down Expand Up @@ -184,7 +192,8 @@ export function ChatsSection({
<ChatRow
key={chat.id}
chat={chat}
isCurrentRoute={pathname === chat.href}
leading={leadingFor?.(chat)}
isCurrentRoute={pathname === chat.href.split('?')[0]}
isSelected={selectedChats.size > 1 && selectedChats.has(chat.id)}
isMenuOpen={menuOpenChatId === chat.id}
onSelectChat={actions.handleChatClick}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { ChatsSection } from './chats-section'
export { OrganizationFooter } from './organization-footer'
export { OrganizationHeader } from './organization-header'
export { ProjectsSection } from './projects-section'
export { WorkspacesSection } from './workspaces-section'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ProjectsSection } from './projects-section'
Loading