Commit Graph

1431 Commits

Author SHA1 Message Date
Jeff Emmett 8ba14a0e15 fix(rwallet): skip spam filter when CoinGecko data unavailable
Revert per-address batching (rate limit cascade). Track cgAvailable flag
in cache — only apply spam filter when CoinGecko successfully returned data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:25:48 -07:00
Jeff Emmett 395623af66 feat(rdesign): deploy KiCad & FreeCAD MCP as Docker sidecars
Switch from broken StdioClientTransport (child process) to
SSEClientTransport (HTTP to sidecar containers via supergateway).
Both sidecars share rspace-files volume so generated CAD files
(STEP, STL, Gerber, SVG) are directly servable without copying.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:25:23 -07:00
Jeff Emmett 95246743c3 fix(rwallet): batch CoinGecko requests to 1 address each (free tier limit)
CoinGecko free tier now limits to 1 contract address per request.
Process in batches of 3 concurrent single-address requests with 1.5s delay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:17:03 -07:00
Jeff Emmett 2c710bef68 Merge branch 'dev' 2026-03-25 16:10:14 -07:00
Jeff Emmett 55b973ebc2 fix(blender): use correct Ollama model (qwen2.5-coder:7b)
qwen2.5:14b doesn't exist on the server, causing silent 404 from
Ollama and 502 to the client. Also added error logging for non-ok
Ollama responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:10:11 -07:00
Jeff Emmett 1a422f06ac feat(canvas): add first-time forgotten shapes explainer tooltip
Shows a one-time onboarding tooltip when users first encounter a faded
(forgotten) shape. Explains right-click to remember/forget permanently,
the Hide Forgotten toggle in profile menu, and highlights the Collective
Memory graph as a prototype feature. Persisted via localStorage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:09:05 -07:00
Jeff Emmett 5f853322b0 fix(rwallet): filter spam tokens via CoinGecko verification
ERC-20 tokens not recognized by CoinGecko and valued < $1 by Safe API
are now stripped from balance responses, removing fake ETH and airdrop spam.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:08:52 -07:00
Jeff Emmett 4d7d2c0108 fix(rsocials): campaign wizard auth — read correct session storage key
Was reading `encryptid-token` (doesn't exist), now reads `encryptid_session`
and extracts `.accessToken` matching the pattern used by all other modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 16:01:10 -07:00
Jeff Emmett aa23108f5f fix(invites): redirect to invited space, improve invite emails
- Fix invite accept fetch URL in shell.ts (was missing /api/spaces prefix)
- After accepting invite, redirect to the invited space instead of reloading
- Notification actionUrls now point to the space subdomain (https://slug.rspace.online)
- Direct-add email includes inviter name, role, and space description
- Identity invite email includes space name/role context when inviting to a space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:39:58 -07:00
Jeff Emmett 8989523646 Merge branch 'dev' 2026-03-25 15:38:59 -07:00
Jeff Emmett 2f3a4a13dc fix(blender): make RunPod optional, fix script-only generation
RunPod was hard-gated — returned 503 when RUNPOD_API_KEY missing,
blocking even LLM script generation. Now generates script via Ollama
regardless, only attempts RunPod render if key is configured. Health
check returns warnings (non-blocking) vs issues (blocking). Default
model switched to qwen2.5:14b (available on server). Regex also
handles non-python-tagged code blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:38:49 -07:00
Jeff Emmett 59d2cc9933 feat(spaces): add visibility/description to settings panel, merge invite sources
- Space Settings section in dropdown with visibility (public/permissioned/private)
  and description fields, matching the full edit space modal
- GET /api/spaces/:slug now includes description field
- listSpaceInvites merges both space_invites and identity_invites tables
  so email invites appear in Pending Invites
- revokeSpaceInvite falls through to identity_invites table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:29:33 -07:00
Jeff Emmett 858457c056 fix(invites): show email invites in space settings pending list
listSpaceInvites now queries both space_invites and identity_invites
tables, merging results so email-based invites (via /invite endpoint)
appear in the Pending Invites section. revokeSpaceInvite also falls
through to identity_invites if not found in space_invites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:24:26 -07:00
Jeff Emmett 00904c4832 Merge branch 'dev' 2026-03-25 15:21:23 -07:00
Jeff Emmett 4a43ecdee0 fix(rcal): replace event dots with thin colored bars on mobile
Dots were overlapping in small day cells. Now renders full-width 2px
color-coded stripes (solid for confirmed, dashed for tentative). Multi-day
spans also thinner (10px) with hidden text on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:21:15 -07:00
Jeff Emmett 0753b31990 fix(spaces): correct API paths for member/invite operations in settings panel
All fetch calls in rstack-space-settings were missing the /api/spaces prefix,
causing 404s for add-by-username, invite-by-email, change-role, remove-member,
and load-invites. Also add color-scheme: light dark to fix native select
dropdowns rendering in light mode on dark theme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:15:33 -07:00
Jeff Emmett b7853beca1 Merge branch 'dev' 2026-03-25 14:40:22 -07:00
Jeff Emmett 28f11242f7 fix(rwallet): consolidate dual tab bars into single shell subnav
Remove internal view-tabs from folk-wallet-viewer — navigation now handled
entirely by shell subnav outputPaths: Budget (default), Token Balances, Flows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:40:14 -07:00
Jeff Emmett a10f8e9507 fix(rwallet): capture ETHEREUM_TRANSACTION inflows, filter airdrop spam tokens
Transfers: handle ETHEREUM_TRANSACTION txType as inflows (was only scanning
tx.transfers), exclude self-transfers from embedded transfers loop.
Balances: hide unpriced ERC-20s (airdrop spam) while keeping native tokens,
CRDT tokens, and CoinGecko-priced tokens. Filter zero balances on single-chain
Safe endpoint. Bump JS cache to v=20.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:37:35 -07:00
Jeff Emmett 6c07e277f5 Merge branch 'dev' 2026-03-25 14:04:06 -07:00
Jeff Emmett c7c6b6a13b chore(rwallet): bump JS cache version to v=19
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:04:00 -07:00
Jeff Emmett 2bfd674d0e refactor(rwallet): consolidate tabs — remove Yield, merge viz into Budget + Flows
Simplify rWallet from 5 internal tabs to 3: Token Balances, Budget Visualization
(default), and Flows (Sankey + timeline scrubber with play/pause). Remove Yield
shell-level outputPath and route. Budget view auto-loads transfer data on entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 14:03:35 -07:00
Jeff Emmett 037182efdf Merge branch 'dev' into main
Resolve login-button.ts conflicts — take dev's cleaner formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:23:21 -07:00
Jeff Emmett 8071b620e1 fix(auth): throttle session validation, typed auth-change events, misc fixes
- rstack-identity.ts: throttle server session validation to every 5min,
  add reason detail to all auth-change events (signin/signout/revoked/
  refresh/persona-switch), remove redundant location.reload on signout
- shell.ts: skip UI side-effects on token refresh, only redirect home
  on genuine signout/revocation
- server.ts: add PUT to CORS allowMethods
- folk-inbox-client.ts: pass auth token on mailbox API fetch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:21:26 -07:00
Jeff Emmett 32be9d7b94 fix(ui): bump subnav sticky top to avoid header overlap
Increase .rapp-subnav top from 92px to 93px so pill buttons
don't clip under the fixed header + tab-row border.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:54:23 -07:00
Jeff Emmett c2d7e8b238 fix(shell): prevent infinite loop when rapidly switching tabs
Abort previous in-flight fetch when switchTo() is called again, and
guard the shell's fallback navigation against stale callbacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:44:38 -07:00
Jeff Emmett 06a58f1bba fix(ui): theme-adaptive rSocials buttons + device link textbox
- campaign-wizard.css: fix undefined --rs-surface-hover → --rs-bg-hover
- campaign-workflow.css: replace hardcoded blue colors with theme vars
  (--rs-primary-hover, --rs-bg-active, --rs-border, --rs-primary)
- rstack-identity.ts: device link URL input --rs-bg-inset → --rs-input-bg
  (--rs-bg-inset was never defined in theme.css, dark fallback always won)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:39:14 -07:00
Jeff Emmett b3fb51c39a feat(encryptid): known accounts picker + passkey-first for both UIs
- login-button.ts: no-known-accounts state shows passkey-first button
  (unscoped WebAuthn) with email magic link fallback, auto-revealed on
  NotAllowedError. Fix stale usernameInput ref.
- server.ts (auth.rspace.online): add localStorage known accounts system.
  Returning users see their stored usernames as clickable buttons.
  handleAuth() accepts optional username for scoped auth. Saves account
  after successful login. renderSigninAccounts() called on page init.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:29:44 -07:00
Jeff Emmett c651b51864 Merge branch 'dev' 2026-03-25 11:27:42 -07:00
Jeff Emmett 423d2612af fix(auth): preserve active tab through login on bare domain
The identity component's inline _getCurrentModule() assumed path-based
routing (/{space}/{moduleId}) for non-subdomain URLs, returning "rspace"
instead of the actual module. On bare domain (rspace.online/rnotes),
this caused login to redirect to the canvas instead of rnotes.

Add _isBareDomain() check so _getCurrentSpace() returns "demo" and
_getCurrentModule() reads parts[0] (the module) on the bare domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:27:30 -07:00
Jeff Emmett 51fb898dd3 Merge branch 'dev' 2026-03-25 11:16:58 -07:00
Jeff Emmett 22b5c00a13 fix(routing): prevent domain stacking and remove Try Demo button
- Fix server-side redirect to always use canonical rspace.online as base
  domain instead of deriving from hostClean (prevents demo.rspace.rspace.online)
- Fix bare-domain check to exact match instead of .includes() (prevents
  stacked subdomains from triggering bare-domain routing)
- Fix client-side rspaceNavUrl to guard against reserved subdomain names
  being used as space subdomains (e.g. rspace.rspace.online)
- Fix identity component _navUrl with same canonical domain guards
- Remove "Try Demo" header button from all shell rendering functions
- Remove demo-btn CSS styles
- Fix pre-existing SchemaType error in Gemini tool declarations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 11:16:46 -07:00
Jeff Emmett b60cfbdc71 Merge branch 'dev' 2026-03-24 19:27:06 -07:00
Jeff Emmett dd46905e12 feat(mi): agentic upgrade — multi-turn loop, LiteLLM, media gen, live data
Transform MI from single-shot chat into an agentic system:

- LiteLLM provider with Claude Sonnet/Haiku models via proxy
- Agentic loop (max 5 turns): stream → parse actions → execute server-side → feed results back
- Server-side media generation (fal.ai + Gemini) as first-class MI actions
- Module data queries (rnotes, rtasks, rcal) read directly from Automerge
- System prompt enriched with recent notes, open tasks, and calendar events
- Client handles new NDJSON types (turn, action-start, action-result)
- Extracted shared media helpers, refactored image/video endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:26:56 -07:00
Jeff Emmett 90ecc1d952 Merge branch 'dev' 2026-03-24 19:06:13 -07:00
Jeff Emmett a5c7eef466 fix(startup): move space alias provisioning after loadAllDocs
The IIFE raced with doc loading so listCommunities returned empty.
Moved into the .then() callback to ensure all docs are loaded first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:06:06 -07:00
Jeff Emmett 7b0bd25d71 Merge branch 'dev' 2026-03-24 19:02:11 -07:00
Jeff Emmett 3596bb9d7c fix(ui): raise MI search z-index and unclip header overflow
Search dropdown was rendering behind overlays and getting clipped by
the header's overflow:hidden. Bump z-index to 10001 and set overflow
to visible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 19:02:04 -07:00
Jeff Emmett c8bd527e55 feat(encryptid): passkey-first login UX — zero-typing sign-in
Replace username input with primary passkey button for unscoped WebAuthn
(browser shows all stored passkeys). Email magic link as hidden fallback,
auto-revealed on NotAllowedError. Applied to both login-button.ts web
component and server-rendered auth.rspace.online page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:57:24 -07:00
Jeff Emmett 5915daf8a0 feat(rtrips): interactive AI workspace with maps, flights & route planning
Transform the AI planner right panel into an interactive workspace:
- Persistent MapLibre GL map (40% height) with pin accumulation and route lines
- Flight search results with prices, airlines, and Kiwi.com booking links
- Route cards with distance/duration from OSRM
- Nearby POI discovery via Overpass API (restaurants, hotels, attractions)
- Server-side trip tool execution via new /api/trips/ai-prompt endpoint
- Conversational system prompt that progressively builds understanding
- New lib/trip-ai-tools.ts with 4 executable tools (search_flights, get_route,
  geocode_place, find_nearby)
- Enhanced demo mode with realistic mock flights, routes, and geocode data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:56:49 -07:00
Jeff Emmett 193588443e fix(routing): eliminate /{space} from paths on subdomain routing
On subdomain routing (e.g. demo.rspace.online), the space slug belongs
only in the subdomain — never in the URL path. This fixes all server
and client code that was generating /{space}/module paths on subdomains.

Server fixes:
- index.ts: notification actionUrls, template/disabled-module redirects,
  subdomain passthrough (now redirects HTML, rewrites API), WS notifications
- output-list.ts: subdomain-aware path prefix for hrefs and fetch URLs
- shell.ts: dashboard pushState URL

Client fixes (basePath getter pattern):
- folk-book-shelf.ts, folk-splat-viewer.ts: _basePath getter
- folk-campaign-wizard.ts: basePath subdomain check
- folk-trips-planner.ts: use __rspaceNavUrl for canvas export
- rschedule/landing.ts: onclick handlers use __rspaceNavUrl
- rsplat/mod.ts: legacy view redirect subdomain check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:45:16 -07:00
Jeff Emmett 75ad3f8194 feat(rinbox): per-space email forwarding via Mailcow aliases
Provision {space}@rspace.online forwarding aliases that route to
opted-in members' personal emails. Admins/mods opted in by default;
regular members can opt in via PUT /api/spaces/:slug/email-forwarding/me.

New: space-alias-service.ts, schema tables, 8 DB functions, 6 API routes.
Hooks: rinbox onSpaceCreate/Delete, spaces.ts member lifecycle, startup migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:40:29 -07:00
Jeff Emmett 348f86c179 fix(rtrips): fit all views on one screen without page scrolling
Pin nav bar and tabs at top, make tab content scroll within the remaining
viewport height. Uses flex layout with overflow-y: auto on the content
area. Applies to list, detail, and AI planner views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:28:50 -07:00
Jeff Emmett 1eb4e1cb66 feat(rmaps): UX parity with rmaps-online — route overlay, ping cooldown, session persistence
Phase 1: Route double-layer outline, ScaleControl, route instruction summary,
Enter key in meeting search, select-all toggle in import preview, fitToParticipants FAB.
Phase 2: Ping All sidebar button, push vibrate+requireInteraction, 30s ping cooldown,
bundled QR code (qrcode package with external API fallback), ping toast with vibration.
Phase 3: Location persistence across sessions (<30min restore), auto-start sharing preference.
Also fix pre-existing TS error in community-sync.ts (bulkForget changes array typing).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:25:46 -07:00
Jeff Emmett 496dff3c7f feat(rtrips): add in-module AI planner with split-view chat + canvas export
"Plan with AI" now opens a split-view within rTrips instead of redirecting
to the canvas. Left panel: chat with model selector. Right panel: generated
trip cards (destinations, itineraries, budgets, packing lists) with
accept/discard flow. Demo mode provides realistic mock responses for Japan,
Europe, and beach queries. Accepted items export to canvas via sessionStorage
+ #trip-import hash handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:21:40 -07:00
Jeff Emmett efa5a5c315 fix(collab): read username from session.claims.username instead of session.username
The encryptid session stores username at claims.username, not at the
top level. Also falls back to the rspace-username localStorage key
that rstack-identity sets on login.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:03:01 -07:00
Jeff Emmett 3f496d9fc6 feat(rnotes,canvas): comments in demo mode, emoji reactions, reminders + inline picker modal
- rNotes comments now work in demo mode via in-memory thread storage
- Added emoji reactions (7-emoji palette) and date reminders on comment threads
- Reminders integrate with rSchedule API for persistent notifications
- Canvas toolbar: split Note into "Blank Note" (always available) and "From rNotes" (picker)
- Replaced browser prompt()-based pickFromList with showPickerModal (dark-themed, searchable, keyboard nav)
- Updated pickTrip, destination, and booking handlers to use the new modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:53:06 -07:00
Jeff Emmett 1ae0609f14 perf(canvas): batch bulk forget into single Automerge transaction
The bulk forget dialog was freezing because each shape triggered a
separate Automerge change, IndexedDB write, and WebSocket sync. New
bulkForget() method batches all shapes into one transaction with DOM
updates applied immediately for responsiveness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:52:11 -07:00
Jeff Emmett cefc1aa5b7 fix(collab): rename Solo/Share to Online/Offline, use EncryptID usernames
Swap toggle labels to Online/Offline (more intuitive). Resolve canvas
peer usernames from encryptid_session instead of rspace-username fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:45:55 -07:00
Jeff Emmett 1cbee3e4d1 fix(canvas): absolute drag positioning + remove Move Here drop ghosts
Replace movementX/Y delta accumulation with absolute mouse-to-shape offset
tracking for drift-free drag. Remove drop suggestion overlay system entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:42:50 -07:00