Commit Graph

1317 Commits

Author SHA1 Message Date
Jeff Emmett c35f39380e feat(rflows): replace drain valve bar with rotary knob, move allocations to panel
- Add renderDrainKnob() with rotating handle matching source valve style
- Remove rectangular ◁ $/mo ▷ drag bar and split control overlays from canvas
- Add editable range sliders in inline config Allocations tab
- Rewire drag handler for live knob rotation during drain rate adjustment
- Clean up dead split-divider CSS and event listeners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:38:59 -07:00
Jeff Emmett 8635b54800 fix(rflows): eliminate SVG NaN errors via comprehensive data sanitization
Added safeNum() + migrateNodeData() to sanitize all numeric fields (including
positions and allocation percentages) at every data loading boundary. The nullish
coalescing operator (??) doesn't catch NaN, so corrupted Automerge/localStorage
data cascaded NaN through pipe positions, port coordinates, and edge paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:14:26 -07:00
Jeff Emmett 2d28252f1a feat(rwallet): replace S-curve flows with L-curve right-angle flows in timeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:03:23 -07:00
Jeff Emmett ef65ec49ff chore(rnotes): bump JS/CSS cache version to v=4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:45:26 -07:00
Jeff Emmett a83c714f5a fix(auth): username-first flow in rstack-identity sign-in modal
The actual login UI lives in rstack-identity.ts, not login-button.ts.
Added username input to the sign-in modal, pass allowCredentials from
server to WebAuthn so the browser auto-selects the matching passkey.
Shows "No account found" if username not recognized. Enter key support
and auto-focus on the username field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:44:39 -07:00
Jeff Emmett 0e9ca3ec30 feat(rnotes): convert to Docmost-style persistent sidebar layout
Replace 3-step drill-down navigation (notebook grid → note list → editor)
with a persistent sidebar showing collapsible notebook tree alongside the
editor. Sidebar supports search, per-notebook note lists, hover add buttons,
and active note highlighting. Mobile collapses to slide-in overlay <768px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:43:21 -07:00
Jeff Emmett 3655632e0f fix(auth): check cross-subdomain cookie in access gate and dashboard redirects
The access gate and space dashboard redirect scripts checked only
localStorage, which is per-origin. When navigating between subdomains
(e.g. demo → jeff), the session wasn't found. Now both scripts also
check the eid_token cross-subdomain cookie and sync it to localStorage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:24:30 -07:00
Jeff Emmett 5f25ae02e1 fix(rsocials): use checkboxes for campaign wizard platform selectors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:22:49 -07:00
Jeff Emmett 4e6d0b885b fix(rdesign): chat messages top-to-bottom, input at bottom, no page scroll
Move chat input below messages container so conversation flows naturally
top-to-bottom. Add overflow:hidden on html/body to prevent page scrolling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:16:07 -07:00
Jeff Emmett bf0661fab2 feat(cad): LLM-orchestrated MCP tool-calling for KiCad and FreeCAD
Add Gemini Flash agentic loop that converts natural language prompts
into real MCP tool call sequences for PCB design (KiCad) and parametric
CAD (FreeCAD). Dynamic schema conversion from MCP tools to Gemini
function declarations, 8-turn/60s loop with real execution and result
feedback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:07:19 -07:00
Jeff Emmett d8736ba341 fix(rcal): add post-load migration for tags field on existing events
Automerge docs created before the tags schema don't have the field.
The migration runs 5s after startup (after loadAllDocs completes),
patches missing tags onto events, and assigns known demo event tags.
Also removes debug endpoint and tracing logs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 14:01:01 -07:00
Jeff Emmett 9ae88e14b7 debug: add tags tracing logs 2026-03-24 13:56:22 -07:00
Jeff Emmett d7e195c0b3 debug: temporary tags debug endpoint 2026-03-24 13:48:21 -07:00
Jeff Emmett a3b6d7f425 fix(rcal): convert Automerge proxy arrays to plain arrays for tags serialization
Automerge proxy lists don't serialize to JSON properly via ?? null.
Use Array.from() to materialize them before returning in API responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:41:32 -07:00
Jeff Emmett 2dd5e764cd feat(rcal): MI calendar awareness, tags, saved views, MCP server
Phase 1: MI now knows the current date/time and upcoming events (14-day
lookahead, 5 events max) via direct Automerge read — no HTTP overhead.

Phase 2: Tags (string[] | null) on CalendarEvent for first-class filtering.
Saved views (named filter presets) with full CRUD API. Tag filter on
GET /api/events via comma-separated AND logic. Demo events seeded with tags.

Phase 3: Calendar MCP server (5 tools: cal_list_events, cal_get_event,
cal_list_sources, cal_list_views, cal_create_event) registered in .mcp.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:28:02 -07:00
Jeff Emmett f2c3245240 fix: ensure demo community visibility is always public on startup
The demo Automerge doc had visibility: "private" from initial creation.
ensureDemoCommunity now forces visibility to "public" on every startup
if it drifted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:21:59 -07:00
Jeff Emmett 90d511077c fix: campaign wizard using wrong localStorage key for auth token
Was reading `auth_token`, should be `encryptid-token`. Also removes
the premature client-side auth guard that blocked signed-in users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 13:04:57 -07:00
Jeff Emmett 7f327eb07a fix: whitelist rvote GET API as public + guard campaign wizard auth client-side
1. Add GET /rvote/api/* to public endpoint whitelist so proposal
   listings work on private/permissioned spaces without auth.
2. Campaign wizard now checks for auth token before POSTing,
   showing "Please sign in" instead of a cryptic 401.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:58:21 -07:00
Jeff Emmett 7ad5666b9a fix: enforce enabledModules check on module root path
The sub-path middleware (/:space/:moduleId/*) already blocked disabled
modules, but the root path (/:space/:moduleId) didn't. Now both paths
consistently check enabledModules before allowing access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:38:01 -07:00
Jeff Emmett 4536b5cab1 fix: remove rvote proposals from space dashboard + fix protocol in redirects
1. Remove all rvote/proposals fetching from rstack-user-dashboard.
   rApp-specific data (proposals) should stay within the rVote module,
   not leak into the space-level dashboard.

2. Fix url.protocol in bare-domain redirects — TLS is terminated by
   Cloudflare/Traefik so url.protocol is always http: internally.
   Use https: for production domains.

3. Rewrite /{space}/api/... paths internally on bare domain instead
   of redirecting to subdomain (avoids CORS + mixed content issues).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:29:15 -07:00
Jeff Emmett 6e4d1436e0 fix: mixed content on bare-domain API calls + SSE stream error handling
Two fixes:
1. Bare-domain routing used url.protocol (always http: behind TLS
   termination) for redirects, causing mixed-content blocks. Added
   proto helper that uses https: on production domains. Also rewrite
   /{space}/api/... calls internally instead of redirecting to the
   subdomain.
2. rDesign SSE stream reader now catches QUIC protocol errors on
   stream close gracefully.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:20:20 -07:00
Jeff Emmett 50c003e8e3 fix(rdesign): catch SSE stream close errors (Cloudflare QUIC reset)
Add .catch() to the ReadableStream reader loop so Cloudflare QUIC
protocol resets on stream close don't surface as uncaught errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:13:44 -07:00
Jeff Emmett 4ed940d75c fix(rdesign): run Scribus runner as standalone supervisor process
The Scribus --python-script flag requires GUI initialization which
blocks in headless environments. Instead, run the runner as a separate
supervisor-managed Python process (always-on socket server). The bridge
server now simply verifies the socket exists rather than launching
Scribus.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:05:51 -07:00
Jeff Emmett 3a443a0d09 fix(rdesign): run runner startup unconditionally (Scribus doesn't set __main__)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:53:47 -07:00
Jeff Emmett aacbcdaddf fix(rdesign): remove --no-gui flag so Scribus runner script executes
Scribus 1.5 --no-gui mode doesn't execute --python-script properly.
Remove the flag and let Scribus use the Xvfb display, which also
enables the runner to create the bridge socket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:49:50 -07:00
Jeff Emmett 8f1ad52557 feat(collab): unify header & tab-row — shared people-panel across all rApps
Canvas now uses the same rstack-collab-overlay component as all other
rApps instead of its own custom #people-online-badge. Header restructured
to match renderShell() layout (history/settings in dropdown-wraps on left).
Bridge API (updatePeer/removePeer/setConnState/clearPeers) lets canvas
feed CommunitySync peers into the shared component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:46:26 -07:00
Jeff Emmett e5466491c7 fix(rdesign): auto-restart Scribus when runner socket is missing
The bridge's /start endpoint was returning "already running" even when
the runner script had crashed (socket gone). Now kills zombie Scribus
and restarts. Agent route also verifies runner connectivity after start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:41:58 -07:00
Jeff Emmett af446938be fix(auth): show username input on first login before passkey prompt
When no known accounts exist in localStorage, show a username/email
input field instead of immediately triggering the unscoped passkey
picker. User types their username, then gets a scoped passkey prompt
for only that account's credentials.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:41:29 -07:00
Jeff Emmett 724c0e16ba fix(auth): redirect logged-out visitors from private spaces to module landing
Non-demo space dashboards now redirect logged-out visitors to
rspace.online/ instead of showing another user's rApp grid. Private
space module pages redirect to rspace.online/{moduleId} instead of
showing the sign-in gate overlay.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:39:39 -07:00
Jeff Emmett fdf4db2050 fix(rdesign): move prompt input above replies in chat panel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:37:08 -07:00
Jeff Emmett 3cb2298569 feat(rdesign): split-pane chat + visual editor UI, SSE keepalive
Rewrite rDesign UI from cramped textarea+step-log to proper split-screen:
left = chat conversation with bubbles, right = interactive SVG editor
with click-to-select, drag-to-move, and corner-handle resize.

SSE keepalive pings every 15s prevent Cloudflare QUIC stream drops.
Tool calls now show human-readable descriptions in collapsible details.
Gemini reasoning text included in thinking events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:28:28 -07:00
Jeff Emmett 3ead9b4ca0 fix(auth): keep known accounts on logout, pass transports in scoped auth
Logout no longer removes the account from the picker — users see
"Sign in as [username]" on next visit. fetchScopedCredentials now
returns full PublicKeyCredentialDescriptor with transports so the
browser can locate the right authenticator without showing a picker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:26:33 -07:00
Jeff Emmett b625913eba feat(auth): username-first passkey login with account picker
Scoped passkey prompts via /api/auth/start so the browser only shows
matching credentials for the selected account. Known accounts stored
in localStorage and surfaced as a picker (1 account = named button,
multiple = list). "Use a different account" falls back to unscoped.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 11:00:36 -07:00
Jeff Emmett 68edfaae66 feat(rflows): rewrite flow engine — conservation-enforcing simulation + Sankey renderer
Simplify FunnelNodeData from 4-tier thresholds to 2 fields (overflowThreshold + capacity),
replace 3-tier spending multiplier with flat drainRate. Rewrite folk-flow-river.ts as clean
Sankey-style SVG renderer (~580 lines, was ~1043). Add migrateFunnelNodeData() for backward
compat with saved flows. Net -616 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:58:53 -07:00
Jeff Emmett f9767191e8 fix(auth): reload page on logout and redirect logged-in users from space grid
After logout, reload the page so the server re-renders the current rApp
in logged-out/demo mode instead of showing a blank screen. Cross-tab
logout also triggers a reload. Space dashboard now redirects logged-in
users to the rSpace canvas instead of showing the rApp grid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:54:35 -07:00
Jeff Emmett 21b38e7297 fix(tabs): server-authoritative tab sync across browser sessions
Changed syncTabsFromServer to replace local tabs with server tabs
instead of merging (union). This prevents tabs closed in browser A
from being resurrected when browser B refreshes. Also added server
sync to the iframe module landing path which was localStorage-only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:53:24 -07:00
Jeff Emmett 4722aca065 fix(auth): wire cross-session logout in rstack-identity + encryptid profile
rstack-identity is the actual sign-out component used in production.
clearSession() now calls /api/session/logout, and connectedCallback
validates the session with the server to detect revocation. Also
updated the auth.rspace.online profile page handleLogout().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:46:44 -07:00
Jeff Emmett c2b5820f8a fix(rdesign): use relative path for API fetch to avoid mixed content
The bare-domain router redirects /demo/... paths to demo.rspace.online
with http:// protocol, causing mixed content errors. Use the current
page path as the base URL instead of constructing an absolute path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:41:13 -07:00
Jeff Emmett bfbf1d14cd fix(auth): wire cross-session logout through rspace-header
The actual logout UI is in rspace-header.ts (not the encryptid login
button component). clearSession() now calls /api/session/logout, and
on page load the header validates the session with the server to detect
revocation from another browser session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:40:23 -07:00
Jeff Emmett aec42ef976 fix(rdesign): add publicWrite flag to unblock POST requests
The write-method middleware was returning 403 for POST /api/design-agent
because the module lacked publicWrite: true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:36:14 -07:00
Jeff Emmett e0e76446db feat(encryptid): cross-session logout propagation
When a user logs out in one browser, all other sessions are now revoked
on their next page load or token refresh. Adds logged_out_at column to
users table, server-side revocation checks on verify/refresh endpoints,
and a new /api/session/logout endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:32:52 -07:00
Jeff Emmett f70972cfb7 fix(rdesign): add design-agent API to public endpoint exemptions
The demo space auth middleware was blocking POST requests with 403.
Add /rdesign/api/ to isPublicEndpoint list, matching rwallet pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:32:18 -07:00
Jeff Emmett ddb5b0b2e4 fix(rdesign): fix 401 auth error and theme-aware CSS for light mode
Pass encryptid auth token in design-agent API requests. Replace
non-existent --rs-bg-elevated with real theme variables and remove
hardcoded dark fallbacks so the UI works in both light and dark mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:22:16 -07:00
Jeff Emmett 77b7aba893 feat(rdesign): Scribus noVNC + AI design agent + CRDT sync
Replace Affine wrapper with full Scribus DTP stack:
- Docker container: Scribus 1.5 + Xvfb + x11vnc + noVNC + Python bridge
- Bridge API: Flask server (port 8765) proxying to Scribus Python API via Unix socket
- Design agent: Gemini tool-calling loop drives Scribus headlessly from text briefs
- CRDT sync: Automerge schema v2 with pages/frames, bidirectional SLA bridge
- Canvas tool: folk-design-agent shape + create_design_agent in canvas-tools registry
- Module UI: inline text prompt + step log + SVG layout preview (no iframe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:06:04 -07:00
Jeff Emmett d74512ddcd chore(rflows): bump folk-flow-river.js cache version to v=2
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:33:56 -07:00
Jeff Emmett 79f16925aa fix(canvas): remove TS cast from inline script (Vite builds as JS)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:25:18 -07:00
Jeff Emmett 8b43df5ce9 fix(rflows): Sankey-style constant-width L-shaped ribbons for waterfalls
Three fixes for S-curve appearance:
- Constant width throughout each waterfall (no taper between source/river)
- Stack inflow waterfalls side-by-side at funnel top proportionally
- Widen spending drain to 80% of vessel bottom width

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:23:46 -07:00
Jeff Emmett aa4a200f32 feat(history): add "Revert to this point" button in Time Machine panel
Forward Automerge change that overwrites content fields with snapshot data,
preserving meta and full history. Also fixes pre-existing TS errors in
folk-flow-river (undefined exitX) and test-full-loop (StepResult type).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 19:08:15 -07:00
Jeff Emmett 47a3fe32fb fix(rflows,rwallet): unstaged fixes from previous session
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:42:11 -07:00
Jeff Emmett 8aa2e9773a feat(rmaps): ZIP import, chat, route requests, indoor maps
- ZIP import: Google Takeout + generic FeatureCollection ZIP via JSZip
- Route requests: "Ask to navigate" sends WebSocket route_request, toast notification with Navigate/Dismiss in other tab
- Chat: Automerge-backed persistent messages with MapChatMessage schema (v2), sidebar tab toggle, unread badge
- Indoor maps: <map-indoor-view> with c3nav raster tile proxy, level selector, Easter egg on Level 0 triple-click
- Indoor/outdoor toggle in controls bar and mobile FAB
- Cache bust v2→v3

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:42:02 -07:00