Skip to content
Closed
Show file tree
Hide file tree
Changes from 214 commits
Commits
Show all changes
220 commits
Select commit Hold shift + click to select a range
416c891
Add Cloud Team Collections design + implementation plan
hatton Jul 3, 2026
c72ed72
Rework Cloud TC plan for local-first development
JohnThomson Jul 6, 2026
ceef199
task 00: Add cloud TC enablers (TeamCollectionLink, factory, lock sea…
JohnThomson Jul 6, 2026
082d1a9
Add tc schema, RLS, RPCs, and pgTAP tests (task 01)
JohnThomson Jul 6, 2026
59831e6
Task 11: author local dev stack (MinIO + Supabase + seed + docs)
JohnThomson Jul 6, 2026
bf4294c
Merge task 00 (enablers): backend-pluggable TC base classes
JohnThomson Jul 6, 2026
3404c19
Merge task 01 (server schema): tc schema, RLS, RPCs, pgTAP suite
JohnThomson Jul 6, 2026
c511b76
Review fixes for task 01 (orchestrator)
JohnThomson Jul 6, 2026
c7ade8b
Merge task 11 (local dev stack): MinIO compose, dev seed, smoke + par…
JohnThomson Jul 6, 2026
2d37e0e
Fix dev seed bcrypt hash (orchestrator review)
JohnThomson Jul 6, 2026
c9fb177
Update Cloud TC plan: Wave 0 done, merge log, CONTRACTS v1.1
JohnThomson Jul 6, 2026
c1f9d99
Verify local dev stack end-to-end on Podman; fix issues found by running
JohnThomson Jul 6, 2026
f3dc155
Task 03: Cloud TC auth + client skeleton (CloudEnvironment, CloudAuth…
JohnThomson Jul 6, 2026
cc9499b
Add resume-aware orchestration prompts for tasks 02, 03, 07
JohnThomson Jul 6, 2026
f259680
Task 03: unit tests for Cloud TC auth + client (acceptance criteria)
JohnThomson Jul 6, 2026
2f56dd3
Move stranded doc comment onto CloudCollectionClient (orchestrator re…
JohnThomson Jul 6, 2026
9677289
Task 02: author internal checkin/collection-files transaction RPCs + …
JohnThomson Jul 6, 2026
1e66d3a
Task 02: live-integration verify all 6 edge functions; fix 4 real bug…
JohnThomson Jul 7, 2026
55f84a5
Task 02: export edge-function handlers behind import.meta.main guard
JohnThomson Jul 7, 2026
82408c4
Task 02: Deno test suite for all 6 edge functions + invariant checks
JohnThomson Jul 7, 2026
6955c3e
Task 02: author server/provision-aws.ps1 (idempotent AWS provisioning)
JohnThomson Jul 7, 2026
646c47b
WIP (session interrupted): SharingPanel shell + sharingApi mock + tests
JohnThomson Jul 7, 2026
8912a5b
Task 07 step 1: gate cloud-sharing entry point behind experimental flag
JohnThomson Jul 7, 2026
e86b442
Task 07 step 2: cloud Team Collection creation dialog (shell)
JohnThomson Jul 7, 2026
5e20b32
Task 07 step 3 (part 1/2): "Get my Team Collections" chooser sidebar
JohnThomson Jul 7, 2026
8385b94
Task 07 step 3 (part 2/2): pull-down-join dialog for cloud collections
JohnThomson Jul 7, 2026
7d13152
Task 07 step 4: lock registration email to the cloud account identity
JohnThomson Jul 7, 2026
4adfc8f
WIP (session limit hit): XLF strings sweep + component string wiring
JohnThomson Jul 7, 2026
3c8e88e
Task 07 final wrap-up: verify prettier/tests/lint/XLF, close out prog…
JohnThomson Jul 7, 2026
6de9511
Gate the chooser's cloud section behind the experimental feature (orc…
JohnThomson Jul 7, 2026
af2b4c6
Merge task 03 (auth): CloudEnvironment, CloudAuth dev provider, Cloud…
JohnThomson Jul 6, 2026
461515f
Record task 03 merge in plan status + merge log
JohnThomson Jul 6, 2026
39650c8
Merge task 02 (edge functions): all six functions, live-verified on l…
JohnThomson Jul 7, 2026
ac38a22
Record task 02 merge; add *_tx grant hardening to cutover checklist
JohnThomson Jul 7, 2026
0d9cd41
Merge task 07 (UI shells): sharing panel, cloud create dialog, choose…
JohnThomson Jul 7, 2026
67b5d36
Record task 07 merge: Wave 1 complete
JohnThomson Jul 7, 2026
5d18303
Add Wave-2 orchestration prompts (04, 08); generalize resume protocol
JohnThomson Jul 7, 2026
524afdb
Task 04: implement CloudRepoCache, BookVersionManifest, CloudBookTran…
JohnThomson Jul 7, 2026
e20d39f
Task 04: acceptance tests for CloudRepoCache/BookVersionManifest/Clou…
JohnThomson Jul 7, 2026
0456e6d
Task 08 step 1: status button live metadata + Wave-2 capability/statu…
JohnThomson Jul 7, 2026
887ff9a
WIP (session limit hit): TeamCollectionDialog Receive Updates / Send …
JohnThomson Jul 7, 2026
0a798f5
Task 08 step 2: status dialog Receive Updates / Send All (finish resu…
JohnThomson Jul 7, 2026
6808bcc
Task 08 step 3: Share button beside the status button
JohnThomson Jul 7, 2026
f2984f4
Task 08 step 4: per-book panel cloud states + audited Force Unlock
JohnThomson Jul 7, 2026
5befadb
Task 08 step 5: book thumbnail "newer version exists" marker
JohnThomson Jul 7, 2026
33d29c6
Task 08 step 6: history tab server events feed + local cache (Wave-2 …
JohnThomson Jul 7, 2026
b5c70ff
Cache experimental-feature/capability fetches once per page load (orc…
JohnThomson Jul 7, 2026
0202617
Merge task 04 (client core): CloudRepoCache, BookVersionManifest, Clo…
JohnThomson Jul 7, 2026
bb10ef8
Record task 04 merge: contract gap, SDK follow-up, swap note for 05
JohnThomson Jul 7, 2026
2de3f0d
Merge task 08 (collection-tab shells): status button, dialog, share, …
JohnThomson Jul 7, 2026
06a8bd6
Record task 08 merge: Wave 2 complete
JohnThomson Jul 7, 2026
e48ecba
Add get_book_manifest RPC (CONTRACTS v1.2); task 05 launch prompt
JohnThomson Jul 7, 2026
992e129
Task 05: add typed RPC/edge-function wrappers to CloudCollectionClient
JohnThomson Jul 7, 2026
b8c34a7
Task 05: implement CloudTeamCollection and CloudCollectionMonitor
JohnThomson Jul 7, 2026
ff0d71e
Task 05: add CloudJoinFlow (list/create/join a cloud Team Collection)
JohnThomson Jul 7, 2026
7038fdd
Task 05: wire CloudTeamCollection into TeamCollectionManager (authori…
JohnThomson Jul 7, 2026
7825d6b
Task 05: simplify unified-recovery messaging to what PutBookInRepo ca…
JohnThomson Jul 7, 2026
6704b81
Task 05: add CloudTeamCollection/Monitor test suite
JohnThomson Jul 7, 2026
ddfc9f3
Task 05: add live Send/Receive round-trip test; fix 2 bugs it found
JohnThomson Jul 7, 2026
90c86e8
Base-class fixes from task 05 review (orchestrator)
JohnThomson Jul 7, 2026
ef21aff
Merge task 05 (cloud backend): CloudTeamCollection, monitor, join flow
JohnThomson Jul 7, 2026
c08a00d
Task 06 step: add lockedByEmail/lockedByName migration (locked_by dis…
JohnThomson Jul 7, 2026
3b6924d
Record task 05 merge; add task 06 launch prompt
JohnThomson Jul 7, 2026
b2381bc
Task 06 step: Cloud backend additions for API wiring (localVersionSeq…
JohnThomson Jul 7, 2026
91c02cf
Task 06 step: fix MembersRemove/MembersSetRole RPC param mismatch (li…
JohnThomson Jul 7, 2026
81d8fcd
Task 06 step: TeamCollectionApi additive endpoints (capabilities, sta…
JohnThomson Jul 7, 2026
3da6edc
Task 06 step: new SharingApi (sharing/* and collections/* endpoints),…
JohnThomson Jul 7, 2026
d2dd914
Task 06 step: SharingApiTests + TeamCollectionApiCloudTests, visibili…
JohnThomson Jul 7, 2026
45259c5
Task 06 step: fix timezone-dependent assertion in SharingApiTests
JohnThomson Jul 7, 2026
c1d6c4e
Task 06: tick checkboxes, close out progress log
JohnThomson Jul 7, 2026
9d62de9
Merge task 06 (API endpoints): SharingApi, TeamCollectionApi addition…
JohnThomson Jul 7, 2026
0437065
Record task 06 merge; add UI-wiring launch prompt
JohnThomson Jul 7, 2026
1c12440
Fix folder-TC create dialog breakage; add dedicated sign-in dialog (t…
JohnThomson Jul 7, 2026
cc7195c
Wire SharingPanel into TeamCollectionSettingsPanel for cloud TCs (tas…
JohnThomson Jul 7, 2026
8686cfd
Wire JoinCloudCollectionDialog into CollectionChooser's onPullDown (t…
JohnThomson Jul 7, 2026
625a84f
Update stale mock/not-implemented doc comments now that endpoints are…
JohnThomson Jul 7, 2026
e024a35
Record final test sweep + lint results (task 07 Wave-3, item 6)
JohnThomson Jul 7, 2026
4cb894c
Fix claimed-detection for pending invitations (orchestrator review)
JohnThomson Jul 7, 2026
6d05377
Merge Wave-3 UI wiring: dispatcher fix, sign-in dialog, panel/chooser…
JohnThomson Jul 7, 2026
2918339
RESUME.md: record the mandatory widened C# test filter
JohnThomson Jul 7, 2026
d569d46
Record UI-wiring merge: Wave-3 code complete, manual smoke remains
JohnThomson Jul 7, 2026
57cd34f
Fix two crashes found by the first two-instance smoke test
JohnThomson Jul 7, 2026
f424871
Fix cloud checkout shown as 'checked out to null null' by its own owner
JohnThomson Jul 7, 2026
f3aa6b8
Stop the other-group mirror-delete from removing TeamCollectionLink.txt
JohnThomson Jul 7, 2026
715e0fe
Route all checkout-ownership identity through one virtual seam
JohnThomson Jul 7, 2026
2386ebd
Fix OkToCheckIn (and 3 more sites) comparing lock owners to registrat…
JohnThomson Jul 7, 2026
1409e79
Fix update-Send committing changed-files-only manifests (data loss at…
JohnThomson Jul 7, 2026
b39d26f
Fix cloud change notifications discarded by the .bloom-suffix contract
JohnThomson Jul 8, 2026
fe5593b
Record Wave-3 gate PASSED (two-instance smoke); 12-bug session log
JohnThomson Jul 8, 2026
c3c0b8e
Add Wave-4 orchestration prompts (09 E2E, 10 adoption+polish)
JohnThomson Jul 8, 2026
9052dfc
Task 10 item 1: proper "Cloud Team Collections (experimental)" checkbox
JohnThomson Jul 8, 2026
a6f1fbf
Task 10 item 2: pull-down auto-open + cloud join analytics
JohnThomson Jul 8, 2026
e09fd92
Task 10 item 3 (task-file step 1): un-team cleanup + link conflict guard
JohnThomson Jul 8, 2026
e4ce31b
Task 10 item 7: analytics audit -- add missing Receive Updates event
JohnThomson Jul 8, 2026
c03c1ce
Task 10 item 4: First-Receive reconcile -- verified by reading, docum…
JohnThomson Jul 8, 2026
6b3af90
Task 10 item 5: user walkthrough doc + fix Team Collection tab visibi…
JohnThomson Jul 8, 2026
cbbf541
Task 09: E2E harness + scenario E2E-1 (create/share to cloud)
JohnThomson Jul 8, 2026
ece1df4
Task 10 item 6: localization sweep of all new cloud Team Collection s…
JohnThomson Jul 8, 2026
f724349
Task 09: E2E-2 (two-instance collaboration loop) + harness resilience…
JohnThomson Jul 8, 2026
9896816
Task 09: clean up leaked WebView2 profile temp folders in globalSetup
JohnThomson Jul 8, 2026
6457787
Task 09: E2E-2 verified green by orchestrator re-run on unloaded machine
JohnThomson Jul 8, 2026
8974386
Review fixes for task 10 (orchestrator)
JohnThomson Jul 8, 2026
fd6b7fd
Merge task 09 (E2E harness): Playwright-over-CDP harness, E2E-1 + E2E…
JohnThomson Jul 8, 2026
584616d
Merge task 10 (adoption + polish): experimental checkbox, auto-open, …
JohnThomson Jul 8, 2026
c42fde4
Record Wave-4 progress: 09 harness + E2E-1/2 and 10 adoption merged
JohnThomson Jul 8, 2026
8f52949
Update RESUME.md: Wave-4 branches merged; E2E-3..10 continue via 09 p…
JohnThomson Jul 8, 2026
bcca8d9
Fix Bloom-crashing double hyphens in new XLF notes; pin rule in skill
JohnThomson Jul 8, 2026
b7d568c
E2E-1: connect over CDP before createCloudTeamCollection (deadlock gu…
JohnThomson Jul 8, 2026
30eb806
Task 09 progress log: UI-thread create deadlock + locked-session find…
JohnThomson Jul 8, 2026
00d3014
Merge log: post-merge E2E gate results (XLF crash caught; env findings)
JohnThomson Jul 8, 2026
d1f5525
E2E-3: checkout contention (exactly one winner; loser sees holder)
JohnThomson Jul 8, 2026
7b028ec
E2E-9: new-book lifecycle (3 tests green); fix two real product bugs …
JohnThomson Jul 8, 2026
d423ac1
E2E-5: approved accounts on two fresh profiles (green)
JohnThomson Jul 8, 2026
c663579
E2E-7: un-team adoption (2 tests green)
JohnThomson Jul 8, 2026
6375319
E2E-4: forced-unlock/steal flow green; fix LogEvent p_message bug; do…
JohnThomson Jul 8, 2026
c3eda13
E2E-6: kill mid-Send / resume, never a partial version (existing-book…
JohnThomson Jul 8, 2026
6d9dd83
E2E-8: Receive-during-Send coherence (mandated) - byte-perfect old ve…
JohnThomson Jul 8, 2026
af619f0
Task 09: document E2E-10 account-switch safety as BLOCKED (feature no…
JohnThomson Jul 8, 2026
2106a43
E2E-8: tidy stale header comment about the window-widening file
JohnThomson Jul 8, 2026
dcd739a
Harness: scope the foreign-Bloom guard to THIS repo tree
JohnThomson Jul 8, 2026
8da100b
Add go-live runbook, E2E machine/TeamCity setup docs, unit-test setup…
JohnThomson Jul 8, 2026
6cbcbee
Harness: kill by PID not just port; 120s timeout for createCloudTeamC…
JohnThomson Jul 8, 2026
5dd850e
E2E-8: 256MB kill window; opt-in BLOOM_E2E_SCREEN monitor confinement
JohnThomson Jul 8, 2026
c97db66
E2E-8: fix UUID-ordered freeze-check (real bug behind all three failu…
JohnThomson Jul 8, 2026
13b4b00
BLOOM_E2E_SCREEN: fall back to the registry user/machine env value
JohnThomson Jul 8, 2026
67f1723
Fix four create-helper call sites the regex edit missed (multi-line)
JohnThomson Jul 8, 2026
93710fa
Task 09 progress log: findings 9 (problem-report modal freezes automa…
JohnThomson Jul 8, 2026
c7310cf
Merge task 09 continuation: E2E-3..9 scenarios, 3 product fixes, matr…
JohnThomson Jul 8, 2026
4a39c6d
Record Wave-4 E2E scenario completion; acceptance = idle-machine matr…
JohnThomson Jul 8, 2026
c6f7a9a
RESUME.md: Wave-4 fully merged; remaining = idle-machine matrix + dec…
JohnThomson Jul 8, 2026
2ced6e4
Auth Option A decided: update design/go-live docs; add task 12 (real …
JohnThomson Jul 8, 2026
a598e48
Complete Auth Option A decision doc update in CloudTeamCollections.md
JohnThomson Jul 8, 2026
998b631
Task 12 steps 1-2: Firebase token provider + persistent DPAPI token s…
JohnThomson Jul 8, 2026
718d49f
Task 12 steps 3 & 6: token-receipt endpoint + cloud-mode sign-in dialog
JohnThomson Jul 8, 2026
d830942
Task 12 step 4: verify tc.jwt_email_verified() already handles Fireba…
JohnThomson Jul 8, 2026
e071be3
Task 12 step 5 (final step): reference Firebase Admin artifacts
JohnThomson Jul 8, 2026
dbf5a8e
Task 12: fix duplicate progress-log heading, correct vitest verificat…
JohnThomson Jul 8, 2026
5fbee9d
Merge task 12: Option A auth seams (Firebase provider, token store, r…
JohnThomson Jul 8, 2026
49039fa
Merge log: task 12 Option A auth seams
JohnThomson Jul 8, 2026
62a86a7
Rename BLOOM_DEV_MODE -> BLOOM_CLOUD_LOCAL_MODE (and isDevMode -> isL…
JohnThomson Jul 8, 2026
6ac0aef
E2E: pin join auto-open live (pullDown path contract + in-place openC…
JohnThomson Jul 8, 2026
36e0975
Harness: retry + 60s timeout on the foreign-Bloom probe
JohnThomson Jul 9, 2026
f2cb367
Harness: salvage probe JSON when bloomProcessStatus crashes after pri…
JohnThomson Jul 9, 2026
b660890
Harness: never give the status probe a pipe (redirect stdout to a file)
JohnThomson Jul 9, 2026
379addc
Harness probe: file-descriptor stdout via spawn (no pipe, no shell)
JohnThomson Jul 9, 2026
8216870
Harness preflight: Get-Process fallback when the status probe fails
JohnThomson Jul 9, 2026
2278d29
Automation mode: report errors instead of hanging on modal dialogs
JohnThomson Jul 9, 2026
05e57cb
BLOOM_CLOUDTC_POLL_SECONDS (default 60); record 13/13 acceptance PASS
JohnThomson Jul 9, 2026
75b83cf
Fix cloud checkin comments never reaching the server history
JohnThomson Jul 9, 2026
8394e87
Log the checkin-comment fix in the Cloud TC merge log
JohnThomson Jul 9, 2026
5dfcf3e
Add restartable plan for dogfood batch 1 (9 Jul list from John)
JohnThomson Jul 9, 2026
36dc306
Batch plan: pin the atomic-apply safety rule for auto-updates and pro…
JohnThomson Jul 9, 2026
2d74d28
Add Common.BloomIsBusy to the XLF (dogfood batch item 1)
JohnThomson Jul 9, 2026
6f0c4a0
Poll the cloud TC immediately when a book is selected (batch item 2)
JohnThomson Jul 9, 2026
207cc1d
Center the cloud checkin-progress dialog on the TC status panel (batc…
JohnThomson Jul 9, 2026
86ea528
Batch plan: items 1-3 code done; Bloom-launching verification queued …
JohnThomson Jul 9, 2026
4e43a6d
Batch plan: add scouted implementation notes for item 6 (join cards)
JohnThomson Jul 9, 2026
4e6544b
Batch item 4+5 (1/n): auto-apply remote book changes for cloud TCs
JohnThomson Jul 9, 2026
de78b91
Batch item 4+5 (2/n): unit tests for the auto-apply queue and eligibi…
JohnThomson Jul 9, 2026
c2d4603
Batch item 4+5 (3/n): rename cloud "Receive Updates" to "Sync"
JohnThomson Jul 9, 2026
0eb9f99
Batch item 4+5 (4/n): tick checklist, record diagnosis, progress log
JohnThomson Jul 9, 2026
e98cd80
Batch plan: item 4+5 merged after orchestrator review (375/375 + vite…
JohnThomson Jul 9, 2026
288e405
Item 6 (join cards): add collections/getJoinCards backend endpoint
JohnThomson Jul 9, 2026
9fe1c4d
Item 6 (join cards): unit tests for CollectionChooserApi.ComputeJoinC…
JohnThomson Jul 9, 2026
8a3a011
Item 6 (join cards): replace the "Get my Team Collections" sidebar wi…
JohnThomson Jul 9, 2026
f59dc6e
Item 6 (join cards): drop orphaned XLF entries from the removed sidebar
JohnThomson Jul 9, 2026
5e572a8
Item 6 (join cards): add a storybook story for join cards
JohnThomson Jul 9, 2026
ea0adbe
Item 6 (join cards): tick checklist boxes, update status and progress…
JohnThomson Jul 9, 2026
4f74ff3
Review fix for item 6: join-card fetch degrades silently when the ser…
JohnThomson Jul 9, 2026
c44e91f
Batch plan: item 6 merged; record John decisions as items 8 (recovery…
JohnThomson Jul 9, 2026
e0526fa
Item 8: preserve drifted local content as .bloomSource before sync ov…
JohnThomson Jul 9, 2026
20821ab
GOING-LIVE: record 9 Jul decisions (safety window 7d; account-switch …
JohnThomson Jul 9, 2026
ac9418d
GOING-LIVE: subscription policy decided - cloud TCs require the same …
JohnThomson Jul 9, 2026
3d77964
Record AWSSDK.S3 bump decision: on this branch, with human web up/dow…
JohnThomson Jul 9, 2026
75de7d0
Batch plan: 4-spec E2E verification queue GREEN (items 1-6, 8 verifie…
JohnThomson Jul 9, 2026
bfa72dc
GOING-LIVE: dogfood plan decided - fresh test collections only, vario…
JohnThomson Jul 9, 2026
0598404
Progressive join (batch item 7): open cloud collections before all bo…
JohnThomson Jul 9, 2026
d20efb2
Tests for progressive join (batch item 7): queue priority, background…
JohnThomson Jul 9, 2026
d926c02
UI + string for progressive join (batch item 7): placeholder book button
JohnThomson Jul 9, 2026
0063365
Batch plan: item 7 (progressive join) code done; checkboxes ticked, p…
JohnThomson Jul 9, 2026
223dd45
Dev README: functions serve becomes a silent zombie after supabase st…
JohnThomson Jul 10, 2026
9b81c60
Bump AWSSDK.S3/Core 3.5.x to 4.0.100.3 with v4 compatibility fixes (b…
JohnThomson Jul 10, 2026
81007f1
Tick batch item 10 bump checkbox; record version delta and v4 adjustm…
JohnThomson Jul 10, 2026
75b52cf
Item 10 suites verified: tick suites checkbox, status + progress log
JohnThomson Jul 10, 2026
d488784
GOING-LIVE: AWSSDK v4 bump merged; flag BloomHarvester cross-repo bum…
JohnThomson Jul 10, 2026
b30e8bf
Add tc.checkout_book_takeover RPC for account-switch checkout takeove…
JohnThomson Jul 10, 2026
7692241
Implement account-switch behavior for cloud Team Collections (batch i…
JohnThomson Jul 10, 2026
ef9b9dc
Add non-run E2E-10 spec + tick batch item 9 (account-switch behavior)
JohnThomson Jul 10, 2026
6f43a2f
CONTRACTS v1.4: add checkout_book_takeover RPC (additive; account-swi…
JohnThomson Jul 10, 2026
d2c4695
Fix cloud TC subscription-tier check timing (task/b1-tier-timing)
JohnThomson Jul 10, 2026
9e50c81
Add unit tests pinning the cloud TC tier-timing fix
JohnThomson Jul 10, 2026
d406fe2
Log tier-timing fix in DOGFOOD-BATCH-1.md
JohnThomson Jul 10, 2026
f451aa8
Fix two live-found regressions from the last merges (post-batch E2E p…
JohnThomson Jul 10, 2026
80b333c
E2E follow-ups from the first post-batch full matrix (8/14)
JohnThomson Jul 10, 2026
7029006
Window watcher: detached spawn made powershell exit instantly - the w…
JohnThomson Jul 10, 2026
ff6c5a6
Batch plan: pause-point state for VS Code restart (3 open defects, fu…
JohnThomson Jul 10, 2026
8c9d07c
Batch log: resumed after VS Code restart; three-defect fix agent rela…
JohnThomson Jul 10, 2026
b0941db
Batch log: pause point for another VS Code restart (agent stopped pre…
JohnThomson Jul 10, 2026
20555ec
Batch log: resumed; functions serve was dead (restarted), three-defec…
JohnThomson Jul 10, 2026
4339e02
Defect 1: self-healing retry for dropped background book downloads
JohnThomson Jul 10, 2026
4819eda
Defect 3: teamCollection/capabilities is now an application-level end…
JohnThomson Jul 10, 2026
ae35b87
Defect 2: member reopen under a different account hung at startup (un…
JohnThomson Jul 10, 2026
c24af86
E2E harness: poll capabilities after relaunch instead of single-shot
JohnThomson Jul 10, 2026
59a7797
Batch log: handoff entry, e2e-4 diagnosis (staging-folder clash + ove…
JohnThomson Jul 10, 2026
c41fcfd
Merge remote-tracking branch 'origin/master' into cloud-collections
JohnThomson Jul 10, 2026
86bd9c2
Batch log: master integrated as merge (zero conflicts), pnpm accounte…
JohnThomson Jul 10, 2026
a2504e8
e2e-4 fixes: unique per-download staging folder; requeue skips only o…
JohnThomson Jul 10, 2026
b70795a
Batch log: e2e-4 download bugs verified fixed; NEW takeover-semantics…
JohnThomson Jul 10, 2026
72246c2
Preflight review fixes: per-account membership claim; machine-aware l…
JohnThomson Jul 10, 2026
24b0f5c
Batch log: preflight end-of-session state (local half complete, GitHu…
JohnThomson Jul 10, 2026
e9252d8
Batch log: draft PR 8048 created, bot gauntlet + full matrix running
JohnThomson Jul 10, 2026
d8ff5c8
Squash plan: review-grained packaging branch for the Cloud TC feature…
JohnThomson Jul 10, 2026
cee54ba
Batch log: end-of-day shutdown state (matrix 10/14 under load, bot ti…
JohnThomson Jul 10, 2026
159928f
Batch log: resumed after sleep; e2e-3 standalone PASS; bot gauntlet c…
JohnThomson Jul 11, 2026
b93d0c9
E2E queue-arrival spec fixes + Greptile review fixes (PR 8048)
JohnThomson Jul 11, 2026
6443a85
Batch log: full-matrix attempt invalid (desktop locked mid-run, 14/14…
JohnThomson Jul 11, 2026
fc204cf
Bug #0: per-collection-copy seat on cloud checkouts (John's ruling, C…
JohnThomson Jul 11, 2026
a048e92
E2E-5: wait for the initial share's v1 commit before killing Alice
JohnThomson Jul 11, 2026
ac31aa1
Merge origin/master into cloud-collections (RAB interface language + …
JohnThomson Jul 11, 2026
e782978
Prettier formatting for supabase/functions (hook-authoritative)
JohnThomson Jul 11, 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: 2 additions & 0 deletions .github/skills/xlf-strings/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ After the `<note>ID: ...</note>` line, add a **second `<note>`** whenever a tran

The note should state: what UI element it labels, where it appears in the UI, and any constraints (e.g. "appears mid-sentence, should be lowercase", "step N of M in X instructions", "'Bloom' is a product name and must not be translated", "{0} is replaced with a count").

**Never put a double hyphen (`--`) inside `<note>` text.** L10NSharp's XLIFF reader routes note content through XML-comment parsing, and `--` in a comment is illegal XML — Bloom then crashes at startup with "An XML comment cannot contain '--'" while loading localization (found 8 Jul 2026; it killed every launch). Use a period, semicolon, or single hyphen instead. (`--` in `<source>` text is fine.)

Example with context note:
```xml
<trans-unit id="ImageLibrary.PixabayStep4" translate="no">
Expand Down
180 changes: 180 additions & 0 deletions Design/CloudTeamCollections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# Cloud Team Collections: S3 + Supabase design

Status: **design complete, implementation not started** (2 July 2026).
Interactive review version of this document (with diagrams and the full narrative):
https://claude.ai/code/artifact/14157962-d8e4-4c3f-afa7-34c49ed29e1a
Work breakdown: [CloudTeamCollections/IMPLEMENTATION.md](CloudTeamCollections/IMPLEMENTATION.md) ·
API contracts: [CloudTeamCollections/CONTRACTS.md](CloudTeamCollections/CONTRACTS.md)

## Motivation

Team Collections today wraps a shared Dropbox/LAN folder. Chronic problems: Dropbox is hard
and expensive for our users to set up; Bloom can never truly know sync status; and a
third-party sync agent underneath us creates a long tail of races (conflicted-copy files,
two-phase delivery, partial downloads that look corrupt) that the code and tests spend
enormous effort taming. Replacement: a central SIL-hosted backend — Supabase Postgres as the
authoritative database (locks, membership, current-version manifests, history events), one S3
bucket with a prefix per collection for book content, and sharing via an approved-accounts
model. The check-in/check-out editorial model is preserved.

## Requirements (decided)

1. Zero third-party setup for users; only a Bloom (BloomLibrary) sign-in.
2. Central SIL-hosted S3; per-collection prefixes; access brokered per-operation (STS).
3. Check-in/check-out preserved; offline editing of checked-out books always works.
4. Identity = BloomLibrary Firebase account (real auth, not self-declared email).
5. Sharing v1 = **approved accounts**: admin lists emails (+ role Admin/Member); an approved
person signs in anywhere, asks "Get my Team Collections", pulls a collection down.
Invite links/codes, `bloom://` deep links, landing page, Mailgun emails: all deferred to v2.
6. **Send/Receive model** (modal in v1): explicit transfers with progress; no ambient content
copying. Metadata (locks, version numbers) syncs continuously and cheaply; the UI always
knows "checked out to Sara" / "v12 exists, you have v10" without moving bytes.
7. No secondary local repo copy. Transfers stage in temp dirs and swap atomically per book —
never new HTML with stale images.
8. Per-file delta transfers, SHA-256 verified, both directions.
9. **No content retention**: replaced files are not kept anywhere; no restore. The history
*log* (who/when/comment/incidents) is kept — it is metadata. S3 object versioning stays ON
purely as a transactional safety device (crashed Send harmless; torn reads impossible),
with noncurrent versions auto-deleted after ~7 days.
10. Work is never silently lost: whenever the repo must win over local work, that work is
saved as a `.bloomSource` in a local **Lost & Found** folder AND recorded as a server-side
incident event admins can see.
11. Coexists indefinitely with folder/Dropbox TC (second backend behind the same abstraction).
No auto-migration in v1: un-team (delete link file), then enable cloud sharing.
12. Subscriptions untouched: existing client-side gate only; the server has no tier/quota logic.
13. Experimental flag until GA (plus the existing feature gate), like the current TC.

## Architecture

- **Bloom desktop (C#)**: `CloudTeamCollection` — second subclass of the existing abstract
`TeamCollection` (src/BloomExe/TeamCollection/TeamCollection.cs) — plus support classes
(`CloudCollectionClient`, `CloudRepoCache`, `CloudBookTransfer`, `BookVersionManifest`,
`CloudCollectionMonitor`, `CloudAuth`, `CloudJoinFlow`), a new `SharingApi`, and reuse of
`BloomS3Client` (session credentials + TransferUtility), the WebSocket progress harness, and
nearly all existing TC UI.
- **Supabase** (schema `tc`): tables `collections`, `members` (the approved-accounts table;
unclaimed rows have null user_id), `books` (with the authoritative lock columns and
`deleted_at` tombstone), `versions` (metadata row per check-in), `version_files` (the
CURRENT manifest: path → sha256, size, s3_version_id; superseded rows pruned at commit),
`collection_file_groups`/`collection_group_files`, `color_palette_entries` (union merge =
`insert … on conflict do nothing`), `events` (history + realtime source + polling cursor;
numeric types match `BookHistoryEventType`, extended with incident types), and
`checkin_transactions`. RLS on everything; no direct writes to books/versions — state
transitions go through RPCs/edge functions.
- **S3**: bucket per environment (`bloom-teams-production`/`-sandbox`), versioning ON,
lifecycle = abort-multipart 7d + expire noncurrent versions ~7d. Layout:
`tc/{collectionId}/books/{bookInstanceId}/{relativePath}` (+ `.manifest.json` current-state
backup per book; `tc/{cid}/collectionFiles/{group}/...`). Folder keyed by instance id →
rename is a DB row update. Existing buckets/credentials for publishing are untouched; cloud
collections never use embedded keys.
- **Access brokering**: STS temporary credentials from edge functions, scoped by inline
session policy (write: the one book being sent, only while its transaction is open; read:
the collection prefix incl. `GetObjectVersion`). Uploads carry `x-amz-checksum-sha256`;
checkin-finish verifies before commit.
- **Checkout** = conditional UPDATE (`WHERE locked_by IS NULL OR locked_by = me`) — race-free.
Locks never auto-expire; "Force Unlock" (label decided) is a distinct audited RPC.
- **Send** = checkin-start (diff manifest → transaction + changed paths + STS creds) →
parallel PUT changed files → checkin-finish (verify, one DB tx: version row + manifest +
lock release + events; the commit is the atomicity point). Crash mid-Send: nothing
committed, resumable 48h, no partial state visible ever.
- **New books** (first-class): checkin-start with `bookId:null` creates the row locked to
caller **with no current version — invisible to teammates** until first commit. Crash → no
phantom; expired transaction reaps. Same-name race → NameConflict → existing "name2"
resolution; duplicate instance id → existing id-conflict flow.
- **Receive** = `get_collection_state(since)` → reuse of the existing `SyncAtStartup`
reconciliation → download changed files by pinned (path, s3VersionId) into temp → atomic
swap per book.
- **Realtime**: one private broadcast channel per collection driven by an events-table
trigger; clients keep a `last_seen_event_id` cursor; `get_changes(since)` is both reconnect
catch-up and the 60s polling fallback (polling ships first; realtime is an optimization).
- **Auth** (DECIDED 8 Jul 2026: **Option A** — Supabase third-party Firebase auth; brief was
grounded in the BloomLibrary2 + bloom-parse-server code): the login page forwards the
Firebase ID+refresh tokens it already holds (~5 lines in BloomLibrary2 `src/editor.ts`),
plus one NEW small Firebase Admin cloud function adding the static `role:"authenticated"`
claim (+ backfill; no claims infra exists today). Rejected alternatives: B = exchange the
legacy Parse session token (welds us to the server being decommissioned); C = hand-validate
Firebase JWTs per the stale `bloom-parse-server/supabase/` docs. `CloudAuth` isolates the
choice. Claiming an approval requires `email_verified` (all BloomLibrary accounts are
verified — the existing parse adapter already enforces this). Go-live steps:
`CloudTeamCollections/GOING-LIVE.md` Phase 3.
- **Identity/account rules**: account email is the identity in cloud TCs (server stamps lock
identity from the token; client sends only machine name). Sign-out/in as the same account
is always safe. Switching accounts with unsent checked-out changes is **blocked** with
explicit choices (Send first, or preserve `.bloomSource` + release locally); the server
lock stays with the original account. Nothing is ever discarded implicitly.
- **History tab** (cloud TCs): reads server events (cached locally for offline display);
the SQLite-in-book mechanism remains for folder TCs.
- **Unicode**: NFC normalization for names and paths everywhere.

## Client integration: base-class changes (all folder-backend-behavior-preserving)

1. Backend factory: `TeamCollectionLink` parses `TeamCollectionLink.txt` (folder path or
`cloud://sil.bloom/collection/<id>`); factory replaces the three hardcoded
`new FolderTeamCollection(...)` sites in `TeamCollectionManager`. Old Bloom versions read
the cloud link as a folder path and land in the safe Disconnected state.
2. Lock seams: `protected virtual TryLockInRepo/UnlockInRepo` (folder keeps read-modify-write;
cloud is one conditional RPC).
3. Status-write discipline: cloud `WriteBookStatusJsonToRepo` diff-dispatches to the narrowest
RPC; audit the ~10 `WriteBookStatus` callers.
4. Capability flags: `SupportsVersionHistory`, `SupportsSharingUi`, `RequiresSignIn` — UI
branches on capability, never on concrete type.

`SyncAtStartup`, clobber/conflict logic, message log, local status files, `DisconnectedTeamCollection`
are reused unchanged. `CloudRepoCache` (thread-safe, persisted snapshot + event cursor) makes
the synchronous status calls cheap and hydrates Disconnected mode.

## UI changes (summary)

Settings gains the cloud share path + a Sharing panel (approved-accounts list) replacing the
free-text admin list for cloud TCs; the cloud create dialog is sign-in → confirm immutable
name → initial Send (no folder chooser, no restart). Collection chooser gains "Get my Team
Collections". Collection tab: same status chip (now live/precise), status dialog gains
"Receive Updates" (successor of Reload Collection) and "Send All", a Share button appears, the
per-book panel carries over nearly unchanged (+ signedOut / updatesAvailable states). All new
strings via the XLF pipeline with Send/Receive terminology.

## Edge cases

The full ~135-case disposition matrix (every case in src/BloomTests/TeamCollection and the
TeamCollection.cs decision logic → impossible-now / changed / unchanged / disallowed, plus 15
new cloud-specific cases) lives in the review artifact, Level 4, and drives the test plan.
Headline: most Dropbox-era cases exist only because Dropbox is not transactional and become
structurally impossible; all offline-work-vs-moved-on-repo collisions converge on the unified
`.bloomSource` + incident-event recovery.

## Test plan (summary)

- C# unit suites (src/BloomTests/TeamCollection/Cloud/): link/factory, lock seams, cache,
manifest, transfer, member-by-member backend tests, the ported SyncAtStartup matrix
(asserting `.bloomSource` + incident events), monitor, auth, sharing API.
- Server: pgTAP (RLS matrix, checkout concurrency, claiming requires verified email,
last-admin guard, cursor, tombstone/undelete, name uniqueness) + Deno tests per edge function.
- Component (vitest browser mode): SharingPanel, chooser, status panel states, create dialog.
- E2E (Playwright over CDP driving real Bloom.exe; local Supabase + MinIO/sandbox):
E2E-1 create · E2E-2 two-instance collaboration · E2E-3 checkout contention ·
E2E-4 forced check-in recovery (`.bloomSource` + incident) · E2E-5 approved accounts across
two machines · E2E-6 kill-mid-Send/resume · E2E-7 un-team adoption ·
E2E-8 Receive-during-Send coherence (mandated) · E2E-9 new-book lifecycle/phantom/name-race ·
E2E-10 account-switch safety.
- Standing gate: the entire existing folder-TC suite passes unchanged on every branch.

## Provisioning

Supabase CLI (migrations in `supabase/` in this repo — decided location; local dev/CI via
`supabase start`) + AWS CLI/Terraform script creating the versioned bucket, lifecycle rules,
`bloom-teams-broker` role, and the assume-role-only IAM user for edge functions. Docker for
local Supabase + MinIO. Two hosted Supabase projects (production, sandbox).

## Roadmap

M0 enablers (1–2wk) → M1 create + read-only + join-by-listing + polling + modal Receive
(4–6wk) → M2 checkout + Send + force-unlock + `.bloomSource` recovery (4–6wk) → M3 sharing
panel + Get-my-Team-Collections (2–3wk) → M4 realtime + reconnect hardening (2–3wk) →
M5 adoption polish + server-fed history tab + dogfood (2–3wk). Build is orchestrated per
[CloudTeamCollections/IMPLEMENTATION.md](CloudTeamCollections/IMPLEMENTATION.md).

## Open items

- Auth option A/B/C: colleague decision pending (brief in the artifact).
- Safety-window duration: recorded as 7 days ("option one" reading — if "one day" was meant,
transaction lifetime shrinks to ~12h; invariant: transaction lifetime < expiry floor).
Loading