Skip to content

Complete Content workspace switching and provisioning#2206

Merged
3mdistal merged 71 commits into
mainfrom
codex/content-global-workspace-model
Jul 20, 2026
Merged

Complete Content workspace switching and provisioning#2206
3mdistal merged 71 commits into
mainfrom
codex/content-global-workspace-model

Conversation

@3mdistal

@3mdistal 3mdistal commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • replace Content's split local/database product modes with SQL-backed Content spaces, one canonical Files database per space, and source adapters for local folders
  • render Personal, organization, named, and source-backed workspaces together as independently expandable roots; opening a root selects that Content space and its Files database without switching the framework organization context
  • provision and backfill personal and organization Files through the trusted idempotent server path, including ordinary organization members, while preserving document IDs, bodies, ownership, and visibility
  • scope writers and database creation to the selected Content space and restore optimistic workspace-plus page creation, sidebar insertion, page/database choice, selected-page emphasis, hover actions, and destructive page actions
  • expose read-only, filterable Kind, Parent, and Source system properties on every canonical Files database; derive their values from authorized records and keep database-row filtering in the effective saved/personal client view
  • preserve custom Files views and user-created Source columns; adopt only the exact legacy generated Source signature and never overwrite stored legacy values during projection
  • make arbitrary named private workspaces a first-class Add workspace choice alongside Local folder
  • route folder selection only through the trusted Desktop/browser bridge marker; unsupported hosts fail closed instead of invoking an unsafe picker or crashing the host
  • fence cached pre-migration clients at an explicit compatibility version so version-aware stale clients reload instead of mixing legacy chrome with the migrated backend

Production incident coverage

The July 17 ordinary-member report exposed two independent defects in the post-#2189 production path:

  1. Organization Files could serialize private document title/property metadata owned by another organization member while the direct document read correctly failed closed. This is sensitive metadata exposure inside the organization; there is no evidence that unauthorized document bodies were returned.
  2. New page uses create-document, where an ordinary organization member was rejected before insert by the editor-only Content-space gate. This is separate from the hosted create-content-database transaction defect tracked in Fix hosted organization-space database creation #2217.

This PR covers both symptoms and includes the hosted organization transaction correction so the workspace rollout has one acceptance boundary.

Compatibility rollout note

A tab whose JavaScript predates the compatibility mechanism itself cannot be redirected by code it does not contain. On the first boundary deployment, that truly pre-boundary tab fails closed with HTTP 409 and needs one manual reload. Once the boundary is present, future version-aware stale clients reload automatically.

Verification

  • post-merge focused verification: core compatibility/transport 7 files / 204 tests, Content workspace/Files 17 files / 153 tests, and the full parity directory 10 files / 27 tests passed
  • Content and core TypeScript, git diff checks, SSR cache-shell, client-barrel, ownable-query scoping, and localization guards passed on the merged tree
  • merged exact origin/main tip 56faca895ff7f7a18e8716cd77292a7d6d9b9afd; final branch head is d830d523a815f91127635c7a535acd7fe88d6279
  • fresh independent P1/P2 review is green after fixing one-time seeding, system-field mutation/reorder guards, Source adoption, access-safe derived values, post-pagination filtering, OR/personal-view semantics, and manual/effective pagination separation
  • exact Netlify deploy 6a5c2add50a7290008659999 is ready for commit d830d523a815f91127635c7a535acd7fe88d6279; /, the known Files route, and sign-in return HTTP 200
  • pre-merge exact-preview UI QA on a9232b2bedf97dd26bd394f477030b755de0643d confirmed:
    • Personal and named workspace roots remain visible together and expand/collapse independently
    • workspace selection opens the correct Files database and Personal selection persists across reload without a framework organization switcher
    • named workspace and Local folder choices appear under Add workspace
    • Favorites/workspace disclosure controls and their page icons share the same hierarchy geometry
    • Files exposes Kind, Parent, Source, and Content; the untouched default view hides database rows
    • workspace-plus creation adds the page to the correct sidebar root, opens the page/database chooser, survives reload, resolves selected-page emphasis, and deletes cleanly through the restored red Delete action
    • Local folder fails closed with setup guidance in Codex/browser hosts that do not expose the trusted bridge
  • all disposable preview pages created during final QA were deleted
  • the earlier branch-wide test attempt still has an environment-only harness gap: several delete-document.test.ts cases expect a local server on port 3000 and fail with ECONNREFUSED when that server is absent; this is not counted as product-code proof

Remaining platform boundary

The Agent Native Desktop app injects the trusted local-folder bridge. The Codex in-app browser and ordinary browsers currently fail closed because they do not expose that bridge; this PR prevents the repeat-attach host crash but does not claim folder-picker parity in those hosts.

Rollout gate

  • merge exact origin/main tip 56faca895ff7f7a18e8716cd77292a7d6d9b9afd and resolve the five-file conflict without dropping either migration line
  • CI and a post-conflict deploy preview are green
  • ordinary-member organization acceptance: only authorized org/public Files visible, private absent, every visible row opens, and page/database creation persists in the selected org space
  • Personal → named workspace → Personal, independent toggles, Files navigation, optimistic page creation, reload persistence, selected-page emphasis, and destructive cleanup on the exact preview
  • obtain fresh review on the final post-conflict head; the existing approval predates the latest commits
  • merge and production deploy with auto-merge remaining unarmed
  • obtain fresh authorization immediately before any disposable production write
  • independent Safari production QA before declaring the rollout healthy

Favorites database acceptance

  • Favorites is a private per-user system database, not a document boolean or a read-only overlay. A favorited page retains its canonical workspace Files membership and gains a second membership in Favorites.
  • Clicking Favorites opens the normal database editor with editable properties, saved views, filters, sorts, grouping, and the usual view controls. Legacy favorite flags migrate idempotently into membership.
  • Favorites visibility is authorized across every current Content organization before count and pagination; inaccessible rows and potentially sensitive titles are excluded.
  • Single-row, preview, bulk, import, local-folder, and share-copy paths all use Favorites membership. Removing a row says Remove from Favorites and removes only that membership; the underlying page, body, ownership, visibility, and Files membership remain intact.

Focused local proof on head 9f34284f8: 107 relevant tests, Content typecheck, formatting and diff checks, and the production build passed. The build retains 77 pre-existing non-fatal doctor findings outside this slice.

Additional rollout gate:

  • Exact deploy-preview QA: open Favorites as a full database, add and persist a custom property and saved filter, favorite a page from another authorized workspace, reload, remove it through row/preview/bulk membership controls, and confirm the page still opens from its original Files database.

@netlify

This comment has been minimized.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Here's a visual recap of what changed:

Visual recap

Open the full interactive recap

Large diff — this recap is a summarized view (top files + schema/API deltas).

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

builder-io-integration[bot]

This comment was marked as outdated.

@3mdistal

Copy link
Copy Markdown
Contributor Author

Independent human QA completed against the current branch at localhost:9205:

  • fresh disposable account creation succeeded
  • the earliest post-submit state already showed Personal and Files; “No workspaces yet” never appeared
  • automatic provisioning completed without refresh or retry
  • reload preserved the same Files database route and sidebar state
  • browser console had no warnings or errors during the completed flow

The Workspaces/Files UI passed visually. The tester also noted pre-existing clipping in the unrelated right assistant rail at the captured viewport; this PR does not modify that rail or its layout, so it is non-blocking for this fix.

@3mdistal
3mdistal requested a review from steve8708 July 17, 2026 14:59
@3mdistal
3mdistal marked this pull request as draft July 17, 2026 15:01
@netlify

This comment has been minimized.

@3mdistal

3mdistal commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Verified the Favorites database flow on exact Content deploy preview 6a5d4b3843b62c00082f0b12 at head 0f4557e9b8694de3be8e454b859f2ee4333cbc76, then repeated it on final deploy 6a5d4d1ea6bb420008fa71a6 at head c24897da1156e25a74f08e80af642944537f5132:

  • Opened ttypefa in the named non-Personal workspace.
  • Added it to Favorites, then opened the full Favorites database immediately without reloading.
  • Favorites showed both Page 2 and ttypefa (Count 2 pages), covering the stale database-cache regression.
  • Confirmed the row action uses the localized Remove from favorites catalog entry.
  • Removed ttypefa through that row action; the Favorites database returned to Count 1 page while ttypefa remained in its workspace Files.
  • Reloaded Favorites and confirmed Page 2 persisted, ttypefa remained absent from Favorites, and the workspace file remained intact.

Local verification:

  • focused cache + database suite: 41 tests passed
  • focused cache + database UI suite: 72 tests passed
  • i18n catalog guard passed
  • typecheck passed
  • production build passed (with the existing 77 non-fatal doctor findings)

No merge or auto-merge was requested or enabled.

@3mdistal
3mdistal force-pushed the codex/content-global-workspace-model branch from 55d0bdd to ac1124b Compare July 19, 2026 22:48
@netlify

This comment has been minimized.

@3mdistal
3mdistal force-pushed the codex/content-global-workspace-model branch 2 times, most recently from c791ba9 to b5026b9 Compare July 19, 2026 23:05
@3mdistal

Copy link
Copy Markdown
Contributor Author

Verified the final Content deploy preview (6a5d584d600b0b0008ba0d51) at head b5026b9f3b3ce5197187c40e2ead7fa17f619548 against the latest sidebar feedback:

  • Workspaces remain open together; Page 1's tree starts at roots and expands only on explicit disclosure.
  • Page 1's expansion survives a full reload through the per-account server setting.
  • Parent and leaf rows reserve the same icon slot; parents expose the disclosure affordance from that slot, while row More/Add actions remain available.
  • Reproduced the title rollback with the earlier preview, then fixed the optimistic-cache watermark race. On the final preview, immediately renaming an Untitled page and choosing an icon preserved both QA final rename icon b5026b9f3 and 🧩 after a full reload.
  • Deleted the disposable QA page after verification.

Focused tests: 49 passed. Local Node 24 typecheck passed. CI lint, typecheck, Content DB tests, Content parity, build, security, and the Content Netlify preview are green; the repository-wide Fast tests and Scaffold E2E jobs are still running.

Auto-merge remains off; the PR is still open and review-blocked.

@3mdistal
3mdistal force-pushed the codex/content-global-workspace-model branch from b5026b9 to 17d12da Compare July 20, 2026 00:16
@netlify

This comment has been minimized.

@3mdistal

Copy link
Copy Markdown
Contributor Author

QA update for 17d12da16 on Content deploy preview 6a5d68e3acc69800087ca2cf:

  • Top-level Files now renders Workspaces / Personal with folder icons.
  • Clicking Workspaces opens the global Workspaces database.
  • The workspace chooser stayed open across a stationary 1.2s check, and all workspace entries use folder icons.
  • After clicking the nested Page 2 sidebar row and moving the pointer away, focus returned to BODY; the chevron and action slab both returned to opacity 0, while the page marker returned to opacity 1.
  • Focused tests: 48 passed. Typecheck and production build passed.

PR remains open and auto-merge remains disabled.

@3mdistal
3mdistal force-pushed the codex/content-global-workspace-model branch 2 times, most recently from aa3972d to 6aa9e81 Compare July 20, 2026 00:29
@netlify

This comment has been minimized.

1 similar comment
@netlify

This comment has been minimized.

@3mdistal
3mdistal force-pushed the codex/content-global-workspace-model branch from 6aa9e81 to 9bc544a Compare July 20, 2026 00:33
@3mdistal

Copy link
Copy Markdown
Contributor Author

Final hover-boundary follow-up at 9bc544a14:

  • Scoped the workspace hover/focus group to the workspace header row instead of the expanded workspace subtree.
  • Focused layout tests: 15 passed. Content typecheck and the full local production build passed.
  • Local UI QA: with a child page focused, Personal showed folder opacity 1 / chevron opacity 0; with the Personal header focused, it showed folder opacity 0 / chevron opacity 1.
  • Netlify preview remains an infrastructure gap: deploys 6a5d6b4736c4e40007beba64, 6a5d6bddeb061500085fb960, and 6a5d6cef009480000800adaf all ended error with empty public summaries, so I did not claim deploy-preview verification for this final fix.

PR remains open and auto-merge remains disabled.

@3mdistal

Copy link
Copy Markdown
Contributor Author

Folded the final Workspaces feedback from clip IG7136ja1fqH into head d24de08493537d53150ca62f3f109e204177fe42:

  • Creating a workspace from the global Workspaces database now stays on that database instead of navigating into the new Files database.
  • The table create affordance now says “New workspace” for the Workspaces system database.
  • Renaming a workspace through its Files database optimistically updates both the workspace sidebar and its global Workspaces row, then reconciles both caches with the server result.

Evidence:

  • Focused Vitest: 2 files / 26 tests passed.
  • tsc --noEmit passed.
  • Full local production build passed.
  • Completed CI gates currently green include Content DB tests, Content parity, typecheck, lint/format, security guards, SSR smoke, static template QA, core integration, and Plan E2E.

Preview boundary: Netlify deploy 6a5d715864c48300080d82d5 is for this exact commit but resolved to state: error with summary.status: unavailable and no messages, so this head does not yet have a valid preview artifact for real UI QA. I have not merged the PR and auto-merge remains off.

@netlify

This comment has been minimized.

@3mdistal

Copy link
Copy Markdown
Contributor Author

Final workspace-deletion verification on exact head 29d64def8f41fe0af289de707bdd2b27cecf43f7:

  • Netlify Content deploy 6a5d7f821abf5800080dc196 is ready and bound to this head.
  • Replayed the reported row-menu path in the signed-in deploy preview: a user-created workspace with a nested page deleted without an error toast, remained absent after reload, and unrelated Personal/organization workspace content remained.
  • Personal and organization-backed workspace menus expose only Open page; Delete workspace and Duplicate are absent.
  • Workspaces rows use folder fallback icons.
  • Focused workspace-deletion tests, Content DB tests, parity (83 tests), typecheck, build, and the full Content fast suite (128 files; 1,608 passed; 3 expected failures) pass.
  • All required GitHub checks are green, approval is present, auto-merge is not armed, and there are no unresolved review threads.

The destructive path now uses the dedicated owner-only delete-content-space action and preserves the generic document guard for system catalog rows.

@3mdistal
3mdistal merged commit c913280 into main Jul 20, 2026
91 checks passed
@3mdistal
3mdistal deleted the codex/content-global-workspace-model branch July 20, 2026 02:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants