Spaces are now nestable — any space can embed references to other spaces
via SpaceRef, with a permission cascade model (most-restrictive-wins at
each nesting boundary). Every EncryptID registration auto-provisions a
sovereign space at <username>.rspace.online with consent-based nesting
controls.
Key additions:
- NestPolicy per space (open/members/approval/closed consent levels)
- SpaceRef CRUD with allowlist/blocklist, permission ceiling enforcement
- Approval flow for nest requests with admin review
- Reverse lookup (nested-in) so owners see where their space appears
- Source space admins can always revoke (sovereignty guarantee)
- cascadePermissions() for multi-depth permission intersection
- Client-side types for nested space rendering
- Full spec at docs/SPACE-ARCHITECTURE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enhanced landing page with gradient hero, 5-card features grid, auth-aware
"Your Flows" section, and 3-step "How TBFF Works" walkthrough. Added
EncryptID token verification on flow creation, space_flows DB table for
per-space flow association, and space-scoped flow listing API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hono's parameterized /:space route was capturing /admin before the
explicit route. Move admin.html serving into the Bun.serve fetch
handler so it runs before Hono routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new /admin page showing all spaces with stats (shape count,
member count, file size, visibility), search/filter/sort controls,
and links to open or export each space.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change sql.unsafe() param arrays from unknown[] to any[] (9 modules)
- Exclude sw.ts and demo-sync.ts from tsconfig (separate build targets)
- Add type stub for @mkkellogg/gaussian-splats-3d (CDN-loaded)
- Rename private title → designTitle in folk-swag-designer (HTMLElement conflict)
- Fix Hono context typing and instanceof cast in splat module
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add entrypoint.sh that authenticates with Infisical via universal-auth
and injects secrets as env vars before starting the Bun server.
Uses Bun's built-in fetch API instead of Node.js http module.
Secrets removed from docker-compose.yml (now fetched at runtime):
INTERNAL_API_KEY, HETZNER_API_TOKEN, CLOUDFLARE_API_TOKEN,
CLOUDFLARE_ZONE_ID, TWENTY_API_TOKEN, R2_*, X402_*, SMTP_PASS
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rfunds.online now shows a landing page with TBFF info and flow list
instead of the river demo. The river is one tab in a 3-tab flow detail
view (Table | River | Transactions).
- Add folk-funds-app.ts: main app component with landing + detail views
- Extract mapFlowToNodes to shared lib/map-flow.ts
- Simplify folk-budget-river.ts to pure renderer (no API fetching)
- Restructure routes: / = landing, /demo = demo detail, /flow/:id = flow
- Expand funds.css for landing, tabs, table cards, transaction list
- Add folk-funds-app.ts build entry to vite.config.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- rApp dropdown now scrollable (max-height: 70vh) with apps grouped into
5 categories: Creating, Planning, Discussing & Deciding, Funding &
Commerce, Sharing & Media
- Renamed canvas object terminology from "shapes" to "rSpaces" in UI labels
- New shapes placed on canvas automatically find free positions using
spiral search to avoid overlapping existing shapes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dry-run.ts validates all 11 adapters against live DB (19 docs, 292 rows,
0 errors). Standardized rwork slug rspace-dev→demo and rvote slug
community→demo so all seeded data uses consistent space identifier.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Notes/work/cal/vote adapters had wrong table names and missing fields.
Now match actual PG schemas. Added books, cart, providers, files, trips,
inbox, splat adapters. Engine gains idempotency, dry-run, disk backup,
per-row error recovery, and progress logging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Seed gallery with real Bonsai and Nike Shoe splat scenes from Hugging Face,
replacing the synthetic Rainbow Sphere. Add photo/video upload endpoint
(POST /api/splats/from-media) with processing status tracking for future
COLMAP + OpenSplat generation. Gallery now shows upload mode toggle
(splat file vs photos/video) and processing status overlays on cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each module can run as an independent container using its standalone.ts
entrypoint. Reuses the same rspace-online image with CMD override.
Usage:
docker compose -f docker-compose.yml -f docker-compose.standalone.yml \
up -d rtrips-standalone
All services share rspace-db and traefik-public. Module-specific deps
mapped: books/files/swag volumes, OSRM for trips, IMAP for inbox,
R2 for tube, payment network for cart/funds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add domain→module rewrite in Bun.serve fetch handler for standalone
domains (rbooks, rpubs, rchoices, rfunds, rforum, rvote, rnotes, rwork,
rcal, rtrips, rwallet, rdata, rnetwork, rtube, rmaps). Requests to
these domains get rewritten to /demo/{moduleId}/... and served by the
existing Hono module routes.
Adds Traefik labels at priority 120 for all 15 domains. Keeps rcart,
rfiles, swag, and providers on their own containers.
This retires ~25 legacy containers, freeing significant memory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a Listmonk-powered newsletter form at the bottom of the rSpace
landing page, matching the dark theme and gradient styling of existing
sections. Uses rSpace list UUID for subscriber routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GaussianSplats3D infers format from URL file extension. Changed file
serve route to /api/splats/:id/:filename so URLs end in .splat/.ply/.spz.
Also fixed camera orientation (Y-up) and scale values in test data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Relocate the conic intersection calculator from standalone rConic module
into rTrips at /routes sub-page. Adds enhanced visualization with ghost
conic curves, distinct arc colors, overlap zones, crossing angle lines,
pulsing intersection markers, arc labels, and SVG legend.
- New math: sampleConicCurve() for ghost curve tracing, conicTangentAt()
for tangent/crossing angle computation
- Route planner served at /{space}/trips/routes with OSRM proxy
- Removed standalone conic module registration from server/index.ts
- Updated vite build config to build folk-route-planner under trips
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the create-space form out of the landing page into its own
route at /create-space. Landing page now shows CTA buttons for
"Create a Space" and "Try the Demo". /new redirects to /create-space.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New rSpace module for 3D Gaussian splat viewing. Gallery + full-viewport
Three.js/GaussianSplats3D viewer loaded via CDN importmap. EncryptID auth
on uploads, optional x402 micro-transaction gate. Reusable x402 Hono
middleware in shared/x402/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
App switcher:
- Add standaloneDomain to ModuleInfo (exposed via /api/modules)
- Add missing standaloneDomain to 5 modules: funds, files, wallet,
choices, forum (20/21 modules now have standalone domains)
- Show external link arrow on hover for each app's standalone site
Space switcher:
- Pass auth token when fetching /api/spaces so the API returns
private (authenticated/members_only) spaces the user owns or
is a member of
- Group spaces into "Your spaces" (with role badge) and "Public
spaces" sections
- Reload space list on auth-change (sign-in/sign-out)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace legacy mountHeader() (identity only) with the full rstack
shell header on both index.html and canvas.html. Both pages now
show rstack-app-switcher (21 modules), rstack-space-switcher, and
rstack-identity — matching the module pages rendered by renderShell().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 5 — Choices: Lightweight module wrapping the canvas-native
folk-choice-vote/rank/spider components. Lists choice shapes from the
space's Automerge doc, links to canvas for creation/interaction.
Phase 6 — Funds: Port of rfunds-online BudgetRiver visualization to
vanilla web component. Includes simulation engine (pure functions),
types (stripped @xyflow), demo presets, and SVG sankey river with
animated waterfalls, overflow branches, and sufficiency badges.
Flow-service API proxy for same-origin frontend calls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mailcow at mail.rmail.online uses a self-signed certificate.
Set tls.rejectUnauthorized: false for the SMTP transport.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port pocket-press (Next.js + Typst) as an rSpace module with Hono routes,
vanilla folk-pubs-editor web component, and Typst v0.13.1 for PDF generation.
Includes all 4 format templates (A7, A6, Quarter Letter, Digest), artifact
envelope creation with cosmolocal spec, and standalone deployment support.
Typst binary installed in Docker via multi-stage build from debian:bookworm-slim.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 2-of-3 guardian recovery system:
- Guardian invite via email or shareable link
- One-click approval page for recovery requests
- Social recovery initiation (anti-enumeration)
- 7-day recovery request expiry
Add second device linking:
- QR code + link for cross-device passkey registration
- 10-minute link expiry, one-time use
Enhanced profile page:
- Account security checklist (email, device, guardians)
- Guardian management (add/remove, max 3)
- Device linking with QR code display
- Recovery initiation form for lost devices
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port rbooks-online (Next.js + React) as an rSpace module with Hono routes,
vanilla web components, and shared PostgreSQL schema. Includes library grid
(folk-book-shelf), flipbook PDF reader (folk-book-reader), upload with
EncryptID auth, IndexedDB caching, and standalone deployment support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the rSpace module architecture that enables all r-suite apps
to run as modules within a single-origin platform at rspace.online,
while each module can still deploy standalone at its own domain.
Phase 0 — Shell + Module System:
- RSpaceModule interface (shared/module.ts) with routes, metadata, hooks
- Shell HTML renderer (server/shell.ts) for wrapping module content
- Three header web components: rstack-app-switcher, rstack-space-switcher,
rstack-identity (refactored from rspace-header.ts into Shadow DOM)
- Space registry API (server/spaces.ts) — /api/spaces CRUD
- Hono-based server (server/index.ts) replacing raw Bun.serve fetch handler
while preserving all WebSocket, API, and subdomain backward compat
- Shared PostgreSQL with per-module schema isolation (rbooks, rcart, etc.)
- Vite multi-entry build: shell.js + shell.css built alongside existing entries
- Module info API: GET /api/modules returns registered module metadata
Phase 1 — Canvas Module:
- modules/canvas/mod.ts exports canvasModule as first RSpaceModule
- Canvas routes mounted at /:space/canvas with shell wrapper
- Fallback serves existing canvas.html for backward compatibility
- /:space redirects to /:space/canvas
URL structure: rspace.online/{space}/{module} (e.g. /demo/canvas)
All existing subdomain routing (*.rspace.online) preserved.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Simplify resolveRpId() to always return 'rspace.online' so passkeys
registered from any r*.online domain share the same RP ID. Browsers
use .well-known/webauthn Related Origins to validate cross-domain
passkey usage. This makes one passkey work everywhere.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update EncryptID SMTP defaults to use rmail.online Mailcow instance.
From address now noreply@rspace.online instead of noreply@jeffemmett.com.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- folk-shape: skip preventDefault on touch events targeting inputs/textareas
so mobile keyboards can open inside shapes
- toolbar: replace unreadable emoji-only strip with FAB toggle (+) that
opens a 3-column grid overlay with emoji + labels; auto-closes on tool
select; separate always-visible zoom strip at bottom-left
- canvas: remove overflow:hidden from #canvas so viewport moves with
pan/zoom instead of clipping at initial bounds
- canvas-content: add width/height 100% and overflow:visible for robust
containing block
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mobile toolbar: icon-only scrollable strip with horizontal swipe
- Infinite canvas: separate viewport (grid) from content layer (shapes)
- Single-finger pan via pointer events on empty canvas background
- Widen zoom range from 0.25-4x to 0.05-20x
- Fix Automerge sync fallback to full doc reconciliation when no patches
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hono 4.11.10 made the `alg` parameter required in `verify()`. All 6
verify() calls were failing with "JWT verification requires alg option
to be specified", causing every token verification to return 401. This
broke space creation and all authenticated operations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The allowedOrigins array only listed explicit subdomains (auth, cca, demo,
app, dev) so any canvas slug subdomain like create.rspace.online was
rejected by CORS. Switch to a function-based origin check that allows all
*.rspace.online subdomains dynamically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of hardcoding rpId to "rspace.online" (which requires Related
Origins support), derive the RP ID from the request's Origin header.
Each r* app (rmaps.online, rnotes.online, etc.) now gets its own RP ID
matching its domain, so passkeys work natively without browser support
for Related Origin Requests.
- Added resolveRpId() helper that maps Origin → hostname for allowed origins
- Registration creates passkeys with the caller's domain as RP ID
- Authentication uses the caller's domain as RP ID
- Added rp_id column to credentials table for per-credential RP ID tracking
- rspace.online subdomains still use rspace.online as shared RP ID
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forget (F): Soft-delete shapes — close button sets forgotten:true in
Automerge doc instead of removing. Memory panel (toolbar toggle) lets
users browse and Remember forgotten shapes. Server-side forgetShape()
and rememberShape() with WebSocket handlers.
Update (U): New public updateShape(id, fields) method on CommunitySync
for programmatic field updates. Existing auto-capture unchanged.
New (N): Renamed all create/add vocabulary to new — toolbar buttons,
event names (new-shape, shape-new, shape-removed), internal functions
(newShape, newShapeElement).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrote auth flow to go through EncryptID server instead of
client-side unsigned JWTs. Fixes "Invalid or expired authentication
token" on space creation, and shows username in header.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The RP ID jeffemmett.com caused "relying party ID is not a registrable
domain suffix" errors on *.rspace.online subdomains. Related Origins
also exceeded the 5 eTLD+1 browser limit with 18+ domains listed.
Now rspace.online is the RP ID, so all *.rspace.online subdomains
(including cca.rspace.online) are valid automatically. The Related
Origins file only lists non-rspace.online r* ecosystem domains.
Also points rspace-header auth URL to auth.rspace.online.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cca.rspace.online/campaign/demo now loads the campaign-demo community.
Path segments are joined with hyphens to derive the slug. Subdomain
acts as a brand namespace; root path still loads the subdomain slug.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server-side clock broadcasting time signals via Event Bus for shapes
to subscribe to periodic events (tick, hourly, daily).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New feature card in hero grid and a dedicated section explaining
local IndexedDB persistence, Automerge auto-merge, and incremental
sync. Matches the existing visual style with pillars and identity cards.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
rSpace apps now work fully offline. Automerge documents and sync state
persist to IndexedDB, enabling instant load from cache, offline editing,
and automatic incremental merge on reconnect. A Service Worker caches
the app shell (HTML/JS/WASM) for loading without network.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Inject rdata.online/collect.js tracking script in layout
- Add rData link to ecosystem footer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three new canvas shapes for small-group decisions:
- folk-choice-vote: live polling with plurality, approval, and
quadratic voting modes
- folk-choice-rank: drag-to-reorder with Borda count and
instant-runoff aggregation
- folk-choice-spider: multi-criteria scoring with SVG radar chart,
per-user polygon overlays, and weighted mean aggregation
All sync via rSpace's existing Automerge CRDT infrastructure.
Aggregation algorithms are exported as pure functions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>