Commit Graph

227 Commits

Author SHA1 Message Date
Jeff Emmett 36931b2d30 fix(token-service): use known DID for jeff seed instead of cross-container API call
The directory API only returns space members, and jeff isn't in demo space.
Hardcode the known DID with SEED_JEFF_DID env var override support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:52:21 -07:00
Jeff Emmett df453d9e00 fix(token-service): use HTTP API instead of direct DB import for DID lookup
The rspace container doesn't have DATABASE_URL for the encryptid DB.
Use the /api/users/directory endpoint via HTTP to resolve jeff's DID,
with retry-on-restart if encryptid isn't reachable yet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:48:32 -07:00
Jeff Emmett ba3a0018ea feat(rwallet): add cUSDC CRDT token system with Automerge ledger
Introduces CRDT-native token infrastructure stored as Automerge documents.
Seeds 5 cUSDC to user jeff on startup. Adds token API routes and a
"Local Tokens" section in the rWallet viewer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:43:49 -07:00
Jeff Emmett f2d575d1a2 feat(shell): add consistent rApp tab bar system with URL-backed ?tab= params
Server-rendered tab bar via renderShell tabs option. Tabs use ?tab= query
params with history.replaceState and dispatch rapp-tab-change events.
Migrated rNetwork CRM from internal Shadow DOM tabs to the shared system.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:50:26 -07:00
Jeff Emmett adb0d173d8 feat(shell): add module sub-nav bar + rCart UX polish + fix TS errors
- Add secondary pill navigation bar between tab-row and <main> showing
  each module's outputPaths + subPageInfos as navigable links with
  client-side active highlighting
- Rename rcart /buy/:id route to /group-buy/:id, add payments and
  group-buys outputPaths, rename products → catalog
- Add outputPaths (mailboxes) to rinbox module
- Polish group buy page: hero stat cards, fill-up liquid progress
  visual with tier markers, warm amber→green gradient, pledge avatars,
  green CTA button, price box, responsive improvements
- Fix centering for narrow rcart form pages (flex layout in cart.css)
- Fix TS error: add walletAddress to rstack-identity SessionState type
- Fix TS errors: add ambient type declarations for 3d-force-graph and
  three (dynamically imported in folk-graph-viewer)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:44:45 -07:00
Jeff Emmett 42c6dea091 feat(canvas): image paste/drop + bookmark cards + enhanced paste/drop handlers
- Enhanced paste: clipboard images upload via /api/image-upload → folk-image shape
- Enhanced paste: URLs create folk-image (image ext) or folk-bookmark (others)
- Enhanced drop: image files upload → folk-image, URLs → bookmark/image
- Short URLs (< 20 chars) now handled instead of ignored
- Long text still goes through AI triage (existing behavior preserved)
- Updated mi-routes triage to distinguish folk-image/folk-bookmark/folk-embed
- Added folk-image + folk-bookmark to CSS selectors, SHAPE_DEFAULTS, registry
- Added zine generator link to rPubs editor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:50:25 -07:00
Jeff Emmett 5a33293a23 feat(rnetwork): implement delegative trust flows for liquid democracy
Person-to-person delegation within spaces across 5 authority verticals
(voting, moderation, curation, treasury, membership). Trust engine
recomputes scores every 5 min with time decay, transitive BFS, and
50% per-hop discount. Graph viewer shows trust-weighted node sizing
with authority selector. New Delegations tab in CRM with management
UI and Sankey flow visualization.

Schema: delegations, trust_events, trust_scores tables
API: delegation CRUD, trust scores, events, user directory
Frontend: folk-delegation-manager, folk-trust-sankey, graph trust mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:16:06 -07:00
Jeff Emmett 751a2c8e7b fix(infra): consolidate external service URLs to rspace.online (TASK-51.1)
- Replace rdata.online/collect.js with /collect.js proxy route (7 files)
- Update MAPS_SYNC_URL to wss://maps-sync.rspace.online
- Fix legacy TWENTY_API_URL to crm.rspace.online
- Add Traefik host exclusions for maps-sync, crm, analytics, newsletter
- Close TASK-23 (feature parity audit) and TASK-51.2 (301 redirects)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 19:12:51 -07:00
Jeff Emmett 1460d2b579 feat(ecosystem): implement cross-app embedding protocol (TASK-46)
Add ecosystem manifest protocol, EcosystemBridge class, server proxy
routes, port/event integration for folk-rapp, sandboxed iframe mode
with origin-validated postMessage, and SW caching for ecosystem modules.

Security: no allow-same-origin on sandboxed iframes, redirect: error
on proxy fetches, origin validation on all postMessage handlers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:32:28 -07:00
Jeff Emmett eb00579183 feat(mi): upgrade to community-focused builder with interchangeable AI
Transform MI from a small Ollama-only chat dropdown into a rich builder
panel with swappable AI backends (Gemini, Ollama, Anthropic/OpenAI stubs),
role-based permission gating, and module-spanning content actions.

- Provider abstraction layer (mi-provider.ts) with stream normalization
- Extracted MI endpoints into mi-routes.ts Hono sub-app
- New action types: create/update/delete-content, scaffold, batch
- Module routing map (mi-module-routes.ts) for rApp API integration
- Redesigned panel: fixed 520px, model selector, textarea, minimize pill
- Action confirmation for destructive ops, scaffold progress bar
- Permission validation endpoint with role-based action gating
- Better markdown rendering (headers, code blocks, links, lists)
- Cmd/Ctrl+K keyboard shortcut, collapsible action details

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:29:19 -07:00
Jeff Emmett a93d124d4b feat(shell): improve onboarding page for empty module state
Add card background, glow effect, and contextual hint explaining
the empty state. Rename "Get Started" to "Load Sample Data" with
+ icon for clarity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:02:07 -07:00
Jeff Emmett 988fc4f893 fix: handle subdomain URLs that already include space prefix
When accessing demo.rspace.online/demo/rcart/pay/123, the subdomain
router was prepending the space again, creating /demo/demo/rcart/pay/123
which returned 404. Now detects when first path segment matches the
subdomain and passes through without double-prefixing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:02:02 -07:00
Jeff Emmett 602544ecdf feat(seo): add OG/Twitter meta tags + generated OG banner image
- Add og:title, og:description, og:image, twitter:card meta tags to landing page
- Add default OG tags to renderShell for all module pages
- Generate 1024x576 OG banner image via fal.ai Flux Pro (dark indigo + network pattern)
- Update meta description: "rSpace is a local-first platform where communities own their tools, data, and governance"
- Update page title to "rSpace — Own Your Community Infrastructure"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:51:25 -07:00
Jeff Emmett fee72573ba feat: system clock heartbeat + ephemeral clock delivery (TASK-47)
Server-side SystemClock broadcasts tick/5min/hourly/daily events via
WebSocket to all connected clients. Events are ephemeral (not persisted
in CRDT). Client-side fallback clock activates when server connection
is lost.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:20:04 -07:00
Jeff Emmett 9bb00a8bab feat(rflows+rtasks): BCRG demo flow with live rTasks integration
Replace TBFF preset with 19-node BCRG Community Flow (2 sources →
central funnel → 5 person funnels → 11 outcomes). Seed matching
BCRG Outcomes board in rTasks (4 DONE, 5 IN_PROGRESS, 2 TODO).

Add SyncServer.registerWatcher() for cross-module doc change hooks.
When an rFlows outcome is marked "completed", auto-create a DONE task
in rTasks with ref:rflows:outcome:{id} deduplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:47:13 -07:00
Jeff Emmett d79d560771 feat(rsplat): interactive demo scenes + AI image-to-3D generation
Replace fake demo data with real HuggingFace CDN Gaussian splats (train,
truck, garden) that open in an inline 3D viewer without server round-trips.
Add "Generate from Image" tab that sends images to fal.ai Trellis for
AI-powered 3D model generation. Add gallery header and progress UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:29:15 -07:00
Jeff Emmett 31b088543e feat: add ViewHistory for in-app back navigation, rename rWork to rTasks
Add shared ViewHistory<V> utility class that provides a proper navigation
stack for rApps with hierarchical views. Replaces hardcoded data-back
targets with stack-based back navigation across 10 rApps: rtrips, rmaps,
rtasks, rforum, rphotos, rvote, rnotes, rinbox, rschedule, rcart.

Rename rWork module to rTasks — directory, component (folk-tasks-board),
CSS, exports, domains, and all cross-module references updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:04:13 -07:00
Jeff Emmett 2b909becdb fix(shell): move info icon to left of layer toggle in tab bar
Slot the rApp info button into the tab-bar's tab-actions area so it
appears immediately left of the view-toggle (layer icon) instead of
after it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:27:07 -07:00
Jeff Emmett 99e486b598 fix(rmeets): add camera/mic/display-capture to iframe permissions
The external app iframe was missing media permissions in its allow
attribute, preventing Jitsi from accessing camera/microphone/screen
when embedded in rMeets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:19:19 -07:00
Jeff Emmett 7177b2882c fix: deduplicate spaces dropdown, group by visibility type
Personal space (slug=username) forced to private so it doesn't appear
as both public and private. Dropdown now groups spaces: Private (red)
at top, Permissioned (yellow) middle, Public (green) bottom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:00:37 -07:00
Jeff Emmett d96130f919 feat: fix tab duplication, add info popover, add rFlows guided tour
Fix tab duplication by syncing tabBar state after layer-add, deduplicating
Automerge layers, and syncing app-switcher tabs to CommunitySync. Add info
icon popover that lazy-loads module landing page content with auto-show on
first visit. Add 5-step guided tour for rFlows with spotlight overlay,
auto-advance on click, and toolbar restart button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:04:33 -07:00
Jeff Emmett 8072b250ea feat: canvas background selector — grid, dot, or blank preference
Add user-selectable canvas background style via data-canvas-bg attribute
and CSS custom properties (--rs-canvas-bg-image, --rs-canvas-bg-size).
Three options: grid (default), dot, blank — persisted in localStorage.

- theme.css: new tokens + [data-canvas-bg] selectors
- rstack-identity.ts: Grid/Dot/Blank selector in user dropdown
- canvas.html: CSS vars, zoom-aware scaling, canvas-bg-change listener
- flows.css: use shared bg-image/bg-size vars (fixes rFlows theme bug)
- FOUC prevention in all entry points (shell.ts, create-space.html)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 18:37:50 -07:00
Jeff Emmett a7063d24f5 feat: PWA support — installable app, Web Push notifications, app badge
Phase 1: Installable PWA
- Add web app manifest with multi-size icons (192, 512, maskable, apple-touch)
- Add PWA meta tags to all entry points (shell.ts, canvas.html, index.html, create-space.html)
- Register service worker on all pages (previously only canvas.html)
- Add manifest.json to precache core list
- Capture beforeinstallprompt for custom install UX

Phase 2: Web Push Notifications
- Add web-push dependency + push_subscriptions DB table
- VAPID key endpoint, subscribe/unsubscribe routes in notification-routes.ts
- Web Push delivery in notify() with auto-cleanup of expired subscriptions
- SW push + notificationclick event handlers
- Client push subscription flow in notification bell component

Phase 3: Install UX Polish
- App badge (setAppBadge/clearAppBadge) on unread count changes
- "Enable push" button in notification panel header

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:35:30 -07:00
Jeff Emmett b2347ec418 feat: per-rApp inline config + module-aware settings panel
Add <rstack-module-setup> component for inline module configuration
(replaces static "Not Configured" instructions). Enhance settings
gear panel to show the current module's settingsSchema at the top.
Pass module-id through shell rendering and tab-cache switching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:45:48 -07:00
Jeff Emmett 49f55dffc8 fix: resolve 500s on notifications, cache errors in SW, and [object Object] on-ramp alert
- Notification routes: wrap GET / and GET /count in try-catch, return
  graceful fallbacks instead of 500s when DB table is missing/unavailable
- getUnreadCount: add null safety (row?.count ?? 0) and catch DB errors
- Service worker: add .catch(() => {}) to all cache.put() calls to
  suppress NetworkError on quota-exceeded or corrupted cache entries
- On-ramp error display: coerce err.error to string so alerts show the
  actual message instead of [object Object]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:31:14 -07:00
Jeff Emmett c19142791e feat(rnotes): type-specific notes, voice recording, web clipper, module settings
Phase 1: All 7 note types (NOTE, CODE, BOOKMARK, CLIP, IMAGE, AUDIO, FILE)
with type-specific editors, filter bar, new-note dropdown, and demo notes.
Phase 1.5: Code Snippet and Voice Note slash commands.
Phase 2: Voice recording with 3-tier transcription cascade (server Whisper,
Web Speech API, offline Parakeet TDT), mic button in toolbar, standalone
voice recorder component, upload/transcribe/diarize server routes.
Phase 3: Manifest V3 browser extension (web clipper) retargeted to
rspace.online with slug-based routing, article unlock via Wayback/Google
Cache/archive.ph strategies.
Phase 4: Per-module settings framework — settingsSchema on modules,
moduleSettings in CommunityMeta, gear icon in space settings Modules tab,
rNotes declares defaultNotebookId setting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:39:10 -07:00
Jeff Emmett 63b4294c9c fix: use [rS] favicon.png across all server-rendered pages
Replace inline SVG emoji (🌌) favicons with /favicon.png in all four
shell renderers and both landing page renderers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 22:25:25 -07:00
Jeff Emmett 1568a5d0dc feat: user dashboard shown when all tabs are closed
When the last tab is closed, a dashboard appears showing the user's
spaces (sorted by most recent visit), notifications, and quick actions.
Clicking any item creates a new tab and hides the dashboard. Browser
back/forward handles dashboard state correctly.

Also adds proper cache headers for HTML and Vite-hashed assets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:55:39 -07:00
Jeff Emmett 0cf1db56f4 feat(rmeets): register rMeets as rApp with Jitsi embed
Adds rMeets module with hub page (Quick Meet, Join Room, Jitsi Lobby)
and room pages that embed jeffsi.localvibe.live via renderExternalAppShell.
Jitsi URL configurable via JITSI_URL env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:54:10 -07:00
Jeff Emmett 0b58ff364b fix(auth): sync .well-known/webauthn origins with EncryptID server
The main server's Related Origins list was stale — it listed 5 generic
r*.online domains instead of the priority domains where passkey ceremonies
actually happen. This caused p2pf socials (socials.p2pfoundation.net) and
other external domains to fail WebAuthn authentication because browsers
couldn't verify them as related origins for RP ID rspace.online.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:27:31 -07:00
Jeff Emmett 2ecea4ebb8 feat: history panel with author attribution + settings gear relocation
Move settings gear to header right (next to identity) on all pages.
Add history clock button in header left that opens a new slide-out
history panel with Activity feed and Time Machine tabs. Embed author
identity (DID, username, timestamp) in Automerge change messages via
JSON envelope, with backward-compatible parsing for old plain strings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:24:27 -07:00
Jeff Emmett 20c26cd3d7 feat: scope system, cross-space navigation, and spaces-as-layers
Phase 1 — Fix scope system: new scope-resolver.ts resolves global vs
space-scoped docId prefixes. Server middleware sets effectiveSpace on
Hono context. All 18 modules updated to use dataSpace for Automerge
doc access while keeping space for display. Client runtime gets
setModuleScopes() and resolveDocSpace() for local-first scope
resolution.

Phase 2 — Seamless cross-space navigation: TabCache now tracks panes
per space:module key. OfflineRuntime maintains lazy WebSocket
connections per space. Space-switcher dispatches space-switch event
handled client-side with history.pushState instead of full reload.

Phase 3 — Spaces as layers: Layer type extended with spaceSlug and
spaceRole. Tab bar gains "Add Space Layer" picker. Canvas renders
cross-space shapes with visual indicators. Space layers persisted as
SpaceRefs via nesting API. Runtime provides getAllActiveSpaces() and
subscribeModuleAcrossSpaces() for module-level data aggregation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 06:33:32 +00:00
Jeff Emmett bc139de0cc feat: add Image Studio for brand-consistent img2img generation
New folk-image-studio canvas shape with multi-image style analysis
(Gemini vision), img2img via fal.ai FLUX and Gemini Nano Banana models,
and image attachment support in folk-prompt chat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:31:27 -08:00
Jeff Emmett b591267b81 feat: remove title/header image, add Twitter-style link previews
Remove the title input and header image upload/generate section from
the thread builder editor. Title is now auto-derived from first tweet.

Add link preview cards that render inline in tweet content, similar to
Twitter's URL card unfurling. Server-side /api/link-preview endpoint
fetches OG metadata (title, description, image) with caching.

URLs in tweet text are rendered as clickable links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:04:58 -08:00
Jeff Emmett 92dff99793 fix: thread image 404 on subdomains + move photo section to top
Pass /data/ paths through subdomain routing without rewriting so
generated image files are accessible on *.rspace.online subdomains.

Move image upload/generate section above the compose textarea in the
thread builder editor layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 18:00:58 -08:00
Jeff Emmett aff16e647a feat: content-hash cache busting for module/shell assets
Build generates SHA-256 content hashes per asset file and appends
?v=<hash> to all module/shell URLs in rendered HTML automatically.
Eliminates manual ?v=N bumping in mod.ts files. Versioned assets
get Cache-Control: immutable headers, and the service worker cleans
stale entries on activation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:50:57 -08:00
Jeff Emmett feabf89137 feat: add MI Content Triage — paste/drop content for AI-powered shape layout
Adds a "dump & layout" feature where users can paste or drag-drop unstructured
content onto the canvas and have Gemini 2.5 Flash analyze it, classify each piece
into the appropriate folk-* shape type, and propose a multi-shape layout with
semantic connections.

- POST /api/mi/triage endpoint with structured JSON output from Gemini
- TriageManager orchestrator (analyze, removeShape, commitAll via MiActionExecutor)
- MiTriagePanel floating preview UI with shape cards, connections, Create All/Cancel
- Canvas drag/drop overlay + paste handler integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:50:44 -08:00
Jeff Emmett 991c0ed8a5 chore: remove rDocs and rDesign from module registry
Placeholder modules not yet built out as full rApps. Removes them
from the dropdown/tab bar until they have proper schemas, components,
and local-first support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 19:36:10 -08:00
Jeff Emmett 3c26addeae fix: defer tab bar active state until switchTo() resolves
The tab bar was setting its `active` attribute synchronously on click,
before TabCache.switchTo() finished fetching and injecting the new pane.
This caused a visual desync where the tab highlighted immediately but
the content area showed a blank flash or stale content.

Now the tab bar dispatches the layer-switch event without changing its
own active state. The shell event handler sets active only after
switchTo() confirms the pane is ready, eliminating the race condition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 19:32:38 -08:00
Jeff Emmett 4cc420d0f6 feat: wire offline-first Automerge sync to all 13 rSpace modules
Add shared RSpaceOfflineRuntime singleton that coordinates IndexedDB
persistence (EncryptedDocStore), WebSocket sync (DocSyncManager), and
in-memory Automerge docs (DocumentManager) for all module web components.

- Phase 0: runtime.ts singleton, shell integration, beforeunload flush
- Phase 1: rstack-offline-indicator status dot in shell header
- Phase 2: service worker stale-while-revalidate for API GETs + offline fallback
- Phase 3: storage-quota.ts with LRU eviction (30d) and quota warnings (70%)
- Phase 4: Tier 1 single-doc modules (rFlows, rCal, rBooks, rSplat)
- Phase 5: Tier 2 multi-doc modules (rNotes, rWork, rInbox, rVote, rTrips, rFiles)
  with doc-list-request/response wire protocol for document discovery
- Phase 6: Tier 3 special cases (rCart hybrid, rForum global doc, rSchedule)

Data now loads instantly from IndexedDB, syncs via WebSocket when online,
and remains browsable offline. rNotes migrated from inline Automerge WS
to shared runtime. All modules fall back to REST when runtime unavailable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 19:07:59 -08:00
Jeff Emmett 3b3eecdddb fix: stop demo→personal space redirect and clean up space switcher
Logged-in users visiting demo.rspace.online were auto-redirected to
their personal space on page load. Now only provisions the space
silently without redirecting. Also removes the redundant "Public
spaces" section from the dropdown and filters the /api/spaces endpoint
to only return demo, user's own spaces, and permissioned spaces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:02:00 -08:00
Jeff Emmett 2bc1b78f30 fix: make active tab local-only, stop Automerge from overriding it
The active tab was stored in Automerge's shared doc (activeLayerId),
causing different browser windows/sessions to fight over which tab
is highlighted. When one window switched to rInbox, another window
showing rFlows would have its tab bar update to highlight rInbox
while still displaying rFlows content.

Changes:
- Active tab is now always determined locally by the URL/currentModuleId
- Automerge sync only manages the tab LIST (which modules are open)
  and flows, not which tab is active
- Removed sync.setActiveLayer() calls on tab switch
- Removed activeLayerId reads from Automerge on connect and on
  remote change events
- TabCache continues to manage active state correctly when switching
  tabs within the same page load

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:49:40 -08:00
Jeff Emmett 707d83525b fix: responsive header dropdowns + space switcher on all pages
- Remove overflow:hidden from header__left on mobile (was clipping
  app-switcher and space-switcher triggers)
- Add white-space/overflow/text-overflow to both trigger buttons so
  they truncate gracefully on narrow screens
- Add <rstack-space-switcher> to module landing and sub-page info
  shells so the spaces dropdown always appears next to the rApps dropdown

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 16:46:40 -08:00
Jeff Emmett 59bdd741be feat: bare-domain sub-pages show info/marketing pages + save-gate
Bare-domain URLs like rspace.online/rsocials/thread now render an info
page with CTAs instead of silently serving the functional app. The
functional app only appears inside a {space} context (e.g.
demo.rspace.online/rsocials/thread). API routes still pass through.

- Add SubPageInfo interface to shared/module.ts
- Add renderSubPageInfo() renderer to server/shell.ts
- Modify bare-domain routing: api/ passthrough → info page → demo fallback
- Add subPageInfos to 8 modules (rsocials, rflows, rnetwork, rtrips,
  rbooks, rphotos, rinbox, rsplat)
- Add window.__rspaceSaveGate() auth prompt on write operations
- Wire save-gate into rsocials Thread Builder save handler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:16:17 -08:00
Jeff Emmett abb3f57ca0 fix: space settings panel hidden behind canvas due to backdrop-filter containment
Move <rstack-space-settings> outside the header element so its position:fixed
is relative to the viewport instead of the 56px header (backdrop-filter creates
a containing block for fixed descendants). Bump panel z-index above all canvas
elements. Also migrate hardcoded colors to CSS theme variables across shell
components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:30:20 -08:00
Jeff Emmett 495baa5935 fix: allow unauthenticated thread builder save/share operations
The space role middleware was blocking all POST/PUT requests from
unauthenticated users with a 403, preventing the thread builder's
save draft and share buttons from working. Added publicWrite module
flag to bypass the role check for modules with public API endpoints.
Also fixed saveDraft() to properly surface server errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:57:59 -08:00
Jeff Emmett a6008a4f2d refactor: complete rfunds → rflows rename across configs and references
Update docker-compose, vite config, Traefik labels, module imports,
and all cross-module references to use the new rflows naming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:13:14 -08:00
Jeff Emmett cdfe8c5b78 feat: add unified notification system with real-time WS delivery
Persistent, PostgreSQL-backed notification system replacing the in-memory
access request polling. Notifications are created via notify(), persisted
to DB, and delivered in real-time over WebSocket with a 30s polling fallback.

Infrastructure:
- notifications + notification_preferences tables in EncryptID schema
- 10 CRUD functions in db.ts (create, list, count, read, dismiss, etc.)
- notification-service.ts: core notify(), WS registry, notifySpaceAdmins()
- notification-routes.ts: REST API at /api/notifications
- rstack-notification-bell.ts: bell icon component with dropdown panel

Module integration (11 hooks):
- spaces.ts: access_request, access_approved, access_denied, member_joined,
  member_left, role_changed
- index.ts WS handler: ping_user (24h expiry)
- encryptid/server.ts: guardian_accepted, recovery_initiated (owner + guardians),
  recovery_approved

Legacy cleanup:
- Removed access request polling, badge, and approve/deny UI from
  rstack-identity.ts (now handled by notification bell)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 18:59:09 -08:00
Jeff Emmett 15be495e91 feat: add SpaceConnection primitive + default visibility to private
Introduces bilateral typed inter-space connections (economic, trust,
data, governance, resource) stored in both spaces' Automerge docs.
Includes connection policy, approval flow, membrane permeability
endpoint, and full CRUD API. Also changes default space visibility
from public to private for all user-facing creation paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:05:23 -08:00
Jeff Emmett c55e28a400 style: gradient background + (you)rSpace wordmark on landing page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:58:15 -08:00
Jeff Emmett 59b1ae2d05 feat: add rSchedule module — persistent cron-based job scheduling
New module providing in-process, Automerge-backed job scheduling to
replace system-level crontabs. Includes email, webhook, calendar-event,
broadcast, and backlog-briefing action types with a 60-second tick loop.

- modules/rschedule/ — schemas, mod, landing page, web component UI
- Seed jobs: morning/weekly/monthly backlog briefings
- SMTP env vars added to docker-compose for email actions
- ONTOLOGY.md updated (26+ modules, rSchedule in Planning & Spatial)
- Also: Twenty CRM docker-compose aligned to rspace-internal network

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:34:53 -08:00
Jeff Emmett 80e42596b3 fix: normalize visibility enums + tab tracking across remaining files
Update remaining references from legacy 4-value visibility model
(public/public_read/authenticated/members_only) to simplified 3-value
model (public/permissioned/private) in rInbox, rVote, identity component,
admin panel, and create-space page. Add tab trackRecent calls in shell.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:29:01 -08:00
Jeff Emmett eb2859d849 refactor: normalize space visibility enums + inline space create form
Align visibility values across server and UI to the canonical set:
public, permissioned, private (replacing public_read, authenticated,
members_only). Add inline space creation form to the space switcher
dropdown and tab bar instead of navigating to /new.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:27:31 -08:00
Jeff Emmett 6801916c60 feat: conviction voting button handler, server import cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:21:36 -08:00
Jeff Emmett 06f7d67cd3 chore: slash-command refinements, server import fixes, misc cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:21:04 -08:00
Jeff Emmett b52aa8298b feat: conviction voting component, rNotes refinements, space visibility endpoints
- Add folk-choice-conviction library and register in lib/index
- Refactor rNotes app layout and interaction
- Space visibility normalization in server/spaces
- Minor canvas.html tweaks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:19:45 -08:00
Jeff Emmett daa6013fd0 fix: add migrateVisibility runtime migration, fix participant→member role label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:17:53 -08:00
Jeff Emmett 0d8d8202a5 fix: normalize legacy space visibility values to 3-type model
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:16:06 -08:00
Jeff Emmett 35a5a5f29a feat: workflow template, choice components, space settings, EncryptID vault, UI polish
- Pre-populated 4-node workflow template (trigger→action→condition→output) with blue arrows
- Add folk-choice-vote, folk-choice-rank, folk-choice-spider component libraries
- New rstack-space-settings component
- EncryptID encrypted vault schema and server endpoints
- Space management and community store enhancements
- Shell, landing, and module CSS refinements
- Tab bar, app switcher, identity, and MI component updates
- rNotes app improvements
- rFunds diagram adjustments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:15:13 -08:00
Jeff Emmett 8bd899d146 fix: persist theme via html[data-theme] + theme.css custom properties
- Blocking <head> script restores canvas-theme from localStorage
  with prefers-color-scheme fallback (no FOUC)
- New theme.css with CSS custom properties for dark/light
- Removed data-theme from body/header/tab-row (now on <html>)
- Theme toggle writes to documentElement instead of body

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:56:51 -08:00
Jeff Emmett b77fb30001 fix: persist light/dark theme preference across sessions
Restore canvas-theme from localStorage on page load with a blocking
script before first paint (body) and a fixup for header/tab-row.
Applied to all three shell renderers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:50:49 -08:00
Jeff Emmett 91cafc92ce fix: cursor world-coords, loading skeleton, WebSocket readyState guard
- Convert cursor positions to canvas world coordinates (screen→world on
  send, world→screen on render) so remote cursors appear at correct
  canvas locations regardless of pan/zoom
- Add PresenceManager.setCamera() to reproject cursors on pan/zoom
- Add loading spinner overlay dismissed on first cache hit or sync
- Guard WebSocket open handler with readyState check after async load

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 10:40:13 -08:00
Jeff Emmett fef419f572 fix: folk-wrapper crash, service worker API exclusion, fal.ai endpoint
- folk-wrapper: createRenderRoot crashed because innerHTML="" removed the
  slot from DOM, making parentElement null on the next line. Save parent
  ref before clearing.

- sw.ts: module API paths (/space/module/api/...) weren't excluded from
  caching. Changed startsWith("/api/") to includes("/api/"). Also fixed
  catch handler returning undefined instead of a Response.

- image-gen: changed queue.fal.run to fal.run for synchronous responses.
  The queue endpoint returns request_id, not the actual image data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:36:15 -08:00
Jeff Emmett ebdda1e443 feat: enhanced rinbox multisig approval UI, module landing pages, help guide
- Rinbox: visual multisig approval cards with signer avatars, progress bars,
  email previews, status-colored borders, and compose-for-approval form
- Rinbox: help/guide popout with feature cards, how-it-works steps, use cases
- Rinbox: rich demo data with threaded comments, signer lists, multiple mailboxes
- Module landing pages: improved UX descriptions for rBooks, rCal, rNotes,
  rTrips, rVote, rWork with proper feature descriptions
- Added landingPage support to RSpaceModule interface and server routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:05:08 -08:00
Jeff Emmett e3c4d74b1a fix: update Gemini model names from deprecated -exp to current versions
gemini-2.0-flash-exp was removed from the API. Updated to:
- gemini-2.5-flash for text generation
- gemini-2.5-pro for outline/reasoning
- gemini-2.5-flash-image for image generation with responseModalities

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:43:42 -08:00
Jeff Emmett 74a5142349 feat: Gemini AI integration + zine generator + fix Ollama network
- Add /api/prompt multi-provider endpoint (Gemini Flash/Pro + 4 Ollama models)
- Add /api/gemini/image with fallback cascade (gemini-2.0-flash → imagen-3.0)
- Add /api/zine/outline, /api/zine/page, /api/zine/regenerate-section
- Create folk-zine-gen.ts: 8-page MycroZine generator with editable text
  and per-section regeneration (text + image independently)
- Update folk-prompt.ts: multi-provider model dropdown (Gemini + Ollama)
- Update folk-image-gen.ts: add Gemini provider toggle + new styles
- Connect rspace to ai-internal Docker network for Ollama access
- Fetch GEMINI_API_KEY from Infisical claude-ops/ai (no plaintext secrets)
- Update entrypoint.sh: dual Infisical project support (primary + AI)
- Install @google/generative-ai, @google/genai SDKs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:27:11 -08:00
Jeff Emmett 6d1661a4f3 feat: template seeding system for new spaces
Every non-demo space gets generic "Getting Started" content (~25 shapes)
covering all rApp modules so users see what each module can do immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:03:45 -08:00
Jeff Emmett dfa09a39f6 feat: email invite endpoint, canvas share panel, backlog task-77 done
- Add POST /:slug/invite email endpoint (nodemailer via Mailcow SMTP)
- Add share badge + panel UI to canvas whiteboard
- Mark task-77 (encrypted VPS backup) as Done with updated references

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:39:43 -08:00
Jeff Emmett 606c60c511 fix: remove auto-redirect from demo space when logged in
Logged-in users visiting demo.rspace.online were auto-redirected to
their personal subdomain. Remove this redirect so the demo stays
accessible regardless of auth state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:25:41 -08:00
Jeff Emmett 46c2a0b035 feat: layered local-first data architecture — encrypted backup, relay persistence, at-rest encryption
Implement the 4-layer data model (device → encrypted backup → shared sync → federated):

- Extract shared encryption-utils from community-store (deriveSpaceKey, AES-256-GCM, rSEN format)
- Encrypt module docs at rest when space has meta.encrypted === true
- Fix relay mode persistence: relay-backup/relay-restore wire protocol + .automerge.enc blob storage
- Add backup store + REST API (PUT/GET/DELETE /api/backup/:space/:docId) with JWT auth
- Add client BackupSyncManager with delta-only push, full restore, auto-backup
- Wire backup stubs in encryptid-bridge to BackupSyncManager
- Add rspace-backups Docker volume
- Create docs/DATA-ARCHITECTURE.md design doc with threat model and data flow diagrams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:09:07 -08:00
Jeff Emmett 5ee59f86d6 feat: people online panel — live peer presence on canvas
- community-sync: re-announce on reconnect, handle peer-list/joined/left/ping events
- presence: export peerIdToColor helper
- server: track peer announcements, broadcast join/leave, relay ping-user
- canvas: people online badge + expandable panel with avatar dots and ping button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:45:57 -08:00
Jeff Emmett 22db2f439f feat: client-side encryption wiring + space scoping UI (Phase 5+6)
Phase 5 — EncryptID → DocCrypto bridge:
- Add EncryptedDocBridge connecting WebAuthn PRF to document encryption
- Add per-doc relay mode to SyncServer (encrypted spaces bypass participant mode)
- Wire encryption toggle to syncServer.setRelayOnly() on PATCH /:slug/encryption
- Restore relay mode for encrypted spaces on server startup
- Initialize DocBridge from PRF on login, clear on sign-out (both login-button + identity)
- Use bridge helpers for encrypted backup toggle in My Account

Phase 6 — Space scoping UI:
- Add "Modules" tab to Edit Space modal (enable/disable modules, scope toggles, encryption)
- Auto-filter app switcher by space's enabledModules via renderShell()
- Show "G" badge on global-scoped modules in app switcher
- Show lock icon in header for encrypted spaces
- Add getSpaceShellMeta() helper for auto-populating shell options

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:50:16 -08:00
Jeff Emmett 6a7f21dc19 feat: rNotes local-first pilot migration (Phase 2)
Migrate rNotes from PostgreSQL to Automerge local-first stack with
dual-write support. Reads go Automerge-first with PG fallback; writes
go to both backends during the migration window.

- Add Automerge schemas for NotebookDoc (schemas.ts)
- Add lifecycle hooks (onInit, onSpaceCreate) to rnotes module
- Dual-write all 8 API routes (notebooks + notes CRUD)
- Add NotesLocalFirstClient wrapping DocSyncManager + EncryptedDocStore
- Enhance migration runner with --dry-run, --module, --verify flags
- Add listDocs() to SyncServer

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:51:31 -08:00
Jeff Emmett b2ea5e04cf feat: unified space lifecycle & module scoping contract (Phase 0+1)
Extend RSpaceModule with scoping, lifecycle hooks (onInit, onSpaceCreate/Delete
with SpaceLifecycleContext, onSpaceEnable/Disable), and DocSchema support.
Add scoping to all 25 modules (8 space, 11 global-configurable, 6 global-fixed).
Consolidate 4 space creation endpoints into shared createSpace() function.
Add enabledModules enforcement middleware and module configuration API
(GET/PATCH /api/spaces/:slug/modules). Deprecation header on /api/communities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:35:41 -08:00
Jeff Emmett 4ebbf9f116 feat: add Copy to Space context menu for shapes
Right-click shapes (single or multi-selected) to copy them to another
space the user owns or is a member of. Server endpoint handles ID
remapping, arrow reference preservation, and position centering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:58:44 -08:00
Jeff Emmett a402caacd8 fix: app-switcher routes through tab system + canvas fills viewport in tab pane
- App-switcher now dispatches module-select event instead of full page navigation
  for same-origin links; shell routes through TabCache for instant tab switching
- Tab pane gets height:100% in canvas-layout mode so #canvas fills the viewport
  (fixes pan/zoom not working on empty canvas background)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:35:38 -08:00
Jeff Emmett 74b15ba1b7 feat: add x402 test endpoint and payment test script
Add POST /api/x402-test — a standalone payment-gated endpoint with
no auth required, for testing the x402 flow end-to-end.

Add scripts/test-x402.ts using @x402/fetch to automatically handle
the 402 → sign → retry cycle on Base Sepolia.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 00:28:55 -08:00
Jeff Emmett 15812195f1 fix: set canvas-layout class on initial server render
When loading the rspace canvas directly (not via tab navigation),
#app lacked the canvas-layout class. Without it, #canvas collapses
to 0 height and pointer events for panning miss the canvas element.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:33:55 -08:00
Jeff Emmett 3808b51a64 feat: strip demo pages to show just the interactive component
Demo pages now render the same clean shell as regular spaces — just the
<folk-*> component full-page, no marketing wrapper (hero, feature cards,
CTA). Descriptions belong on landing pages, not demos.

- Remove demo branch from 7 module route handlers (rcal, rcart, rfunds,
  rnotes, rtrips, rtube, rvote)
- Delete 7 demo.ts files (~1200 lines of dead markup)
- Remove renderDemoShell() and DEMO_PAGE_CSS from server/shell.ts
- Remove demoPage field from RSpaceModule interface
- Rename top rApp dropdown item from "rSpace" to "rStack"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:03:46 -08:00
Jeff Emmett a39cf6e1c2 feat: auto-provision personal spaces on first visit + redirect logged-in users from demo
Server-side middleware creates the user's personal space when they visit
{username}.rspace.online for the first time (token in cookie, verified once).
Client-side redirect sends logged-in demo users to their personal space.
"Try Demo" button sets a sessionStorage flag to bypass the redirect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:31:32 -08:00
Jeff Emmett b66e9b44de feat: hide "Try Demo" header button when logged in
The header demo button is now hidden via data-hide when the user has
an active EncryptID session. Reacts to auth-change events so it
appears on logout and disappears on login without page reload.
Landing page hero CTAs already swap to "Go to My Space" when logged in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:16:59 -08:00
Jeff Emmett 5408eb0376 feat: add outputPaths to module interface and browsable list pages
Add OutputPath type to RSpaceModule so each module declares what content
types it produces (e.g. notebooks, routes, campaigns). Auto-generate
browsable list pages at /:space/:moduleId/:path that render a card grid
inside the standard shell, fetching items from the module's API.

Declares outputPaths across 23 modules (rwallet/rinbox skipped).

Move campaign demo from standalone campaign-demo space to
/rsocials/campaign route with a dedicated timeline view and
/api/campaigns endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:55:29 -08:00
Jeff Emmett 317bc46de6 feat: three-state FUN — present, forgotten (faded), deleted
Shapes now have three states instead of two. "Forgetting" a shape fades
it (35% opacity, greyscale) for all connected clients rather than hiding
it. Other users can then choose to "forget too", "remember" (restore),
or "delete" (hard-remove from DOM). A forgottenBy map tracks who forgot,
enabling social signaling around shared attention.

- folk-shape.ts: :state(forgotten) CSS + forgotten property
- community-sync.ts: forgetShape(id,did), rememberShape, hardDeleteShape,
  getShapeVisualState, hasUserForgotten, getFadedShapes, getDeletedShapes
- community-store.ts: forgottenBy map server-side, rememberShape clears map
- canvas.html: right-click context menu, two-section memory panel (Fading/
  Deleted), close button fades instead of removes, Delete key escalates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:44:02 -08:00
Jeff Emmett 2bbe50991d fix: exclude server paths from space-to-subdomain redirect
The bare-domain routing logic was redirecting all multi-segment paths
like /api/modules → api.rspace.online/modules. Add exclusion for
known server path prefixes (api, admin, admin-data, admin-action,
.well-known) so they fall through to Hono route handlers instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:11:49 -08:00
Jeff Emmett 85ac897a1a fix: use single-segment admin endpoints to bypass Cloudflare redirect
Cloudflare has a wildcard rule that redirects any multi-segment path
on rspace.online to a subdomain (e.g. /foo/bar → foo.rspace.online/bar).
This broke both /api/* and /admin/api/* paths.

Replace with single-segment endpoints:
- GET /admin-data — returns spaces + modules (admin-only)
- POST /admin-action — handles mutations like delete-space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:58:37 -08:00
Jeff Emmett caae204c2b fix: bypass Cloudflare /api/* redirect for admin dashboard
Cloudflare has a redirect rule that rewrites rspace.online/api/* to
http://api.rspace.online/*, causing Mixed Content errors in the browser.
Add a separate /admin/api router that serves the same admin data at
paths that don't trigger the redirect rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:51:23 -08:00
Jeff Emmett b12cc52892 feat: admin dashboard with user management and delete capabilities
- Add tabbed admin UI (Spaces | Users) with auth gate
- Add admin API endpoints on EncryptID: list users, delete user, clean space members
- Add admin force-delete space endpoint on rSpace (bypasses owner check)
- Protect all admin endpoints with ADMIN_DIDS env var
- Add ADMIN_DIDS to both Docker Compose configs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:30:21 -08:00
Jeff Emmett f8c51fad0b fix: move /notifications and /admin routes before /:slug wildcard
Hono matches routes in definition order, so /:slug was catching
"notifications" and "admin" as slug params and returning 404.
Static routes must be defined before parameterized routes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:54:27 -08:00
Jeff Emmett 1db8341fb2 feat: email forwarding via Mailcow aliases + private space access gate
Email forwarding (EncryptID):
- New mailcow.ts API client for alias CRUD via Mailcow REST API
- Schema: email_forward_enabled + email_forward_mailcow_id columns
- API endpoints: GET/POST email-forward status, enable, disable
- Profile email change hook updates/disables alias automatically
- Docker: rmail-mailcow network + MAILCOW_API_URL/KEY env vars

Private spaces:
- Access gate overlay blocks members_only spaces for unauthenticated users
- Space visibility injected into HTML via middleware
- Auto-provision creates spaces as members_only by default
- Personalized "Create {username}'s Space" CTA in space switcher
- Removed unused /notifications endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:54:07 -08:00
Jeff Emmett 75b148e772 Merge branch 'dev'
# Conflicts:
#	modules/rcal/mod.ts
#	modules/rfiles/mod.ts
#	modules/rforum/mod.ts
#	modules/rmaps/mod.ts
#	modules/rnetwork/mod.ts
#	modules/rswag/mod.ts
#	modules/rwork/mod.ts
#	shared/module.ts
2026-02-28 19:51:51 -08:00
Jeff Emmett 5613370817 refactor: rename module directories to match r-prefixed module IDs
All 22 module directories under modules/ now match their module IDs
(e.g. modules/cart → modules/rcart, modules/canvas → modules/rspace).
Updated all import paths, vite build config, HTML template asset refs,
docker-compose standalone commands, and .gitignore accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:49:26 -08:00
Jeff Emmett abbfb552cc feat: client-side tab caching for instant tab switching
Previously loaded tabs stay in the DOM and are shown/hidden via CSS.
New tabs are fetched via fetch() + DOMParser on first visit, then
cached. Switching back is instant with no network request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:21:10 +00:00
Jeff Emmett d9bd7557fa fix: dropdown menus use fixed positioning to escape overflow clipping
Dropdown menus in app-switcher and space-switcher were clipped by
overflow:hidden on .rstack-header__left (mobile). Changed from
position:absolute to position:fixed with dynamic getBoundingClientRect
positioning. Bumped shell asset versions to v=5 to bypass CF cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:36:18 +00:00
Jeff Emmett bf1d126ee5 fix: prevent double space prefix in dashboard links on subdomains
Dashboard card hrefs were /{space}/{moduleId}, causing double-prefix
(/demo/demo/rbooks) when accessed via demo.rspace.online subdomain
routing. Now renders /{moduleId} and resolves via __rspaceNavUrl on
the client for cross-context compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 09:04:47 +00:00
Jeff Emmett db078d3152 feat: embed external apps via iframe in rSpace shell
Add ?view=app iframe integration for 4 existing modules (rNetwork→Twenty CRM,
rSocials→Postiz, rForum→Discourse, rFiles→Seafile) and 2 new modules
(rDocs→Docmost, rDesign→Affine). Each module shows its demo view by default
with an "Open Full App" button to switch to the iframe-embedded external app.

Also includes: splat demo data seeding, MI search bar mobile layout fix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 08:56:08 +00:00
Jeff Emmett e55e56bc06 feat: move search bar to second row on mobile header
On screens <= 640px, the header wraps to two rows: logo/app-switcher
and identity on top, "Ask Mi Anything" search bar full-width below.
Header and tab row switch from fixed to sticky positioning on mobile,
eliminating the need for magic padding-top values on #app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:17:38 +00:00
Jeff Emmett 9db9c89bed fix: dark background on all demo pages + calendar mobile improvements
Shell CSS: add body background (#0f172a) so all module pages have the
dark theme instead of transparent/white on mobile. Add mobile media
queries for #app padding and nav wrapping.

Calendar: add day-detail panel that opens on tap (crucial for mobile
where event labels are hidden). Improve touch targets, add source
badges in event modal, shorter weekday headers for narrow screens.

Cache-bust shell.css, cal JS, and swag JS via ?v=2 query params to
bypass Cloudflare edge cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 07:10:40 +00:00
Jeff Emmett 01fa8b1ba5 feat: enhance demo modes across 12 modules + add inbox/sharp/x402 deps
Improve interactive demos for notes, maps, network, vote, calendar,
choices, trips, work, books, wallet, and inbox modules with richer
mock data and better mobile responsiveness. Update server routing
and landing page. Add sharp, imapflow, mailparser, and x402 dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 06:48:51 +00:00
Jeff Emmett 5b7ee71eb9 fix: case-insensitive module routing for mixed-case URLs
rTrips, rFunds, rVote etc. now resolve correctly — normalizes module
ID to lowercase in subdomain routing, bare-domain routing, and 404
fallback checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 04:38:42 +00:00
Jeff Emmett c59b7d85a1 feat: replace static landing page with server-rendered main landing
Replace the 177KB static Next.js landing with a server-rendered page using
the same shell, theme, and rl-* CSS utilities as all module landings. Fixes
the 354KB logo.png → 1.6KB favicon.png glitch across all pages. Dynamic
ecosystem grid is always in sync with registered modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 03:48:17 +00:00