Adds named, colored ports to every node type (source outflow, funnel
inflow/spending/overflow, outcome inflow/overflow) with a full wiring
state machine supporting both click-to-wire and drag-to-wire interaction.
Edges now originate from specific port positions. Outcomes gain overflow
allocations so fully-funded outcomes can cascade surplus onward.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Automerge schemas, lifecycle hooks (onInit, docSchemas), and
local-first client wrappers for all remaining PG modules:
rWork, rVote, rCal, rFiles, rCart, rBooks, rTrips, rInbox, rSplat, rFunds.
Each module now:
- Defines typed Automerge document schemas (schemas.ts)
- Registers docSchemas and onInit hook with SyncServer reference
- Moves initDB() from top-level to onInit for unified startup
- Has a client-side local-first wrapper (local-first-client.ts)
Dual-write route handlers will be wired incrementally per module
following the rNotes pattern established in Phase 2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
The regex matched /cal instead of /rcal, so getApiBase() always returned
empty string, causing 404s on api/events, api/lunar, and api/sources.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Transform the Diagram tab from a read-only SVG into a full interactive
canvas with draggable nodes, zoom/pan, Sankey-width edges with +/-
allocation controls, slide-in editor panel, live simulation, node CRUD,
keyboard shortcuts, and lz-string URL sharing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents stale WebSocket reconnect loops after sign-out by adding an
intentional-disconnect flag to CommunitySync. Canvas and shell pages
now redirect to homepage when the user signs out.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standalone test harness for flow tubes, particle animation, and
interactive port wiring with event logging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Replace invisible particle-only flow visualization with colored 3D tubes
between layers, spread horizontally to avoid overlap. Particles now travel
along tube paths. Add click-to-wire interaction on I/O port chips with
visual feedback (glow/breathe/dim). Prevent animation restart on Automerge
sync by surgically updating flow elements in-place.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite folk-calendar-view with 5 views (Day/Week/Month/Season/Year),
3 tabs (Temporal/Spatial/Lunar), Leaflet map with event markers and
transit polylines, temporal-spatial zoom coupling, and lunar phase display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorganize user dropdown into expandable "My Account" submenu containing
account actions (Add Email, Add Device, Recovery) plus Dark Mode and
Encrypted Backup toggle switches. Move theme toggle from toolbar into
account settings, default to dark mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
Derive a deterministic secp256k1 EOA from the passkey's PRF output via
HKDF-SHA256, enabling hardware-backed signing for x402 micropayments and
Safe treasury proposals without storing private keys.
Key changes:
- EOA key derivation with domain-separated HKDF (eoa-derivation.ts)
- Key manager integration with PRF-only EOA path (key-derivation.ts)
- Encrypted client-side wallet store for Safe associations (wallet-store.ts)
- Passkey-backed x402 signer replacing EVM_PRIVATE_KEY (passkey-signer.ts)
- Safe propose/confirm/execute proxy routes in rwallet (mod.ts)
- Wallet capability flag in JWT via users.wallet_address (server.ts)
- Payment operation permissions: x402, safe-propose, safe-execute (session.ts)
Privacy: Safe wallet associations stored client-side only (AES-256-GCM
encrypted localStorage). Server only knows user has wallet capability.
108 tests passing across 5 test suites.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch ghost tracking from mousemove to pointermove (fires for touch/pen/mouse)
- Add cancel button (✕) on ghost outline for mobile (no ESC key available)
- Center ghost on viewport for touch devices instead of (0,0)
- Add touch-action: manipulation to all toolbar buttons (eliminates 300ms tap delay)
- Bump mobile touch targets to 44px min-height with larger padding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
The bare domain x402.org/facilitator returns a 308 redirect that
breaks payment verification. Use www.x402.org/facilitator instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DATABASE_URL, ADMIN_DIDS, and ENCRYPTID_DEMO_SPACES are now stored
in Infisical and injected via the entrypoint. Remove the last
docker-compose.yml reference that was temporarily re-added.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
The shared/db/pool.ts requires DATABASE_URL but it was missing from
both docker-compose.yml and Infisical, causing the container to
crash-loop on startup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
folk-rapp used class "rapp-header" but the drag detection in
folk-shape checks for ".header" or "[data-drag]". Added both so
the rapp header works as a drag handle like every other shape type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove DATABASE_URL and ADMIN_DIDS from docker-compose.yml (now
injected via Infisical entrypoint). Add scripts/seed-infisical.sh
to interactively populate 21 module-specific secrets (R2, Immich,
Twenty, Discourse, FAL, RunPod, etc.) into the rspace Infisical
project. Update Dockerfile to include scripts/ in the image.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On touch devices, both pointer and touch events fire. When a second
finger was added, the pointer handler re-captured the interaction,
fighting the touch-based pan/pinch. Now the touch handler releases
pointer captures and sets a flag that blocks the pointer handler
during two-finger gestures. Also cancels shape drag on multi-touch
and closes the context menu on touchstart for reliable mobile dismiss.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The overlap resolver now moves siblings in the drag direction rather
than snapping the dragged shape away from them. Supports chain-pushing
(A pushes B into C) with a recursion depth of 3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hovering a forgotten shape now shows a tooltip explaining the state.
A new "Hide Faded" toolbar button lets users hide all forgotten shapes
entirely, with the preference persisted in localStorage. Hidden shapes
reappear automatically when another user remembers them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
The rspace module was serving raw canvas.html as a standalone page
(bypassing renderShell) because canvas-module.html didn't exist.
This meant navigating to rspace caused a full page replacement with
no shared shell, tabs, or TabCache support — appearing to open in a
"new window."
Now extracts body content, styles, and scripts from canvas.html at
startup (stripping the duplicate shell chrome) and renders through
renderShell like every other module. This makes rspace fully
interoperable with the tab system and TabCache.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Fix getApiBase() regex to match /rphotos instead of /photos, add
/album route with iframe embed via renderExternalAppShell, and update
Immich links to navigate within rSpace instead of opening externally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Replace static HTML mockups and WebSocket skeleton demos with the actual
self-contained web components (with built-in demo data) for rcart, rtube,
rfunds, rnotes, rtrips, and rvote — matching the rcal demo pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EncryptID sessions were lost when navigating between rspace.online
subdomains (e.g. demo→cca) because localStorage is per-origin. Now
stores a domain-wide cookie (eid_token, domain=.rspace.online, 30 days)
alongside localStorage. On new subdomain visits, the cookie is synced
to localStorage at module load time. Expired tokens are auto-refreshed
via the server before being discarded. Sign-out clears both stores.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
The demo page was a frozen July 2026 static HTML grid with no real
functionality. Now embeds <folk-calendar-view space="demo"> which
provides full month/week/day views, navigation, lunar overlay, source
filtering, event modals, keyboard shortcuts, and 37 demo events.
Keeps hero, temporal zoom showcase, feature cards, ecosystem
integrations, and CTA sections around the interactive component.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- Tab bar state persists to localStorage per space
- Emergency synchronous localStorage fallback for beforeunload saves
- Merge Automerge full-sync instead of replacing (preserves local changes)
- Validate shape coordinates before applying (prevent NaN/Infinity)
- Save on visibilitychange for mobile browser tab backgrounding
- Add OutputPath type for module browsable content types
- Fix canvas module ID from "canvas" to "rspace" in tab-cache
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sync #attrWidth/#attrHeight during resize so CSS reflects new dimensions
- Call #dispatchTransformEvent() directly for immediate visual update
- Fix TransformEvent to fire "folk-transform" matching CommunitySync listeners
- Reduce min-width/min-height on folk-markdown and folk-wrapper to 80x40px
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Visibility badges now color-coded: green (public), yellow (permissioned),
red (private) with matching card border tints
- Public spaces show eye icon instead of lock
- Private spaces display as "username's (you)rSpace" instead of raw name
- Applied consistently across space switcher dropdown and My Spaces modal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resize and rotation handlers in folk-shape.ts passed raw event.clientX/Y
(screen coordinates) to toLocalSpace/angleFromOrigin, but those methods
expect canvas-parent coordinates. With any zoom/pan, the two coordinate
systems diverge, making resize non-functional and rotation erratic.
Added #screenToParent() to convert viewport coords to the parent's
coordinate space using getBoundingClientRect + parent scale. Applied to:
- Resize handle drag (pointermove → toLocalSpace)
- Rotation start (pointerdown → angleFromOrigin)
- Rotation drag (pointermove → angleFromOrigin)
Also syncs ghost placeholder size with zoom changes so the dotted
preview stays accurate if user zooms while in placement mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resize handles now appear when a shape is highlighted/focused, not just during
active drag. Canvas left-click+drag now pans by default; hold 250ms then drag
for marquee selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
- newShape() with explicit position now places directly at click point
instead of routing through findFreePosition spiral which could nudge
the shape away from the cursor
- Sticky note converted to setPendingTool so it shows dotted placeholder
before placement instead of instantly spawning at viewport center
- Feed tool converted to setPendingTool with __postCreate for the same
click-to-place UX
- Removed wb-sticky from mobile keepOpen list since it's now a
placement tool that should close the menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sessions now last 30 days instead of 15 minutes. Both the rstack-identity
component and legacy header auto-refresh the token when < 7 days remain,
so users who visit at least once every ~23 days stay logged in indefinitely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Canvas page was hardcoded to data-theme="light" while all other pages
default to dark. Also hides the redundant #community-info overlay
(slug/URL box) since the shell header space switcher already shows this.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>