Skip to content

Refactor BaseNodeViewer to use SharedNodeStore for all database operations#238

Merged
malibio merged 2 commits into
mainfrom
feature/issue-237-refactor-basenodeviewer-sharedstore
Oct 12, 2025
Merged

Refactor BaseNodeViewer to use SharedNodeStore for all database operations#238
malibio merged 2 commits into
mainfrom
feature/issue-237-refactor-basenodeviewer-sharedstore

Conversation

@malibio

@malibio malibio commented Oct 11, 2025

Copy link
Copy Markdown
Collaborator

Closes #237

malibio and others added 2 commits October 12, 2025 01:32
…tions (#237)

## Summary

Eliminates dual persistence paths by routing all BaseNodeViewer database operations through SharedNodeStore, resolving conflicts and race conditions while preserving sophisticated FOREIGN KEY coordination logic.

## Changes

### SharedNodeStore Enhancements
- Added `pendingContentSaves` tracking for FOREIGN KEY coordination
- Implemented `waitForNodeSaves()` with timeout and grace period handling
- Added `ensureAncestorChainPersisted()` for recursive placeholder parent persistence
- Added `validateNodeReferences()` for FOREIGN KEY validation before structural updates
- Added `updateStructuralChangesValidated()` for serial processing with validation
- Added `loadChildrenForParent()` wrapping database queries
- Implemented hybrid debouncing: 500ms for content, immediate for structural updates
- Added placeholder-awareness: skips persistence when `isPlaceholder === true`

### BaseNodeViewer Refactoring
- Replaced all direct `databaseService` calls with `sharedNodeStore` methods
- Refactored `waitForNodeSavesIfPending()` to delegate to SharedNodeStore
- Refactored `ensureAncestorsPersisted()` to delegate with placeholder checker callback
- Updated content save watcher to use `saveNodeImmediately()` and `updateNodeContentDebounced()`
- Updated deletion watcher to use `sharedNodeStore.deleteNode()`
- Updated structural watcher to use `updateStructuralChangesValidated()` with proper coordination
- Refactored `loadChildrenForParent()` to use SharedNodeStore method
- Removed `saveNode()` and `debounceSave()` functions (replaced by SharedNodeStore)
- Simplified `saveHierarchyChange()` to use SharedNodeStore
- Removed `queueDatabaseWrite` import (no longer needed)

### Architecture
- **BaseNodeViewer** remains the "conductor": decides WHEN and WHAT ORDER to persist
- **SharedNodeStore** is the "performer": executes database operations with coordination
- Preserved all FOREIGN KEY logic: waiting for saves, validating references, ordering operations
- Maintained sophisticated save/delete coordination for data integrity

## Test Notes

All quality checks pass. Some pre-existing test failures in node-ordering tests are unrelated to this refactoring (tests use service layer directly, not BaseNodeViewer).

## Related Issues

Closes #237

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
## Changes Implemented

### 1. Component Unmount Safety (🟡 Important)
- Added `isDestroyed` flag to BaseNodeViewer to prevent writes after unmount
- Checks flag before all save operations in content watcher
- Prevents race conditions and stale writes

### 2. Grace Period Logic Fix (🟡 Important)
- Fixed `waitForNodeSaves()` to properly detect in-flight vs failed saves
- Now checks if promise actually rejected vs still pending
- Prevents false positive failures for saves that complete during grace period

### 3. Single Source of Truth (🟢 Nice-to-Have)
- Added `hasPendingSave()` accessor method to SharedNodeStore
- Eliminates dual promise tracking between components
- Provides clean API for checking pending save status

### 4. Error Event Construction (🟢 Nice-to-Have)
- Extracted `buildPersistenceErrorEvent()` helper function
- Reduces code duplication in error handling paths
- Improves maintainability and consistency

### 5. Comprehensive Test Coverage (🟡 Important)
- Added 34 unit tests for 7 new SharedNodeStore methods:
  - `loadChildrenForParent()` (3 tests)
  - `updateNodeContentDebounced()` (4 tests)
  - `saveNodeImmediately()` (5 tests)
  - `hasPendingSave()` (3 tests)
  - `waitForNodeSaves()` (5 tests)
  - `ensureAncestorChainPersisted()` (4 tests)
  - `validateNodeReferences()` (5 tests)
  - `updateStructuralChangesValidated()` (5 tests)
- All 65 tests passing (100% pass rate)
- Tests cover FOREIGN KEY coordination, debouncing, validation, error handling

## Test Results
✅ 65/65 tests passing
✅ quality:fix passes with 0 errors, 0 warnings
✅ All lint issues resolved

## Files Modified
- `packages/desktop-app/src/lib/design/components/base-node-viewer.svelte`
  - Added isDestroyed flag and checks
  - Added buildPersistenceErrorEvent() helper
- `packages/desktop-app/src/lib/services/shared-node-store.ts`
  - Fixed waitForNodeSaves() grace period logic
  - Added hasPendingSave() method
- `packages/desktop-app/src/tests/services/shared-node-store.test.ts`
  - Added 34 comprehensive unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@malibio

malibio commented Oct 11, 2025

Copy link
Copy Markdown
Collaborator Author

Code Review Recommendations Addressed ✅

I've completed all the recommendations from the pragmatic code review. Here's what was implemented:

🟡 Important Issues Fixed

1. Component Unmount Race Condition

Issue: Async save operations could complete after component unmounts, causing stale writes
Fix:

  • Added isDestroyed flag set in onDestroy()
  • Added checks before all save operations in content watcher
  • Prevents writes after component cleanup

Files: base-node-viewer.svelte:55-56, 130-136, 160

2. Grace Period Logic False Positives

Issue: waitForNodeSaves() incorrectly marked in-flight saves as failed
Fix:

  • Changed grace period logic to actually await promises
  • Now detects if promise rejected vs still pending
  • Prevents false failures for saves completing during grace period

Files: shared-node-store.ts:651-665

3. Comprehensive Test Coverage

Issue: 7 new SharedNodeStore methods had no unit tests
Fix: Added 34 comprehensive unit tests covering:

  • loadChildrenForParent() - 3 tests
  • updateNodeContentDebounced() - 4 tests
  • saveNodeImmediately() - 5 tests
  • hasPendingSave() - 3 tests
  • waitForNodeSaves() - 5 tests
  • ensureAncestorChainPersisted() - 4 tests
  • validateNodeReferences() - 5 tests
  • updateStructuralChangesValidated() - 5 tests

All tests cover complex business logic: FOREIGN KEY coordination, debouncing, validation, error handling

Files: shared-node-store.test.ts:518-1260

🟢 Nice-to-Have Improvements

4. Single Source of Truth

Issue: Dual promise tracking between BaseNodeViewer and SharedNodeStore
Fix: Added hasPendingSave() accessor method to SharedNodeStore

Files: shared-node-store.ts:612-614

5. Error Event Construction Helper

Issue: Duplicated error event construction logic
Fix: Extracted buildPersistenceErrorEvent() helper function

Files: base-node-viewer.svelte:99-141


Test Results

65/65 tests passing (100% pass rate)
quality:fix passes with 0 errors, 0 warnings
✅ All linting issues resolved

Impact

  • Eliminated memory leak risk from unmounted components
  • Fixed grace period false positives
  • 100% test coverage for new SharedNodeStore methods
  • Cleaner, more maintainable error handling
  • Single source of truth for pending save status

Ready for final review and merge! 🚀

@malibio
malibio merged commit 4110f70 into main Oct 12, 2025
@malibio
malibio deleted the feature/issue-237-refactor-basenodeviewer-sharedstore branch October 12, 2025 00:01
malibio added a commit that referenced this pull request Feb 4, 2026
…tions (#238)

* Refactor BaseNodeViewer to use SharedNodeStore for all database operations (#237)

## Summary

Eliminates dual persistence paths by routing all BaseNodeViewer database operations through SharedNodeStore, resolving conflicts and race conditions while preserving sophisticated FOREIGN KEY coordination logic.

## Changes

### SharedNodeStore Enhancements
- Added `pendingContentSaves` tracking for FOREIGN KEY coordination
- Implemented `waitForNodeSaves()` with timeout and grace period handling
- Added `ensureAncestorChainPersisted()` for recursive placeholder parent persistence
- Added `validateNodeReferences()` for FOREIGN KEY validation before structural updates
- Added `updateStructuralChangesValidated()` for serial processing with validation
- Added `loadChildrenForParent()` wrapping database queries
- Implemented hybrid debouncing: 500ms for content, immediate for structural updates
- Added placeholder-awareness: skips persistence when `isPlaceholder === true`

### BaseNodeViewer Refactoring
- Replaced all direct `databaseService` calls with `sharedNodeStore` methods
- Refactored `waitForNodeSavesIfPending()` to delegate to SharedNodeStore
- Refactored `ensureAncestorsPersisted()` to delegate with placeholder checker callback
- Updated content save watcher to use `saveNodeImmediately()` and `updateNodeContentDebounced()`
- Updated deletion watcher to use `sharedNodeStore.deleteNode()`
- Updated structural watcher to use `updateStructuralChangesValidated()` with proper coordination
- Refactored `loadChildrenForParent()` to use SharedNodeStore method
- Removed `saveNode()` and `debounceSave()` functions (replaced by SharedNodeStore)
- Simplified `saveHierarchyChange()` to use SharedNodeStore
- Removed `queueDatabaseWrite` import (no longer needed)

### Architecture
- **BaseNodeViewer** remains the "conductor": decides WHEN and WHAT ORDER to persist
- **SharedNodeStore** is the "performer": executes database operations with coordination
- Preserved all FOREIGN KEY logic: waiting for saves, validating references, ordering operations
- Maintained sophisticated save/delete coordination for data integrity

## Test Notes

All quality checks pass. Some pre-existing test failures in node-ordering tests are unrelated to this refactoring (tests use service layer directly, not BaseNodeViewer).

## Related Issues

Closes #237

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address code review recommendations for Issue #237

## Changes Implemented

### 1. Component Unmount Safety (🟡 Important)
- Added `isDestroyed` flag to BaseNodeViewer to prevent writes after unmount
- Checks flag before all save operations in content watcher
- Prevents race conditions and stale writes

### 2. Grace Period Logic Fix (🟡 Important)
- Fixed `waitForNodeSaves()` to properly detect in-flight vs failed saves
- Now checks if promise actually rejected vs still pending
- Prevents false positive failures for saves that complete during grace period

### 3. Single Source of Truth (🟢 Nice-to-Have)
- Added `hasPendingSave()` accessor method to SharedNodeStore
- Eliminates dual promise tracking between components
- Provides clean API for checking pending save status

### 4. Error Event Construction (🟢 Nice-to-Have)
- Extracted `buildPersistenceErrorEvent()` helper function
- Reduces code duplication in error handling paths
- Improves maintainability and consistency

### 5. Comprehensive Test Coverage (🟡 Important)
- Added 34 unit tests for 7 new SharedNodeStore methods:
  - `loadChildrenForParent()` (3 tests)
  - `updateNodeContentDebounced()` (4 tests)
  - `saveNodeImmediately()` (5 tests)
  - `hasPendingSave()` (3 tests)
  - `waitForNodeSaves()` (5 tests)
  - `ensureAncestorChainPersisted()` (4 tests)
  - `validateNodeReferences()` (5 tests)
  - `updateStructuralChangesValidated()` (5 tests)
- All 65 tests passing (100% pass rate)
- Tests cover FOREIGN KEY coordination, debouncing, validation, error handling

## Test Results
✅ 65/65 tests passing
✅ quality:fix passes with 0 errors, 0 warnings
✅ All lint issues resolved

## Files Modified
- `packages/desktop-app/src/lib/design/components/base-node-viewer.svelte`
  - Added isDestroyed flag and checks
  - Added buildPersistenceErrorEvent() helper
- `packages/desktop-app/src/lib/services/shared-node-store.ts`
  - Fixed waitForNodeSaves() grace period logic
  - Added hasPendingSave() method
- `packages/desktop-app/src/tests/services/shared-node-store.test.ts`
  - Added 34 comprehensive unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
malibio added a commit that referenced this pull request Feb 5, 2026
…tions (#238)

* Refactor BaseNodeViewer to use SharedNodeStore for all database operations (#237)

## Summary

Eliminates dual persistence paths by routing all BaseNodeViewer database operations through SharedNodeStore, resolving conflicts and race conditions while preserving sophisticated FOREIGN KEY coordination logic.

## Changes

### SharedNodeStore Enhancements
- Added `pendingContentSaves` tracking for FOREIGN KEY coordination
- Implemented `waitForNodeSaves()` with timeout and grace period handling
- Added `ensureAncestorChainPersisted()` for recursive placeholder parent persistence
- Added `validateNodeReferences()` for FOREIGN KEY validation before structural updates
- Added `updateStructuralChangesValidated()` for serial processing with validation
- Added `loadChildrenForParent()` wrapping database queries
- Implemented hybrid debouncing: 500ms for content, immediate for structural updates
- Added placeholder-awareness: skips persistence when `isPlaceholder === true`

### BaseNodeViewer Refactoring
- Replaced all direct `databaseService` calls with `sharedNodeStore` methods
- Refactored `waitForNodeSavesIfPending()` to delegate to SharedNodeStore
- Refactored `ensureAncestorsPersisted()` to delegate with placeholder checker callback
- Updated content save watcher to use `saveNodeImmediately()` and `updateNodeContentDebounced()`
- Updated deletion watcher to use `sharedNodeStore.deleteNode()`
- Updated structural watcher to use `updateStructuralChangesValidated()` with proper coordination
- Refactored `loadChildrenForParent()` to use SharedNodeStore method
- Removed `saveNode()` and `debounceSave()` functions (replaced by SharedNodeStore)
- Simplified `saveHierarchyChange()` to use SharedNodeStore
- Removed `queueDatabaseWrite` import (no longer needed)

### Architecture
- **BaseNodeViewer** remains the "conductor": decides WHEN and WHAT ORDER to persist
- **SharedNodeStore** is the "performer": executes database operations with coordination
- Preserved all FOREIGN KEY logic: waiting for saves, validating references, ordering operations
- Maintained sophisticated save/delete coordination for data integrity

## Test Notes

All quality checks pass. Some pre-existing test failures in node-ordering tests are unrelated to this refactoring (tests use service layer directly, not BaseNodeViewer).

## Related Issues

Closes #237

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address code review recommendations for Issue #237

## Changes Implemented

### 1. Component Unmount Safety (🟡 Important)
- Added `isDestroyed` flag to BaseNodeViewer to prevent writes after unmount
- Checks flag before all save operations in content watcher
- Prevents race conditions and stale writes

### 2. Grace Period Logic Fix (🟡 Important)
- Fixed `waitForNodeSaves()` to properly detect in-flight vs failed saves
- Now checks if promise actually rejected vs still pending
- Prevents false positive failures for saves that complete during grace period

### 3. Single Source of Truth (🟢 Nice-to-Have)
- Added `hasPendingSave()` accessor method to SharedNodeStore
- Eliminates dual promise tracking between components
- Provides clean API for checking pending save status

### 4. Error Event Construction (🟢 Nice-to-Have)
- Extracted `buildPersistenceErrorEvent()` helper function
- Reduces code duplication in error handling paths
- Improves maintainability and consistency

### 5. Comprehensive Test Coverage (🟡 Important)
- Added 34 unit tests for 7 new SharedNodeStore methods:
  - `loadChildrenForParent()` (3 tests)
  - `updateNodeContentDebounced()` (4 tests)
  - `saveNodeImmediately()` (5 tests)
  - `hasPendingSave()` (3 tests)
  - `waitForNodeSaves()` (5 tests)
  - `ensureAncestorChainPersisted()` (4 tests)
  - `validateNodeReferences()` (5 tests)
  - `updateStructuralChangesValidated()` (5 tests)
- All 65 tests passing (100% pass rate)
- Tests cover FOREIGN KEY coordination, debouncing, validation, error handling

## Test Results
✅ 65/65 tests passing
✅ quality:fix passes with 0 errors, 0 warnings
✅ All lint issues resolved

## Files Modified
- `packages/desktop-app/src/lib/design/components/base-node-viewer.svelte`
  - Added isDestroyed flag and checks
  - Added buildPersistenceErrorEvent() helper
- `packages/desktop-app/src/lib/services/shared-node-store.ts`
  - Fixed waitForNodeSaves() grace period logic
  - Added hasPendingSave() method
- `packages/desktop-app/src/tests/services/shared-node-store.test.ts`
  - Added 34 comprehensive unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
malibio added a commit that referenced this pull request Feb 26, 2026
…tions (#238)

* Refactor BaseNodeViewer to use SharedNodeStore for all database operations (#237)

## Summary

Eliminates dual persistence paths by routing all BaseNodeViewer database operations through SharedNodeStore, resolving conflicts and race conditions while preserving sophisticated FOREIGN KEY coordination logic.

## Changes

### SharedNodeStore Enhancements
- Added `pendingContentSaves` tracking for FOREIGN KEY coordination
- Implemented `waitForNodeSaves()` with timeout and grace period handling
- Added `ensureAncestorChainPersisted()` for recursive placeholder parent persistence
- Added `validateNodeReferences()` for FOREIGN KEY validation before structural updates
- Added `updateStructuralChangesValidated()` for serial processing with validation
- Added `loadChildrenForParent()` wrapping database queries
- Implemented hybrid debouncing: 500ms for content, immediate for structural updates
- Added placeholder-awareness: skips persistence when `isPlaceholder === true`

### BaseNodeViewer Refactoring
- Replaced all direct `databaseService` calls with `sharedNodeStore` methods
- Refactored `waitForNodeSavesIfPending()` to delegate to SharedNodeStore
- Refactored `ensureAncestorsPersisted()` to delegate with placeholder checker callback
- Updated content save watcher to use `saveNodeImmediately()` and `updateNodeContentDebounced()`
- Updated deletion watcher to use `sharedNodeStore.deleteNode()`
- Updated structural watcher to use `updateStructuralChangesValidated()` with proper coordination
- Refactored `loadChildrenForParent()` to use SharedNodeStore method
- Removed `saveNode()` and `debounceSave()` functions (replaced by SharedNodeStore)
- Simplified `saveHierarchyChange()` to use SharedNodeStore
- Removed `queueDatabaseWrite` import (no longer needed)

### Architecture
- **BaseNodeViewer** remains the "conductor": decides WHEN and WHAT ORDER to persist
- **SharedNodeStore** is the "performer": executes database operations with coordination
- Preserved all FOREIGN KEY logic: waiting for saves, validating references, ordering operations
- Maintained sophisticated save/delete coordination for data integrity

## Test Notes

All quality checks pass. Some pre-existing test failures in node-ordering tests are unrelated to this refactoring (tests use service layer directly, not BaseNodeViewer).

## Related Issues

Closes #237

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address code review recommendations for Issue #237

## Changes Implemented

### 1. Component Unmount Safety (🟡 Important)
- Added `isDestroyed` flag to BaseNodeViewer to prevent writes after unmount
- Checks flag before all save operations in content watcher
- Prevents race conditions and stale writes

### 2. Grace Period Logic Fix (🟡 Important)
- Fixed `waitForNodeSaves()` to properly detect in-flight vs failed saves
- Now checks if promise actually rejected vs still pending
- Prevents false positive failures for saves that complete during grace period

### 3. Single Source of Truth (🟢 Nice-to-Have)
- Added `hasPendingSave()` accessor method to SharedNodeStore
- Eliminates dual promise tracking between components
- Provides clean API for checking pending save status

### 4. Error Event Construction (🟢 Nice-to-Have)
- Extracted `buildPersistenceErrorEvent()` helper function
- Reduces code duplication in error handling paths
- Improves maintainability and consistency

### 5. Comprehensive Test Coverage (🟡 Important)
- Added 34 unit tests for 7 new SharedNodeStore methods:
  - `loadChildrenForParent()` (3 tests)
  - `updateNodeContentDebounced()` (4 tests)
  - `saveNodeImmediately()` (5 tests)
  - `hasPendingSave()` (3 tests)
  - `waitForNodeSaves()` (5 tests)
  - `ensureAncestorChainPersisted()` (4 tests)
  - `validateNodeReferences()` (5 tests)
  - `updateStructuralChangesValidated()` (5 tests)
- All 65 tests passing (100% pass rate)
- Tests cover FOREIGN KEY coordination, debouncing, validation, error handling

## Test Results
✅ 65/65 tests passing
✅ quality:fix passes with 0 errors, 0 warnings
✅ All lint issues resolved

## Files Modified
- `packages/desktop-app/src/lib/design/components/base-node-viewer.svelte`
  - Added isDestroyed flag and checks
  - Added buildPersistenceErrorEvent() helper
- `packages/desktop-app/src/lib/services/shared-node-store.ts`
  - Fixed waitForNodeSaves() grace period logic
  - Added hasPendingSave() method
- `packages/desktop-app/src/tests/services/shared-node-store.test.ts`
  - Added 34 comprehensive unit tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
mstomar125 pushed a commit to mstomar125/nodespace-core that referenced this pull request Jul 2, 2026
…paceAI#238 review)

Address the S1 review: only the read path (loadCollection / ensureIdentity) was
Pro-gated; the 9 mutations called the pro_* commands unconditionally, breaking
the store's own "every method is inert in community mode" contract — and
acceptInvite / requestJoin are the S5 onboarding entry points.

- Void mutations early-return in community mode; the value-returning
  createInvite / acceptInvite / requestJoin throw via a requirePro() guard (never
  a fake-success value) so none reach the service when tier !== 'pro'.
- Test pins the invariant: a void mutation no-ops and the value-returning ones
  throw, none touching the service, when isPro === false.

Also from review (non-blocking):
- ensureIdentity retries while person_id is empty, so a mid-session identity bind
  is picked up instead of leaving currentUserRole null all session.
- loadCollection commits the roster before the admin-only invite/request
  listings, so a listing failure no longer discards an already-fetched roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
mstomar125 added a commit that referenced this pull request Jul 2, 2026
…238) (#1473)

* Add membership service + store foundations for the Collaboration UI (#238)

Groundwork (slice S1) for the collection-membership UI on top of the complete
#143 backend. No visible surface yet — this is the service + reactive store the
Collaboration view (S3/S4) and onboarding inbox (S5) build on.

- membership-service.ts: typed wrappers over the eight pro_* membership commands
  plus S2's three (pro_list_invites / pro_list_requests / pro_revoke_invite) and
  pro_current_person. Maps the commands' snake_case DTOs to camelCase interfaces
  at the boundary so the rest of the frontend never sees the wire shape.
- membership.svelte.ts: a Svelte 5 runes store caching per-collection roster +
  pending invites/requests + the caller's own identity. Derives
  currentUserRole(collectionId) by matching the caller's person id against the
  roster, so admin controls gate correctly; only fetches the admin-gated
  invite/request listings when the caller is an admin. Mutations refresh the
  affected collection. Pro-gated: every method is inert when
  proSync.tier !== 'pro', so the community build is behaviorally unchanged.

Tests: 16 new (service arg/mapping + store role-derivation, admin gating,
community-inert, mutation refresh, reset).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Enforce community-inert contract on membership store mutations (#238 review)

Address the S1 review: only the read path (loadCollection / ensureIdentity) was
Pro-gated; the 9 mutations called the pro_* commands unconditionally, breaking
the store's own "every method is inert in community mode" contract — and
acceptInvite / requestJoin are the S5 onboarding entry points.

- Void mutations early-return in community mode; the value-returning
  createInvite / acceptInvite / requestJoin throw via a requirePro() guard (never
  a fake-success value) so none reach the service when tier !== 'pro'.
- Test pins the invariant: a void mutation no-ops and the value-returning ones
  throw, none touching the service, when isPro === false.

Also from review (non-blocking):
- ensureIdentity retries while person_id is empty, so a mid-session identity bind
  is picked up instead of leaving currentUserRole null all session.
- loadCollection commits the roster before the admin-only invite/request
  listings, so a listing failure no longer discards an already-fetched roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Mayank  Tomar <mayanktomar@Michaels-Mac-mini.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

Refactor BaseNodeViewer to use SharedNodeStore for all database operations

1 participant