Commit Graph

216 Commits

Author SHA1 Message Date
Jeff Emmett 2ecee5b2e7 feat(auth): cross-subdomain username hint for passkey SSO
Adds a non-HttpOnly `rspace_hint` cookie scoped to .rspace.online carrying
only the public username (+ optional displayName). No JWT, session, or
credential crosses origins — WebAuthn RP ID rspace.online still drives
the actual ceremony, so moving between space subdomains requires a single
passkey tap instead of re-registering an account.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:05:07 -04:00
Jeff Emmett 6f8d938e1f fix(presence): keep peers online across rApp navigation in same space
- Drop beforeunload leave broadcast — was flashing users offline during
  intra-space page nav between rApps
- Heartbeat 10s → 5s; GC stale threshold 15s → 12s
- Presence payload now carries userId; overlay keys peer map by userId
  so reconnects with a new WS peerId map back to the same row
- uniquePeers() prefers entries with module/context metadata so the panel
  shows which rApp a peer is in, even alongside cursor-only awareness
2026-04-17 11:23:50 -04:00
Jeff Emmett cfe060dc61 fix: invite UX — hide disabled modules, resolve usernames, show invites list, require userId on claim
- rApp dropdown no longer shows a "Manage rApps" panel for disabled modules.
  Enable/disable lives in Edit Space → Modules only.
- /api/internal/user-email/:userId now resolves by id OR did (real did🔑z6Mk…
  or legacy synthetic did🔑<32-char id prefix>), so Edit Space members list
  shows display names instead of raw DIDs.
- /api/spaces/:slug/invites admin check now accepts ownerDID stored as either
  raw userId or did🔑. Routes the list through a new internal endpoint on
  encryptid so Automerge-owned spaces without a space_members row still work.
- /join page registration payload was missing userId, causing every invite
  claim to fail with "Missing required fields: userId, credential, username".
  Same fix applied to the OIDC accept page flow.
2026-04-17 09:53:53 -04:00
Jeff Emmett 8042e86815 wip(rschedule): schemas + folk-app-canvas/folk-widget shared components
Schema for the new Calendly-style rSchedule port plus two new shared
canvas components (folk-app-canvas, folk-widget) that replace per-rApp
tab-based nav with a unified widget-on-canvas surface.
2026-04-16 17:26:45 -04:00
Jeff Emmett 3a614e2866 rename: finish rschedule → rminders migration
Complete the rename started in dda7760 (which removed rschedule/ but
left callers unmigrated and the rminders/ dir uncommitted). Updates
vite.config.ts build entries, API base fetches in folk-comment-pin,
folk-rapp widget map, module-display meta, calendar reminder-drop
route, docs comment-panel, e2e fixtures, shell/landing/mcp-server
references, and backlog/ONTOLOGY docs.

Fixes vite build failure: "Could not resolve entry module
modules/rschedule/components/folk-schedule-app.ts".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 17:18:17 -04:00
Jeff Emmett 98d6d22e55 ui(space-settings): Invite label + breathing room under username search
- Rename 'Add' to 'Invite' in the By-Username add-member row to match
  the By-Email path and reflect that it goes through an invite flow.
- Add 10px top margin to .add-member-row so the role dropdown and
  button don't visually collide with the search input/selected-user
  area above.
2026-04-16 16:36:52 -04:00
Jeff Emmett 351565c934 fix(space-settings): refresh invitations tab after sending invite
Email-invite path previously only showed 'Invite sent' without
refreshing the list. Username-invite path reloaded members but not
invitations. Both now call #loadInvitations after a successful POST.
2026-04-16 16:34:05 -04:00
Jeff Emmett 3a69234819 feat(rpast): chronicle-of-self timeline + markwhen projection
- New rpast module renders a cross-rApp personal timeline
- shared/markwhen/ projection layer hydrates from syncServer docs
- rCal gets a Timeline applet wiring into the same markwhen view
- rstack-markwhen-view component for embedding elsewhere
- Smoke-test fixtures under output/ and scripts/smoke-rpast.ts
- Adds @markwhen/{parser,timeline,calendar,mw} deps

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 16:13:11 -04:00
Jeff Emmett 39fbd99897 feat(mi-voice): quieter+smoother voice, caveman terseness in voice mode
- Default voice en-US-AvaMultilingualNeural -> en-US-AndrewMultilingualNeural
  (smoother, less feminine timbre).
- Volume 0.55 -> 0.3, rate -8% -> -10%, pitch -2Hz -> -6Hz.
- Browser fallback matches: pitch 0.85, volume 0.3.
- Client passes voiceMode flag to /api/mi/ask; server appends a VOICE
  MODE section to the system prompt demanding ≤1-2 short sentences,
  no lists/markdown/emoji/preamble — because listening to long replies
  is tedious.
2026-04-16 15:44:11 -04:00
Jeff Emmett 9daeb60895 fix(collab): dedup cursors by username + same-page-only visibility
- Deduplicate cursor rendering using #uniquePeers() (was showing
  multiple cursors per user from different tabs/sessions)
- Strict same-page filtering: cursors only visible when peers share
  the same effectiveViewId (viewId ?? moduleId)
- Users on different rApps no longer see each other's cursors
- Applied same fixes to focus rings and panel "different view" badge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 15:00:11 -04:00
Jeff Emmett c885773844 fix(shell): move tab bar up 2px more, reduce left padding for full-width span
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 14:56:05 -04:00
Jeff Emmett 63c6fcc941 fix(auth): preserve current page on login instead of redirecting
Only redirect to personal dashboard when on demo landing page.
Logging in from any module page now reloads in place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 08:17:24 -04:00
Jeff Emmett 127d692058 fix(rcred): add Vite build entry + fix script path + darken badge color
Dashboard was empty because folk-cred-dashboard.ts had no Vite build
entry — the JS never got compiled. Add build step to vite.config.ts,
fix script src to /dist/modules/rcred/folk-cred-dashboard.js, and
darken badge background from #fbbf24 to #d97706 so it doesn't blend
with the  emoji.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:48:30 -04:00
Jeff Emmett a92b5fc100 feat(ui): add rcred badge + orange 'r' prefix in all badge pills
Add r badge for rcred in favicon, app-switcher, and tab-bar badge
maps. Render 'r' with #dc8300 orange in badge pills across all three
components (favicon SVG tspan, app-switcher HTML spans, tab-bar HTML
spans). App names (e.g. "rDocs") intentionally left uncolored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:41:31 -04:00
Jeff Emmett 184da55813 feat: brandedAppName helper, rData cloud refactor, branding color tweaks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 13:08:36 -04:00
Jeff Emmett a2dbf4533a feat(rchats): add global chat widget + unread count endpoint
Persistent chat panel accessible from any page via header icon.
Sliding right panel (360px) with channel selector, message feed,
composer, and unread badge. REST polling with localStorage state
persistence. Includes unread-count API endpoint for badge updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 11:15:33 -04:00
Jeff Emmett 195b42eb3b feat(collab): scope SVG cursors by active sub-document view
Remote cursor arrows and focus rings from peers viewing a different
note in rDocs are now suppressed. A generic viewId concept on the
collab overlay lets any rApp with sub-views opt in via a
rspace-view-change CustomEvent. Peers on a different view appear
dimmed in the people panel with a document icon hint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:17:29 -04:00
Jeff Emmett efbd0f040c fix(canvas): plug memory leaks causing OOM on long sessions
- Store shape listener refs in Map, remove in unregisterShape() (critical leak)
- Compact Automerge history every 500 changes via clone() to cap WASM heap
- Clean shapeLastPos entries on shape removal
- Store outside-click handler ref, clean up in disconnectedCallback()
- Cap MI messages at 50 and prompt messages at 30 to prevent unbounded growth
- Store keep-alive interval handle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 10:26:43 -04:00
Jeff Emmett 1e5f04398b feat(identity): add notification dot on My Account + remove postal address
Show red alert dot on "My Account" dropdown item when email, multi-device,
or social recovery tasks are incomplete. Remove postal address section
from the account modal (render, state, loader, listeners).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:15:17 -04:00
Jeff Emmett c91921592b feat(mi): unify voice into single mic toggle with succinct TTS responses
Replace three separate mic controls (bar dictation, bar miC, panel miC)
with a single 🎤 toggle in the bar that activates the full voice loop:
speech-to-text → auto-submit after 1.5s silence → TTS response.

- Remove standalone dictation mode (#dictation, #interimText)
- Remove panel header miC button
- Single mic button uses voice mode state animations (pulse red = listening,
  spin amber = thinking, pulse cyan = speaking)
- Tighten TTS output to ~2 sentences for succinct responses
- Voice strip still shows in panel with waveform, status, and stop button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 09:03:29 -04:00
Jeff Emmett 48c7f15de4 feat(app-switcher): add badges for all rApps, sort toggle, and pin favorites
- Add r<emoji> badges for rDocs, rDesign, rSheets, rTime, rGov, rAgents,
  rExchange to both MODULE_BADGES and FAVICON_BADGE_MAP
- Add MODULE_CATEGORIES entries for all new modules
- Add "Govern" category for rGov
- Sort modules alphabetically within each function category
- Add sort toggle (By Function / A-Z) at bottom of sidebar, persisted
  in localStorage
- Add star/pin button on each rApp — pinned items appear in a "Pinned"
  section above "Recent", persisted in localStorage
- Fix rAuctions module ID: 'auctions' → 'rauctions' for consistency,
  with alias in MODULE_ALIASES for backward compat
- Change rAuctions emoji from 🏛 to 🎭

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 08:49:52 -04:00
Jeff Emmett 5c88922b13 fix: MI bar z-index, SW force-update, rtime mobile layout
- MI bar z-index lowered to 1 so dropdowns render above it; panel
  gets z-index 10001 only when open
- SW registration URL bumped to v=8 to match cache version
- rtime: pool and weaving are now two separate scrollable sections
  on mobile (50vh/60vh min-heights) with a "Commitment Weaving"
  section header visible on constrained screens

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:17:53 +00:00
Jeff Emmett 44cc47ecf1 fix(auth): same-origin passkey proxy + PRF fallback for Safari
- Add /api/auth/*, /api/register/*, /api/account/* proxy routes to
  rspace-online server, forwarding to encryptid container internally.
  This eliminates cross-origin requests that Safari blocks via ITP or
  Cloudflare security challenges.
- Change client auth URLs from https://auth.rspace.online to same-origin
  in rstack-identity, rspace-header, login-button, and session modules.
- Add PRF extension try/catch fallback in webauthn.ts — Safari throws
  TypeError on the unsupported PRF extension, now retries without it.
- Bump SW cache version v7→v8 to bust stale cached bundles.

Fixes passkey login for Safari/macOS users (e.g. christina) who were
getting "Network error when attempting to reach resource".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:31:59 +00:00
Jeff Emmett cdb62e2ee8 feat(encryptid): social recovery guardian UX enhancements
- Red pulsing alert dot on avatar when social recovery not configured
- SVG puzzle piece visualization for guardian slots (empty/pending/accepted)
- Key assembly animation when 2+ guardians accepted
- Recovery drill system: test the full guardian approval flow without actual recovery
  - POST /api/recovery/drill/initiate, GET .../status, POST .../complete
  - Drill-specific emails with "TEST ONLY" branding
  - Live polling UI with puzzle pieces filling in as guardians approve
  - Drill timestamp tracking (last_drill_at on users table)
- Solo walkthrough modal: 5-step animated preview of how recovery works
- Approval page detects drill flag, shows DRILL badge
- Account status now returns acceptedGuardianCount and lastDrillAt
- Recovery section shows emergency override messaging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:48:55 -04:00
Jeff Emmett dda0492dbf feat(encryptid): add email login (magic link) and optional email on registration
- Sign-in modal: detect email input and send as { email } to auth/start
- Add "Send Magic Link" button alongside passkey sign-in
- Registration: optional email field sent with register/complete
- Enter on username field tabs to email; Enter on email submits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:01:06 -04:00
Jeff Emmett 928867a9e2 fix(encryptid): show all known usernames at login, reduce post-auth redirects
- getAllKnownUsernames() now pulls from 4 sources: current session,
  rspace-username cache, known-personas list, and encryptid-known-accounts
- On specific space: stay on that page (reload only, no redirect away)
- On landing: go straight to dashboard (hardcode "rspace" module)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 08:33:08 -04:00
Jeff Emmett c3457cf98f feat(encryptid): show registered usernames in login modal instead of text input
Display known accounts as clickable buttons in the sign-in modal so users
pick their username rather than typing it — prevents accidental new passkey
creation from typos. Falls back to manual input via "Use a different account".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 08:02:36 -04:00
Jeff Emmett e6328581a7 feat: customizable dashboard with persistent home icon and widget system
Adds always-visible home button in tab bar, toggleable dashboard overlay,
widget card system with 8 widgets (tasks, calendar, activity, members,
tools, quick actions, wallet, flows), customize mode with toggle/reorder,
and dashboard summary API endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 23:10:27 -04:00
Jeff Emmett 53c757e68e fix: comprehensive memory leak and performance fixes across 44 files
Browser-side:
- Fix switchSpace() to LRU-evict idle space WebSocket connections (cap: 3)
- Add runtime.unsubscribe() to disconnectedCallback in 24 components
- Fix DocSyncManager.unsubscribe() to clean up syncStates, timers, listeners
- Fix 14 components leaking RAF loops, ResizeObservers, MutationObservers,
  document/window listeners, setIntervals, MapLibre WebGL contexts, and
  AbortControllers on disconnect
- Deduplicate Automerge WASM: module builds now use global shim from
  shell-offline instead of bundling ~2.5MB each (8 modules affected)

Server-side:
- Add LRU eviction to SyncServer.#docs (cap: 500, evicts idle docs with
  no subscribers, persists to disk before eviction)
- registerWatcher() now returns unsubscribe function

Data:
- Cap unbounded CRDT arrays: rexchange chatMessages (200), rcart events (200)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 22:26:24 -04:00
Jeff Emmett c6cb875ba4 feat(rcal): add Google Calendar sync integration with connectors menu
- Google Calendar API client (server/google-calendar.ts): token auto-refresh,
  list calendars, fetch events with incremental sync, create events, mapping
- OAuth scopes: added calendar.readonly + calendar.events, returnTo param
- rCal routes: subscribe, sync, sync-all, unsubscribe, push-to-Google endpoints
- Background sync loop: 10-minute interval with incremental sync tokens
- Frontend: calendar picker modal, sync button, per-event Google export
- MCP: source_type filter on rcal_list_events, new rcal_sync_google tool
- Connectors menu: Google shows services (Docs/Drive/Calendar) + calendar count,
  added Obsidian & Logseq as file-based connectors, Notion shows services
- Fix: import-export dialog API base corrected from rnotes to rdocs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 19:45:52 -04:00
Jeff Emmett be98bb542c fix: rename MIc to miC with mic emoji in voice conversation buttons
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 18:40:40 -04:00
Jeff Emmett 18b61fa5e6 feat: rebuild rNotes as vault browser, editor code now in rDocs
Phase 2-3 of the rNotes/rDocs split. Rewrites rNotes from a full TipTap
editor (~1800 lines) into a lightweight Obsidian/Logseq vault sync and
browse module (~560 lines). Rich editing features remain in rDocs.

rNotes vault browser:
- VaultDoc schema: metadata-only in Automerge (title, tags, hash, wikilinks)
- ZIP vault uploads stored on disk at /data/files/uploads/vaults/
- File tree browser, search, read-only markdown preview
- Wikilink graph data endpoint for visualization
- 5 MCP tools: list_vaults, browse_vault, search_vault, get_vault_note, sync_status
- Browser extension compat shim redirects old API calls to rDocs

Cleanup:
- Removed dead editor files from rnotes (converters, components, local-first-client)
- Updated MI integration to use getRecentVaultNotesForMI
- Updated ONTOLOGY.md with new module descriptions
- Bumped JS cache versions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 18:05:35 -04:00
Jeff Emmett 1de038eeab feat(comments): spatial comment pins on all rApp module pages
Adds Figma-style threaded comment markers anchored to data-collab-id
elements across all module pages. Comments stored in per-space Automerge
doc, synced via existing local-first stack. Bell is now context-aware
(canvas pins on canvas, module pins on module pages). Notifications
route through existing WS/push/email system with new module_comment
and module_mention event types.

New files: module-comment-types, module-comment-schemas,
rstack-module-comments component. Updated: shell, comment bell,
notification routes. Added data-collab-id to crowdsurf, rtime, rmeets.
Fixed pre-existing SKILL_LABELS import error in rtime/mod.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 11:15:05 -04:00
Jeff Emmett 234c8e6703 fix(canvas): disabled module gating + toolbar reorganization
- Remove MODULE_BADGES fallback in tab-bar add-menu (show "Loading rApps..." instead of leaking all modules)
- Block ?tool= URL param from spawning shapes for disabled modules
- Add disabled-module overlay on existing canvas shapes (grayed out + "Module disabled" badge)
- Guard newShape() against creating shapes for disabled modules
- Reorganize toolbar from 10 groups to 9 category-aligned groups:
  Write, Embed (core 4), Communicate, Plan, Decide, Spend, Create, AI, Record
- Eliminate duplicate "Connect" groups, slim mega "Embed" group, merge "Travel" into "Plan"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 20:35:58 -04:00
Jeff Emmett dd38dcb631 feat(tabs): close-all button with confirmation dialog
Adds a ✕ button next to the + tab button that closes all open rApp tabs
and returns to the user dashboard. Shows a confirm() prompt with tab count
before proceeding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 15:56:30 -04:00
Jeff Emmett 7836b1d956 perf(collab): lazy GC timer — start on first peer, stop when empty
The collab overlay was running a 5s setInterval GC timer on every page
load even with zero peers. Now the timer starts only when the first
peer arrives and stops when all peers are garbage collected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 13:48:18 -04:00
Jeff Emmett 5ddde13b0d feat: magic link responses for polls and RSVPs
HMAC-signed stateless tokens let external respondents vote on rChoices
polls or RSVP to rCal events via a single tap — no account required.
Routes mounted at /respond/:token bypass space auth. Typed EventAttendee
schema replaces unknown[] on CalendarEvent.attendees. Invite endpoints
on both modules generate tokens and optionally send email invitations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 13:41:17 -04:00
Jeff Emmett a711af055a fix(encryptid): remove all remaining authenticatorAttachment: 'platform' hardcodes
Three client-side registration flows still had authenticatorAttachment: 'platform'
hardcoded, blocking Samsung Passkey and Linux users:
- lib/rspace-header.ts (main site header registration)
- shared/components/rstack-identity.ts (2 occurrences)

Also added server-side validation for missing userId in register/complete
to return 400 instead of crashing with TypeError.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 22:27:16 -04:00
Jeff Emmett 8321a9015a revert: restore app switcher to left sidebar
Reverts 4420d9c — the FAB change was applied to the wrong component.
The intended target is the rSpace canvas toolbar, not the app switcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 14:05:38 -04:00
Jeff Emmett 4420d9cafe feat(shell): move app switcher from left sidebar to bottom-right FAB
Repositions the rApp switcher as a floating action button in the bottom-right
corner that expands upward into a rounded panel. Removes all sidebar push-offset
CSS since the panel now overlays content without layout shift.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 15:59:36 -04:00
Jeff Emmett a43bc3b3ee fix: make profile dropdown buttons clickable (pointerdown→click)
pointerdown on document was hiding the dropdown before click could fire
on My Account / My Spaces / My Wallets buttons. Switching to click lets
stopPropagation in item handlers prevent premature close.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-05 14:29:20 -04:00
Jeff Emmett 4a54e6af16 fix: enforce subdomain routing — spaces are subdomains, never path segments
Audit and fix ~60 violations across 47 files where URLs were constructed
as /{space}/moduleId instead of /moduleId (subdomain provides the space).

- Add getModuleApiBase() helper to shared/url-helpers.ts
- Fix client components: use getModuleApiBase() for fetch URLs,
  rspaceNavUrl() for navigation
- Fix server routes: use c.get("isSubdomain") for redirects and
  JSON response URLs
- Fix OAuth callbacks (notion, google, clickup): subdomain-aware redirects
- Fix email notification URLs (rvote): use {space}.rspace.online format
- Fix webhook registration (rtasks/clickup): subdomain-aware endpoint URL
- Replace broken #getSpaceSlug() methods in folk-feed, folk-splat
- Replace NODE_ENV checks with proper isSubdomain checks (rdata, rnetwork)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 14:09:53 -07:00
Jeff Emmett 2c3f8568a3 fix: use subdomain format {space}.rspace.online instead of path-based routing
Space creation popup slug field now shows input followed by .rspace.online
suffix instead of rspace.online/ prefix. Also fixes rtasks notification
link and browser extension help text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:16:07 -07:00
Jeff Emmett 3b0999da64 feat(rtime): commitment notifications + email delivery channel
- Fire commitment_accepted/commitment_declined notifications when solver
  results are accepted/rejected in intent-routes.ts
- Fire commitment_declined when a connection is deleted in mod.ts
- Add metadata (resultId, fromCommitmentId) to commitment_requested notify
- Fix actionUrl to use /rtime (subdomain-relative), not /{space}/rtime
- Add Accept/Decline action buttons in notification bell for
  commitment_requested events (same pattern as space_invite)
- Add email delivery channel to notification-service: sends from
  {space}-agent@rspace.online via SMTP, respects emailEnabled preference,
  inline HTML template with dark theme

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 14:59:10 -07:00
Jeff Emmett 7420228ce9 feat: add Mermaid diagram generator canvas tool + share panel role selector
- Add folk-mermaid-gen web component: AI-powered diagram generation via
  Ollama, client-side SVG preview via mermaid.js, animated GIF export via
  mermaid.rspace.online API
- Register in canvas tools, toolbar, and shape registry
- Add role selector dropdown to share panel invite form (backend already
  supports role parameter)
- Fix pre-existing TS errors: SankeyNode missing address field,
  SpaceMember type mismatch in WebSocket auth fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 14:01:52 -07:00
Jeff Emmett 45372c6681 Fix sidebar showing all modules: hide Manage panel when none disabled
- App switcher: only show "Manage rApps" when there are actually
  disabled modules or active restrictions. Move "Available to Add"
  above "Remove" to prioritize adding. Eliminates duplicate module
  listing when all modules are enabled.
- Shell: update app switcher on modules-changed event (was only
  updating tab bar and folk-rapp, not the sidebar itself).
- SMTP: use space-agent@rspace.online as From for invite/approval
  emails with proper envelope sender for DKIM alignment.
- Shell CSS: fix banner z-index, smooth header transition on banner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 12:32:53 -07:00
Jeff Emmett b54ad4b36c Fix multi-user cursor positions: use page-relative coordinates
CI/CD / deploy (push) Failing after 8s Details
Remote cursors were broadcast as viewport-relative (clientX/Y), causing
them to appear at wrong positions when users had different scroll offsets.
Now sends page-relative coords and converts back on the receiver side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 12:32:01 -07:00
Jeff Emmett 29cd6168f9 Fix mobile popup/modal issues across shell components
CI/CD / deploy (push) Failing after 9s Details
- Space switcher: clamp menu left to prevent right-edge overflow,
  add max-width: calc(100vw - 8px), scrollable tabs with smaller
  padding on mobile
- Auth/edit modals: add max-height: 90dvh + overflow-y: auto so
  virtual keyboard doesn't push modal off-screen, reduce padding
  on small screens
- Identity dropdown: raise z-index from 100 to 10002 so it renders
  above the app-switcher sidebar (10001)
- Device nudge toast: constrain max-width to viewport width
- App switcher: add translucent backdrop overlay on mobile (<640px)
  with tap-to-dismiss
- Add :active pseudo-class alongside :hover on interactive elements
  for touch tap feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 11:35:14 -07:00
Jeff Emmett 32093a0fc3 refactor(connections): move from space settings to user account
Connections are per-user, not per-space. Move the platform connections
dashboard from the space settings modal (5th tab) to the My Account
modal as a collapsible section. Add selective sharing: users connect
platforms to their personal data store, then choose which community
spaces to share data into via per-provider space checkboxes.

New endpoints: GET/POST /api/oauth/sharing for per-user sharing config.
Sharing config stored as Automerge doc {userSpace}:oauth:sharing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 15:52:15 -07:00
Jeff Emmett 26aa6433be feat(connections): add platform connections dashboard in space settings
New "Connections" tab in space settings with n8n-style visual dashboard
showing platform cards (Google, Notion, ClickUp live + 7 coming soon)
connected via SVG bezier lines to central rSpace hub node. Includes
OAuth connect/disconnect flows and GET /api/oauth/status endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 13:04:02 -07:00