Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
224 commits
Select commit Hold shift + click to select a range
3054415
feat: add workspace permission controls and live access recovery
appflowy Oct 12, 2026
b485521
fix: keep the last space creation capability while revalidating
appflowy Oct 13, 2026
ade261f
fix: keep sibling tabs signed in when a shared token was already rotated
appflowy Oct 13, 2026
a5d636f
fix: dispatch permission hints that arrive before the user resolves
appflowy Oct 13, 2026
60e96ec
fix: release definitively rejected space drafts and make saved reques…
appflowy Oct 13, 2026
01ed3a2
fix: drop app view and catalog cache rows keyed by the bare account id
appflowy Oct 13, 2026
e71537f
fix: read each space permission once per row and keep old servers' ad…
appflowy Oct 13, 2026
347b65f
fix: gate Duplicate and Move by the destination's page-creation autho…
appflowy Oct 13, 2026
8ea2860
refactor: read override capability and roster together
appflowy Oct 13, 2026
94759eb
fix: offer only writable New Page destinations and show why creation …
appflowy Oct 13, 2026
c368d24
fix: recheck Manage Space in the background after permission changes
appflowy Oct 13, 2026
6e7b259
fix: release workspace creation requests after definitive failures
appflowy Oct 13, 2026
f3943e1
fix: keep workspace creation access stable while it is rechecked
appflowy Oct 13, 2026
7856bb5
fix: report a cancelled workspace import as a cancel
appflowy Oct 13, 2026
8ff284d
fix: remove dead ends and duplicate retries from the workspace importer
appflowy Oct 13, 2026
2a7ba70
feat: redesign workspace creation entry points
appflowy Oct 13, 2026
d991bac
fix(search): fence search and mentions only on real access changes
appflowy Oct 13, 2026
ec8bea5
test: cover the Manage Data workspace import gate
appflowy Oct 13, 2026
10f5aa1
fix(search): keep results through refreshes and finish Ask AI chats
appflowy Oct 13, 2026
710041d
fix(mention): reuse suggestions per access scope and finish created p…
appflowy Oct 13, 2026
9ac237a
feat: show who can add pages as an access-style row
appflowy Oct 13, 2026
0dd311d
feat: choose member access from an access menu in Manage Space
appflowy Oct 13, 2026
211570c
test: cover UUID member paths on servers with per-person access
appflowy Oct 13, 2026
24fa5ca
test: check space access copy against the shared vocabulary
appflowy Oct 13, 2026
70d651e
fix: confirm exact space creation policy and translate transport errors
appflowy Oct 13, 2026
204fd55
fix: restore immediate edits for admitted objects and keep queued upl…
appflowy Oct 13, 2026
f36884a
fix: let calendar transcription respect space creation and keep the m…
appflowy Oct 13, 2026
b017c63
docs: describe legacy-server space creation and destination checks
appflowy Oct 13, 2026
56fc844
feat: redesign Permissions settings and move group access to the grou…
appflowy Oct 13, 2026
d93f1ae
feat: open People > Groups from Permissions and shorten the menu entry
appflowy Oct 13, 2026
0c72325
fix: grey out the disabled Create a new space link
appflowy Oct 13, 2026
a0240bb
fix: make the paused-edits notice actionable, dismissible and quiet w…
appflowy Oct 13, 2026
f194acb
fix: keep the last confirmed space-creation answer on screen while it…
appflowy Oct 13, 2026
92d6d38
fix: remove the synced copy of a page when read access is revoked
appflowy Oct 13, 2026
d9792e8
fix: keep saved-request bookkeeping from failing a finished action
appflowy Oct 13, 2026
d388da7
fix: translate the Import workspace label on the creation surfaces
appflowy Oct 13, 2026
85dbc4b
fix: label picker results and keep stacked policy cards compact
appflowy Oct 13, 2026
7a5dcf8
fix: remove the signed-out account's synced copies from this device
appflowy Oct 13, 2026
2c583d0
fix: translate the workspace switch error in the switcher
appflowy Oct 13, 2026
16bab52
test: cover raw group names and the access menu's accessible name
appflowy Oct 13, 2026
c82fa85
test: expect a socket read revocation to remove only the synced copy
appflowy Oct 13, 2026
0721378
fix: never let sign-out cleanup throw out of invalidToken
appflowy Oct 13, 2026
911b260
fix: announce only the paused-edits message in the live region
appflowy Oct 13, 2026
4fa42d5
fix: skip re-checking quarantined objects on every focus
appflowy Oct 13, 2026
9c0495c
fix: keep a checked-again space request saved when its resend is refused
appflowy Oct 13, 2026
60484b4
fix: give access-to-all-spaces levels their own translated labels
appflowy Oct 13, 2026
c4dc893
fix: keep a replayed workspace request after sign-in or proxy rejections
appflowy Oct 13, 2026
7830e00
fix: render the workspace creation check without a block inside a par…
appflowy Oct 13, 2026
d55728a
fix: keep the access-to-all-spaces menu labelled by an existing element
appflowy Oct 13, 2026
da732ba
fix: keep the sidebar Resume dialog open until the user closes it
appflowy Oct 13, 2026
e710684
fix: show the space creator note as text instead of a hover-only tooltip
appflowy Oct 13, 2026
42752d5
fix: name an invitation without a workspace name in words, not by its ID
appflowy Oct 13, 2026
f095a30
fix: let New Page forget a selected space that is no longer listed
appflowy Oct 13, 2026
3adba79
fix: keep looking for an imported workspace until the empty account p…
appflowy Oct 13, 2026
de3782b
fix: report a failed space settings save after a permission change
appflowy Oct 13, 2026
57b98a8
fix(mention): discard parallel suggestions on a row-only RetryLater
appflowy Oct 13, 2026
361b9a6
fix: explain a workspace creation denial on the import landing page
appflowy Oct 13, 2026
84521c4
fix: follow the import page's redirect only to a page on this site
appflowy Oct 13, 2026
b3aba01
fix(mention): keep shown suggestions when their background re-run fai…
appflowy Oct 13, 2026
bcf7258
fix: treat a Move or Duplicate destination that could not be checked …
appflowy Oct 13, 2026
13f7cd0
test: cover the legacy-server import path end to end and drop the unu…
appflowy Oct 13, 2026
d3c631d
docs: describe how Duplicate Space recovers from a failed creation check
appflowy Oct 13, 2026
d014d2f
fix: keep server text out of Manage Space toasts
appflowy Oct 13, 2026
2678a50
fix(pages): report a refused page creation once, as a denial
appflowy Oct 13, 2026
cc19fc9
docs: describe the revocation probe as deleting the synced copy
appflowy Oct 13, 2026
38dd493
fix: refresh group access to all spaces live in People > Groups
appflowy Oct 13, 2026
a6aa443
fix: stop showing the saving notice for pages released long ago
appflowy Oct 13, 2026
0a04812
fix(search): stop the AI summary spinner after a failed revalidation
appflowy Oct 13, 2026
9ddc703
test: pin that the space creator picker skips current selections
appflowy Oct 13, 2026
af5bd1b
fix: explain and retry a failed Manage Space access check
appflowy Oct 13, 2026
265136a
fix: keep the session when a public-form token refresh fails transiently
appflowy Oct 13, 2026
a77edcd
test: cover the confirmed access merge and withdrawn add rights
appflowy Oct 13, 2026
0d7459a
fix(search): read recent pages from the endpoint, not the shared loader
appflowy Oct 13, 2026
5e979bc
fix: keep local copies on involuntary sign-out; remove them only on r…
appflowy Oct 13, 2026
1bf01ab
fix: use one set of access level names in Space settings
appflowy Oct 13, 2026
82f425b
fix: keep the copies that unsent edits depend on when removing local …
appflowy Oct 13, 2026
cb7652c
fix(search): retry reads lost to a dropped connection after reconnecting
appflowy Oct 13, 2026
8ac54c5
style(mention): format the created-page insertion check
appflowy Oct 13, 2026
f1f421f
docs: describe current Search and mention scope behaviour
appflowy Oct 13, 2026
1c5174f
fix: keep member role labels inside their column
appflowy Oct 13, 2026
5c006ca
Merge branch 'oodrive-fix/web-settings' into codex/oodrive-permission…
appflowy Oct 13, 2026
1e01446
Merge branch 'oodrive-fix/web-space' into codex/oodrive-permissions-f…
appflowy Oct 13, 2026
088ace8
Merge branch 'oodrive-fix/web-create' into codex/oodrive-permissions-…
appflowy Oct 13, 2026
bfb3c55
Merge branch 'oodrive-fix/web-workspace' into codex/oodrive-permissio…
appflowy Oct 13, 2026
bf885d5
Merge branch 'oodrive-fix/web-search' into codex/oodrive-permissions-…
appflowy Oct 13, 2026
5abded0
fix: stop other tabs from re-uploading discarded paused edits
appflowy Oct 13, 2026
5354a2b
fix: remove a revoked database's row copies along with the database
appflowy Oct 13, 2026
449d64a
docs: describe confirming the exact space creation policy
appflowy Oct 13, 2026
20b2a73
Merge branch 'oodrive-fix/web-sync' into codex/oodrive-permissions-fixes
appflowy Oct 13, 2026
80f73da
test: accept French-only plural categories in the permission translat…
appflowy Oct 13, 2026
a97992c
Merge branch 'oodrive-fix/web-compat' into codex/oodrive-permissions-…
appflowy Oct 13, 2026
91dc4c5
fix: name who can add pages to a space by who its members are
appflowy Oct 14, 2026
fcb575f
fix: explain an unexpected first page of a recovered space in plain w…
appflowy Oct 14, 2026
535782e
fix: ask for the empty-account workspace answer explicitly
appflowy Oct 14, 2026
3fde09a
fix: translate the workspace switch error on mobile
appflowy Oct 14, 2026
8b7145f
fix: let keyboard users reach a settings section's explanation
appflowy Oct 14, 2026
2975a49
fix: send the space member level when adding to a non-Custom space
appflowy Oct 14, 2026
1ae088e
fix: tell a refused space creation check apart from one that could no…
appflowy Oct 14, 2026
897d62d
fix: keep a known space creation answer on screen while it is rechecked
appflowy Oct 14, 2026
0eaa31d
feat: confirm before fewer people can create spaces
appflowy Oct 14, 2026
b9f075e
feat: explain in your own Manage Space access menu where more access …
appflowy Oct 14, 2026
be03ddb
fix: keep an open page modal on screen while its access is rechecked
appflowy Oct 14, 2026
93b1bfa
test: pin that the share menu keeps its people list while access is r…
appflowy Oct 14, 2026
92be579
docs: describe member add levels, the own access explanation, allow_e…
appflowy Oct 14, 2026
1755db4
fix: make Manage Space's General tab fully usable with a keyboard
appflowy Oct 14, 2026
5ac2e03
style: format the new workspace switch and space creation notice tests
appflowy Oct 14, 2026
fb0bd00
fix: keep keyboard users in place in the Permissions panel
appflowy Oct 14, 2026
2ff9ff9
fix: give focus back to the space icon after its picker closes
appflowy Oct 14, 2026
2e95661
fix: return to the space type card after its confirmation is cancelled
appflowy Oct 14, 2026
c9e5da2
fix: show keyboard focus on every button in the space settings dialog
appflowy Oct 14, 2026
fde884f
docs: describe workspace creation on older servers and the page setti…
appflowy Oct 14, 2026
b3323c1
fix: name the space page share when it replaces what a group gives
appflowy Oct 14, 2026
5687eea
fix: always send a level when adding an ordinary space member
appflowy Oct 14, 2026
b590561
fix: let Escape close only the open menu or icon picker in space dialogs
appflowy Oct 14, 2026
694ff11
fix: have your own access explanation ready before its menu opens
appflowy Oct 14, 2026
7e421ce
fix: keep Settings open when Escape closes a menu or question inside it
appflowy Oct 14, 2026
cc6d47a
fix: offer only Discard once a created space's first page can't be ma…
appflowy Oct 14, 2026
5d01dbc
fix: show keyboard focus on the buttons of confirmations
appflowy Oct 14, 2026
92be5c5
fix: say in plain words why New Page could not add the page
appflowy Oct 14, 2026
fb1be71
fix: leave focus where the user put it in a space's General tab
appflowy Oct 14, 2026
2e7c057
Merge branch 'oodrive-fix/web-w3b' into codex/oodrive-permissions-fixes
appflowy Oct 14, 2026
8c127b0
fix: keep the whole focus ring of the space icon and type cards visible
appflowy Oct 14, 2026
210e758
test: pin Escape while a layer inside a dialog keeps itself open
appflowy Oct 14, 2026
1e6e68c
fix: set the focus ring apart from filled buttons
appflowy Oct 14, 2026
621bc0a
docs: say exactly when workspace creation shows the denial and rechecks
appflowy Oct 14, 2026
93a4ab5
test: explain which Escape cases also happen in a browser
appflowy Oct 14, 2026
b612fb9
Merge branch 'oodrive-fix/web-w3a' into codex/oodrive-permissions-fixes
appflowy Oct 14, 2026
e786252
fix: keep Manage Space member rows readable next to the Access column
appflowy Oct 14, 2026
005eff6
fix: drop the empty footer under the sign-out question and fix its wo…
appflowy Oct 14, 2026
564d200
fix: describe public spaces in sentence case
appflowy Oct 14, 2026
d2c4d93
test: add an opt-in capture spec for the permission screenshot gallery
appflowy Oct 14, 2026
e616b8c
docs: refresh the permission screenshot gallery for the redesigned UI
appflowy Oct 14, 2026
f8c5d0a
fix: let space settings use the window height and show when more is b…
appflowy Oct 14, 2026
6927372
fix: give space settings tabs, headings and table headers the app's s…
appflowy Oct 14, 2026
ce0489b
fix: title Manage space in sentence case and name the space it manages
appflowy Oct 14, 2026
efc3a04
fix: write the space type and full access confirmations in sentence case
appflowy Oct 14, 2026
93bbbf2
fix: explain the Access column for everyone in it, not "this person"
appflowy Oct 14, 2026
7b35e16
fix: flag extra access beside your own closed Access menu
appflowy Oct 14, 2026
0ae79bb
fix: say what narrowing space creation does and what all-space access…
appflowy Oct 14, 2026
c9ec5e8
fix: show a member who can't create spaces the answer in a callout
appflowy Oct 14, 2026
e38a775
fix: list who can be added when an Add members or groups button is pr…
appflowy Oct 14, 2026
5069106
fix: ask an account with an invitation to join it, and make Join the …
appflowy Oct 14, 2026
3040909
fix: say what signing out removes, and use one pair of verbs for it
appflowy Oct 14, 2026
02c1976
fix: keep the reason for an unavailable menu entry clear of the menu
appflowy Oct 14, 2026
da77b10
fix: drop page actions from a page you can't open, and balance its me…
appflowy Oct 14, 2026
7af339a
fix: tell pointer focus from keyboard focus on an unavailable menu entry
appflowy Oct 14, 2026
bcfa806
test: capture the new permission UI states for the screenshot gallery
appflowy Oct 14, 2026
32146d1
docs: refresh the permission screenshot gallery after the design review
appflowy Oct 14, 2026
31cb537
Merge branch 'oodrive-fix/web-visual' into codex/oodrive-permissions-…
appflowy Oct 14, 2026
d7327d2
Order the space creation choices from broadest to narrowest
appflowy Oct 14, 2026
a8a269d
Say when a waiting invitation is for a guest
appflowy Oct 14, 2026
9aaec72
Name the change that failed in Manage space and group access toasts
appflowy Oct 14, 2026
fde232d
Replace the Create space form with the answer when creation is refused
appflowy Oct 14, 2026
3f0ef35
Refresh the permission gallery for the Desktop parity fixes
appflowy Oct 14, 2026
514c4ac
Say whose access to all spaces could not be changed, in French
appflowy Oct 14, 2026
3b51653
Move keyboard focus to Close when Create space is refused
appflowy Oct 14, 2026
84b7569
Record that the guest invitation line waits for the server
appflowy Oct 14, 2026
967a6c3
Name the commit that holds the harness of the first gallery rerun
appflowy Oct 14, 2026
8d29f0e
Say that a gallery rerun can differ by a few pixels
appflowy Oct 14, 2026
cc8098d
Record the second gallery rerun after the review
appflowy Oct 14, 2026
6d8ece7
Say when a published page is too large to duplicate
appflowy Oct 14, 2026
ef390b5
Keep Manage Space tests off the network
appflowy Oct 14, 2026
23e604e
Show the guest invitation line in the account-only capture
appflowy Oct 15, 2026
d8cd564
Merge remote-tracking branch 'origin/main' into codex/oodrive-permiss…
appflowy Oct 15, 2026
0dd193e
Guard the missing selected workspace in Shared with me actions
appflowy Oct 15, 2026
64c554a
Read the database view source from its scoped storage
appflowy Oct 15, 2026
682be4a
Let ordinary requests use a token a sibling tab rotated
appflowy Oct 15, 2026
ec94ecf
Test the merged storage keys and Dexie upgrade path
appflowy Oct 15, 2026
c23b187
Fit test mocks to the merged module contracts
appflowy Oct 15, 2026
f0676d9
Align page creation tests with the merged Shared with me rules
appflowy Oct 15, 2026
5cff0f4
Cover atomic first pages in space creation recovery
appflowy Oct 15, 2026
2ad9159
Show the permission flows' own words through the shared error renderer
appflowy Oct 15, 2026
bf11a74
Expect shared error copy instead of raw text in permission tests
appflowy Oct 15, 2026
d33e876
Use one error precedence on the permission screens
appflowy Oct 15, 2026
a795f4d
Release atomic page commands the server refuses
appflowy Oct 15, 2026
e896053
Import the error helpers once in Search
appflowy Oct 15, 2026
a60ed47
fix: keep durable denials when a PR build's version 13 database upgrades
appflowy Oct 15, 2026
133e907
fix: never show the text of unexpected client errors on permission sc…
appflowy Oct 15, 2026
028e19b
fix: translate the shared error copy into French
appflowy Oct 15, 2026
02fd7d2
fix: keep creation drafts inside the server restore generation
appflowy Oct 15, 2026
d9c9acf
fix: remove an account's pre-restore copies when it signs out with re…
appflowy Oct 15, 2026
3e310e2
test: cover the login guards the merge moved or relaxed
appflowy Oct 15, 2026
bf9ff59
test: cover Shared with me actions for an account without a workspace
appflowy Oct 15, 2026
b59969d
refactor: group stored database names by restore generation without c…
appflowy Oct 15, 2026
c95f547
test: record the permission flows as videos
appflowy Oct 15, 2026
959cde7
docs: refresh the permission gallery on the merged code
appflowy Oct 15, 2026
00b7322
test: restore the edited page after a failed video and block browser …
appflowy Oct 15, 2026
c75fc38
docs: record the reader and editor videos again after the review
appflowy Oct 15, 2026
8468aff
Skip manifest replies that only repeat the server's deletions
appflowy Oct 15, 2026
0c8da2e
Prove server-held structs and drop stale manifest replies
appflowy Oct 15, 2026
2ae2fac
Queue a legacy view-cache merge only when it changes the database
appflowy Oct 15, 2026
5dbfedf
test: fail the permission videos if the fixed defects come back
appflowy Oct 15, 2026
9437908
docs: record the permission videos again on the fixed code
appflowy Oct 15, 2026
86d828c
Answer state-vector requests that arrive before the server's answer
appflowy Oct 15, 2026
6c99f7e
Count grown pending structs as a change when merging a legacy view cache
appflowy Oct 15, 2026
136a6ae
Document what the server-proof record relies on
appflowy Oct 15, 2026
92d493f
Test the update walker on strings cut inside a surrogate pair
appflowy Oct 15, 2026
11f843e
Fix search access refreshes and group coverage reconnects
appflowy Oct 15, 2026
0592a6d
Merge remote-tracking branch 'origin/main' into codex/oodrive-permiss…
appflowy Oct 17, 2026
0606b75
Re-probe active pages in the background on window focus
appflowy Oct 17, 2026
0c7268a
Keep permission answers on screen while focus re-reads them
appflowy Oct 17, 2026
a2f73e6
Forget the Move destination when the picker closes
appflowy Oct 17, 2026
68b2630
Run one upload access re-check per tab switch
appflowy Oct 17, 2026
968798f
Key the sync layer on the routed workspace
appflowy Oct 17, 2026
e4724dc
Keep database contexts stable across row peek URL writes
appflowy Oct 17, 2026
5944c01
Keep space member rows memoized when they show an Access column
appflowy Oct 17, 2026
1a4ba52
Check space creation while a meeting's event is still being read
appflowy Oct 17, 2026
22c5a85
Share view reads between search results and refined queries
appflowy Oct 17, 2026
b4ad15c
Stop the paused-edits notice from re-reading the outbox on every edit
appflowy Oct 17, 2026
95d2297
Gate full syncs once per batch and overlap Try again's access checks
appflowy Oct 17, 2026
7608bea
Share the workspace creation answer across its consumers
appflowy Oct 17, 2026
08344cd
Share the space creation answer and reuse it for admission
appflowy Oct 17, 2026
3d3a276
Send one pending invitations request per tab return
appflowy Oct 17, 2026
eafa83d
Read the workspace group list once per panel and join it on tab return
appflowy Oct 17, 2026
81817bf
Capture the storage scope once per seed check and seeding pass
appflowy Oct 17, 2026
3e47cbf
Correct comments on permission re-checks and the routed workspace id
appflowy Oct 17, 2026
52e1380
Keep sidebar branches visible while permission changes refetch them
appflowy Oct 17, 2026
087171f
Keep pending sidebar branches visible while another load fetches them
appflowy Oct 17, 2026
a7c7d20
Keep the open page editable while permission changes re-check it
appflowy Oct 18, 2026
4fc25df
Keep permission answers on screen while permission changes re-read them
appflowy Oct 18, 2026
4f12f0d
Prune stored page permissions on routes that render no view
appflowy Oct 18, 2026
8b7364d
Start permission re-reads after the event's own invalidations
appflowy Oct 18, 2026
a98b986
Refetch every affected sidebar branch at once after a permission change
appflowy Oct 18, 2026
397f464
Unmark nested sidebar branches that a failed permission refetch drops
appflowy Oct 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .eslintignore.web
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ playwright/
playwright.config.ts
playwright.integrations.config.ts
playwright.bdd.config.ts
playwright.permissions.config.ts
playwright.permission-gallery.config.ts
playwright-snapshot.config.ts
deploy/*.test.ts
deploy/*.integration.test.ts
Expand Down
233 changes: 233 additions & 0 deletions doc/web-server-compatibility.md

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions playwright.permission-gallery.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { defineConfig, devices } from '@playwright/test';

import { galleryLaunchOptions } from './playwright/support/permission-gallery-browser';

/**
* Opt-in screenshot gallery and videos of the workspace permission UI (Web PR #621). Both seed a
* synthetic "Demo" workspace through the APIs of an isolated loopback stack; see
* playwright/e2e/app/permission-gallery.capture.spec.ts for the required variables, and
* permission-videos.capture.spec.ts for the videos (which also need APPFLOWY_PERMISSION_VIDEOS=1).
*/
export default defineConfig({
testDir: './playwright/e2e/app',
testMatch: ['permission-gallery.capture.spec.ts', 'permission-videos.capture.spec.ts'],
fullyParallel: false,
workers: 1,
retries: 0,
forbidOnly: !!process.env.CI,
timeout: 300000,
reporter: 'list',
outputDir: process.env.APPFLOWY_GALLERY_RESULTS_DIR ?? `test-results/permission-gallery-${Date.now()}`,
use: {
baseURL: process.env.BASE_URL,
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1,
trace: 'off',
video: 'off',
screenshot: 'only-on-failure',
actionTimeout: 15000,
navigationTimeout: 60000,
},
projects: [{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1,
// The gallery's Chromium and flags, shared with the video spec (see the helper).
launchOptions: galleryLaunchOptions(),
},
}],
expect: { timeout: 30000 },
});
35 changes: 35 additions & 0 deletions playwright.permissions.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { defineConfig, devices } from '@playwright/test';

// Explicit opt-in fixture; no setup, seeding, server start, or .env mutation.
export default defineConfig({
testDir: './playwright/e2e/app',
testMatch: ['space-group-permission-lifecycle.spec.ts', 'space-group-permission-boundaries.spec.ts'],
fullyParallel: false,
workers: 1,
retries: 0,
forbidOnly: !!process.env.CI,
timeout: 240000,
reporter: 'list',
outputDir: process.env.APPFLOWY_PERMISSION_OUTPUT_DIR ?? `test-results/permissions-${Date.now()}`,
use: {
baseURL: process.env.BASE_URL,
viewport: { width: 1440, height: 900 },
trace: 'off',
video: 'off',
screenshot: 'only-on-failure',
actionTimeout: 15000,
navigationTimeout: 60000,
},
projects: [{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1440, height: 900 },
launchOptions: {
executablePath: process.env.APPFLOWY_TEST_CHROMIUM_EXECUTABLE,
args: ['--no-sandbox', '--disable-dev-shm-usage'],
},
},
}],
expect: { timeout: 30000 },
});
789 changes: 789 additions & 0 deletions playwright/bdd/evidence/space-group-permission-lifecycle/README.md

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2,667 changes: 2,667 additions & 0 deletions playwright/bdd/evidence/space-group-permission-lifecycle/capture-manifest.json

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"date": "2026-10-12",
"scope": "Web workspace permission implementation draft PR",
"checks": {
"affected_jest_suites": {
"status": "passed; 1021 tests, 70 suites",
"local_log": "pr1367-web-pr-tests.log",
"log_sha256": "abe44d7c28e058861a5d7f393ef4645e6fb3a2e78e1ea22a454f6b3eadc4611c"
},
"lint_only_followup": {
"status": "passed; 38 tests, 3 suites",
"local_log": "pr1367-web-pr-lintfix-tests.log",
"log_sha256": "ba80f1ca7025cc8ec1ae4a454d9cf39df139a295f70fcd2918bca3a5380ca37c"
},
"production_types": {
"status": "passed",
"local_log": "pr1367-web-pr-typecheck.log",
"log_sha256": "1314ed95803fcc4bbe81fb7906f3f2aa87b0c2e6d713dbf2c113bf2aefa372fa"
},
"permission_harness_types": {
"status": "passed",
"local_log": "pr1367-web-pr-playwright-tsc.log",
"log_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"python_guards": {
"status": "passed; 10 tests",
"local_log": "pr1367-web-pr-python-guards.log",
"log_sha256": "45629e08d8c41ba474e149425cf4477b6ed2d14afbd48b41a5dea35ddb36ae32"
},
"offline_browser_guards": {
"status": "passed; 4 tests",
"local_log": "pr1367-web-pr-boundaries.log",
"log_sha256": "9e0fd43a777d43163ab3d03363181185817910f4e13224d8ee0fbd7da1ace814"
},
"indexeddb_browser": {
"status": "passed; real Chromium and IndexedDB",
"local_log": "pr1367-web-pr-indexeddb.log",
"log_sha256": "b8f897e6c1689479af8c4f0637ab163f31fb07e9d520e127c59ff9b2ba3faefc"
},
"bdd_generation": {
"status": "passed; generation only",
"local_log": "pr1367-web-pr-bddgen.log",
"log_sha256": "bff5996bd1af4ba577930723a705fb379013de8d3e4cc41b63c619375717dfca"
},
"fresh_captures": {
"status": "passed; 5 screenshots",
"local_log": "pr1367-web-pr-capture-final2.log",
"log_sha256": "703404bf95e72f174671f244e687d1dd49b94986d7d0904eeeaeb5b8e09ff4f7"
},
"full_application_lint": {
"status": "passed; pnpm lint (production TypeScript and complete application ESLint)",
"local_log": "pr1367-web-pr-full-lint-final.log",
"log_sha256": "c483c36c55a8dff072344ae418f3ffff7d78f6b37eb386082770be0f95f5b49e"
}
},
"limits": [
"Affected Jest suites only, not the entire repository Jest suite.",
"Full connected lifecycle was not rerun against final four Rust review fixes; previous 44-check result stays separately qualified.",
"Fresh captures are read-only and unsaved coverage drafts.",
"No cross-browser, packaged Desktop, external provider, AI search or deployment acceptance claim."
],
"followup": "Three test files received type/lint-only cleanup after the 1021-test run; all 38 tests in those suites were rerun and passed. Production code did not change. The standalone Playwright config uses the same application-lint exclusion as its sibling configs and passes its separate TypeScript project. One extra EOF blank line in a new file was removed."
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -227,16 +227,16 @@ Feature: Seeded Public, Private and Custom space permissions
And the Manage Space members list shows seeded scp0822 "outsider" as "Space member" with the subtitle "Workspace member"

# (j) PRD §17/§39 Custom General: both collective dropdowns offer all five access levels and
# Can view and comment applies like any other level.
# Can comment applies like any other level.
Scenario: The collective dropdowns offer every access level including comment-only
Given I sign in as seeded scp0822 "owner"
When I open the seeded scp0822 "custom space" manage space panel
Then the Custom permissions "space members" dropdown offers every access level
And the Custom permissions "everyone else" dropdown offers every access level
When I set the Custom permissions space members level to "Can view and comment"
Then the seeded scp0822 "custom space" members level is "Can view and comment" via the API
When I set the Custom permissions space members level to "Can comment"
Then the seeded scp0822 "custom space" members level is "Can comment" via the API
When I open the seeded scp0822 "custom space" manage space panel
Then the Custom permissions card shows Space members "Can view and comment" and everyone else "Can view"
Then the Custom permissions card shows Space members "Can comment" and everyone else "Can view"
When I sign in as seeded scp0822 "member"
And I directly open the seeded scp0822 "custom page"
Then the directly opened seeded scp0822 page is "read-only"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Feature: Seeded space group permission resolution
When I directly open the seeded stg0822 "group page B"
Then the directly opened seeded stg0822 page is "denied"

# The Manage Space members tab renders the group's role; its access level is verified via API.
# The Manage Space members tab renders the group's role and tri-state override selector.
Scenario: Owner sees the group as a space member and the page-level group share
Given I sign in as seeded stg0822 "owner"
When I open the seeded stg0822 "group space A" manage space members tab
Expand All @@ -47,7 +47,7 @@ Feature: Seeded space group permission resolution
And I open the share panel
Then the share panel shows seeded stg0822 "group two" with "Can edit"

# Mutating: the After hook always restores group One to Member / Can view via API.
# Mutating: the After hook restores the exact prior role and override, including inherited null.
Scenario: Owner-role group makes its members space owners
Given I sign in as seeded stg0822 "owner"
When I open the seeded stg0822 "group space A" manage space members tab
Expand All @@ -61,7 +61,7 @@ Feature: Seeded space group permission resolution
# Live refresh: the owner mutates group membership over the API while nathan's browser
# session stays on Page A. The server pushes a permission-changed notification and the
# open page downgrades, then upgrades again, without any reload or navigation.
# Mutating: the After hook re-adds every seeded group membership via API.
# Mutating: the After hook restores the exact prior seeded memberships via API.
@live-refresh
Scenario: Removing a member from the page-share group downgrades the open page live
Given I sign in as seeded stg0822 "nathan"
Expand All @@ -74,7 +74,7 @@ Feature: Seeded space group permission resolution

# Live refresh: revoking group One's space grant must deny the open page and drop the
# restricted Custom space from the sidebar in place; re-granting it restores both.
# Mutating: the After hook always restores group One to Member / Can view via API.
# Mutating: the After hook restores the exact prior role and override, including inherited null.
@live-refresh
Scenario: Removing the group from the space hides it live and restores it
Given I sign in as seeded stg0822 "reader"
Expand All @@ -89,11 +89,11 @@ Feature: Seeded space group permission resolution
Then the seeded stg0822 "group space A" space navigation becomes "visible" without reload
And the open seeded stg0822 page becomes "read-only" without reload

# Custom Member principals share one collective access level; an individual group cannot carry
# a different level. Changing that collective level re-probes the open page in place.
# Mutating: the After hook restores the Custom member level to Can view via API.
# The baseline group explicitly inherits (access_level_override: null). Changing the
# collective default updates inherited assignments; explicit overrides remain independent.
# Mutating: the After hook restores the exact prior default and assignment via API.
@live-refresh
Scenario: Changing Custom space member access updates an open page live
Scenario: An inherited group assignment follows Custom space member access live
Given I sign in as seeded stg0822 "reader"
When I directly open the seeded stg0822 "group page B"
Then the directly opened seeded stg0822 page is "read-only"
Expand Down
4 changes: 2 additions & 2 deletions playwright/bdd/steps/space-custom-permissions.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@
const modal = manageSpaceModal(page);

await expect(modal).toBeVisible({ timeout: 15000 });
await expect(modal.getByText('Manage Space', { exact: true })).toBeVisible({ timeout: 15000 });

Check failure on line 823 in playwright/bdd/steps/space-custom-permissions.steps.ts

View workflow job for this annotation

GitHub Actions / space-permissions-bdd

[chromium] › playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:11:3 › Seeded Public

2) [chromium] › playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:11:3 › Seeded Public, Private and Custom space permissions › Owner edits the public workspace members level from the Public access card @scp0822-space-permissions @mode:serial › When I open the seeded scp0822 "public space" manage space panel Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toBeVisible() failed Locator: getByTestId('manage-space-modal').getByText('Manage Space', { exact: true }) Expected: visible Timeout: 15000ms Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 15000ms - waiting for getByTestId('manage-space-modal').getByText('Manage Space', { exact: true }) at ../bdd/steps/space-custom-permissions.steps.ts:823 821 | 822 | await expect(modal).toBeVisible({ timeout: 15000 }); > 823 | await expect(modal.getByText('Manage Space', { exact: true })).toBeVisible({ timeout: 15000 }); | ^ 824 | // The space access cards enable once the structured settings have loaded. 825 | await expect(modal.getByTestId('manage-space-visibility-option-public')).toBeEnabled({ timeout: 15000 }); 826 | } at openManageSpacePanel (/home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/bdd/steps/space-custom-permissions.steps.ts:823:66) at Object.<anonymous> (/home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/bdd/steps/space-custom-permissions.steps.ts:275:3) at /home/runner/work/AppFlowy-Web/AppFlowy-Web/node_modules/.pnpm/playwright-bdd@8.5.1_@playwright+test@1.58.2/node_modules/playwright-bdd/src/runtime/bddStepInvoker.ts:59:22 at BddStepInvoker.invoke (/home/runner/work/AppFlowy-Web/AppFlowy-Web/node_modules/.pnpm/playwright-bdd@8.5.1_@playwright+test@1.58.2/node_modules/playwright-bdd/src/runtime/bddStepInvoker.ts:53:5) at /home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:13:5

Check failure on line 823 in playwright/bdd/steps/space-custom-permissions.steps.ts

View workflow job for this annotation

GitHub Actions / space-permissions-bdd

[chromium] › playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:11:3 › Seeded Public

2) [chromium] › playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:11:3 › Seeded Public, Private and Custom space permissions › Owner edits the public workspace members level from the Public access card @scp0822-space-permissions @mode:serial › When I open the seeded scp0822 "public space" manage space panel Error: expect(locator).toBeVisible() failed Locator: getByTestId('manage-space-modal').getByText('Manage Space', { exact: true }) Expected: visible Timeout: 15000ms Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 15000ms - waiting for getByTestId('manage-space-modal').getByText('Manage Space', { exact: true }) at ../bdd/steps/space-custom-permissions.steps.ts:823 821 | 822 | await expect(modal).toBeVisible({ timeout: 15000 }); > 823 | await expect(modal.getByText('Manage Space', { exact: true })).toBeVisible({ timeout: 15000 }); | ^ 824 | // The space access cards enable once the structured settings have loaded. 825 | await expect(modal.getByTestId('manage-space-visibility-option-public')).toBeEnabled({ timeout: 15000 }); 826 | } at openManageSpacePanel (/home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/bdd/steps/space-custom-permissions.steps.ts:823:66) at Object.<anonymous> (/home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/bdd/steps/space-custom-permissions.steps.ts:275:3) at /home/runner/work/AppFlowy-Web/AppFlowy-Web/node_modules/.pnpm/playwright-bdd@8.5.1_@playwright+test@1.58.2/node_modules/playwright-bdd/src/runtime/bddStepInvoker.ts:59:22 at BddStepInvoker.invoke (/home/runner/work/AppFlowy-Web/AppFlowy-Web/node_modules/.pnpm/playwright-bdd@8.5.1_@playwright+test@1.58.2/node_modules/playwright-bdd/src/runtime/bddStepInvoker.ts:53:5) at /home/runner/work/AppFlowy-Web/AppFlowy-Web/playwright/.features-gen/playwright/bdd/features/workspace/space-custom-permissions.feature.spec.js:13:5
// The space access cards enable once the structured settings have loaded.
await expect(modal.getByTestId('manage-space-visibility-option-public')).toBeEnabled({ timeout: 15000 });
}
Expand Down Expand Up @@ -1328,7 +1328,7 @@
return null;
case 'Can view':
return ACCESS_LEVEL_READ_ONLY;
case 'Can view and comment':
case 'Can comment':
return ACCESS_LEVEL_READ_AND_COMMENT;
case 'Can edit':
return ACCESS_LEVEL_READ_AND_WRITE;
Expand Down Expand Up @@ -1368,7 +1368,7 @@
const expected: Array<[string, string]> = [
[`${triggerTestId}-option-${ACCESS_LEVEL_FULL_ACCESS}`, 'Full access'],
[`${triggerTestId}-option-${ACCESS_LEVEL_READ_AND_WRITE}`, 'Can edit'],
[`${triggerTestId}-option-${ACCESS_LEVEL_READ_AND_COMMENT}`, 'Can view and comment'],
[`${triggerTestId}-option-${ACCESS_LEVEL_READ_AND_COMMENT}`, 'Can comment'],
[`${triggerTestId}-option-${ACCESS_LEVEL_READ_ONLY}`, 'Can view'],
[`${triggerTestId}-option-none`, 'No access'],
];
Expand Down
Loading
Loading