Commit Graph

266 Commits

Author SHA1 Message Date
Jeff Emmett dda7760433 infra(traefik): scope rate limit per CF-Connecting-IP, raise to 600/150
Previous limits (avg 120/min, burst 30) had no sourceCriterion. Traefik
default groups by request Host, so ALL users of rspace.online shared a
single 120/min bucket — tripped almost immediately under normal load
(repeated 429s in rpast, api/mi/models, etc).

Scope per Cloudflare client IP (CF-Connecting-IP header) and raise to
600/min average with 150 burst — interactive use can spike above 120/min
from one client easily (module loads + polling + autosave).
2026-04-16 17:04:15 -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 fec934b8a3 fix(persistence): flush docs on shutdown, fix eviction race, mobile flush
- Add saveDocImmediate() for synchronous awaitable saves (no debounce)
- Add SyncServer.flushAll() to iterate all in-memory docs
- Fix eviction race: onDocEvict now uses saveDocImmediate instead of
  debounced saveDoc (which could fire after doc deleted from memory)
- Add SIGTERM/SIGINT handlers with 10s timeout safety net
- Add visibilitychange flush on client (reliable on mobile/bfcache)
- Flush pending IDB saves in DocSyncManager.disconnect()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 08:45:01 -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 72587ef690 feat(canvas): wire commitment weaving data flow between rTime and rTasks applets
Add pool-out port to folk-commitment-pool, two new applets (weaving-coverage
for rTime, resource-coverage for rTasks), fetchLiveData polling in FolkApplet,
and canvas AI tool declarations for both new applets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 17:16:48 -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 adda731df1 feat(canvas): add rApplet circuit components + template system
Unified applet abstraction for canvas — compact dashboard cards with typed
I/O ports, expandable circuit editors, and save-able reusable templates.

New files: shared/applet-types.ts, lib/folk-applet.ts, lib/applet-circuit-canvas.ts,
lib/applet-template-manager.ts, lib/applet-defs.ts, plus applets for rGov (Signoff Gate,
Governance Circuit), rFlows (Flow Summary), rWallet (Balance Card, Token Balance).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 12:01:30 -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 0f6b5ecd8d fix: disable all feature tours — shell welcome tour, TourEngine, landing links
Tours were demoing stale features and auto-triggering annoyingly.
TourEngine.start() now returns immediately (no-ops). Shell welcome
tour JS/CSS/HTML removed. "Start Guided Tour" links stripped from
all 27 landing pages. Tour CSS selectors removed from info panel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 11:12:00 -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 0eb721d12e feat: object visibility membrane — per-object access filtering
Add per-object visibility levels (viewer/member/moderator/admin) across
all rSpace modules. Objects default to 'viewer' (open), so existing data
remains visible. Server-side GET handlers resolve caller role and filter;
MCP tools filter lists and check single-item access; frontend components
do defense-in-depth filtering with visibility picker (mod+) and lock badges.

- shared/membrane.ts: types + isVisibleTo, filterByVisibility, filterArrayByVisibility
- 9 schema files: visibility field on TaskItem, NoteItem, CalendarEvent, etc.
- 8 module routes: GET handlers filter by caller role
- 6 MCP tool files: list filtering + single-item visibility checks
- 4 frontend components: client filtering, picker, lock badges
- 18 unit tests (all passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 11:09:44 -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 de9cc21301 feat(rmeets): require username on join, fix settings/background, add MI toolbar
- Enable prejoin page so users must enter a display name before joining
- Add requireDisplayName, SETTINGS_SECTIONS, disableVirtualBackground config
- Add floating Meeting Intelligence button with recordings/search links
- Add chat, settings, participants-pane to folk-jitsi-room toolbar
- Also includes: rDocs module expansion, tab-cache/view-history updates,
  converter rewrites, MCP tool additions, OAuth fixes, backlog tasks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 14:06:47 -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 fab155b411 feat(rcart): add MoonPay integration with Transak fallback
Add MoonPay as the primary card payment provider for rCart. MoonPay
uses HMAC-SHA256 signed URLs (no session API needed, no IP whitelisting).
Falls back to Transak if MoonPay keys aren't configured.

- shared/moonpay.ts: URL builder with HMAC signing, currency mapping
- New /api/payments/:id/card-session endpoint picks provider automatically
- Frontend uses unified startCardPayment() with multi-provider message handling
- Set MOONPAY_API_KEY + MOONPAY_SECRET_KEY to activate

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 06:23:14 +00:00
Jeff Emmett 125bed3ad7 fix: try gateway for Transak token refresh before legacy API
Production gateway rejects tokens from api.transak.com. Try getting
the access token from the gateway endpoint first (which staging
confirms works), then fall back to the legacy API endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 03:58:09 +00:00
Jeff Emmett e61da960ea feat: migrate to Transak Secure Widget URL API
Transak now requires widget URLs to be generated server-side via their
gateway session API. Direct query-parameter URLs are deprecated.

- Add getAccessToken() with 7-day caching for partner access tokens
- Add createSecureWidgetUrl() that calls the gateway session endpoint
- Falls back to legacy direct URL if gateway returns an error (e.g.
  production IP not yet whitelisted)
- Update rCart and rFlows to use the secure API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 03:17:18 +00: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 c8e4aede02 feat(canvas): module-aware canvas architecture — shapes, tools, and toolbar gated by module
Modules now declare their canvas shapes and AI tools (canvasShapes/canvasToolIds
on RSpaceModule), creating a single source of truth that the canvas enforces:

- Phase 1: Extended RSpaceModule + ModuleInfo, added moduleId to CanvasToolDefinition
  with getToolsForModules() filter, added moduleOf() to ShapeRegistry, populated
  declarations in 9 modules, fixed 8 ungated toolbar buttons (rchoices, rwallet, rsocials)
- Phase 2: AI prompt sends enabledModules, server filters Gemini tool declarations
- Phase 3: folk-commitment-pool and folk-task-request show lock overlay when rtime disabled
- Phase 4: Extracted MODULE_META into shared lib/module-display.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 15:19:12 -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