diff --git a/MODULE_SPEC.md b/MODULE_SPEC.md new file mode 100644 index 0000000..ac7d34e --- /dev/null +++ b/MODULE_SPEC.md @@ -0,0 +1,101 @@ +# rMaps — Spatial Intelligence + +**Module ID:** `rmaps` +**Domain:** `rmaps.online` +**Version:** 0.1.0 +**Framework:** Next.js 14 / React 18 / MapLibre GL / Zustand (client-side) +**Status:** Active + +## Purpose + +Real-time collaborative location sharing and navigation for groups. Room-based ephemeral spaces where participants share GPS locations with configurable privacy levels. Supports indoor navigation via c3nav (CCC events) and outdoor via OSM/MapLibre. Rooms auto-expire after 7 days of inactivity. + +## Data Model + +### Client-Side Types (no database) + +| Type | Key Fields | Description | +|------|-----------|-------------| +| **Room** | slug, settings, participants (map), waypoints[], expiresAt | Collaborative map space | +| **Participant** | id, emoji, color, location, privacySettings, status | User in a room | +| **ParticipantLocation** | lat, lng, accuracy, altitude, heading, speed, source, indoor | GPS/network/manual position | +| **Waypoint** | id, name, type, emoji, lat, lng, createdBy | Named point of interest | +| **Route** | from, to, segments[] | Navigation route with instructions | +| **PrecisionLevel** | exact/building/area/approximate | Privacy granularity | + +### Storage + +- In-memory rooms (Zustand store) +- Room lifecycle: 7-day auto-expiry +- Future: Automerge CRDT for persistent rooms + +## Permission Model + +### Space Integration + +- **SpaceVisibility:** PUBLIC by default (anyone can join rooms by slug) +- **Default role for open spaces:** PARTICIPANT (can share location, add waypoints) + +### Capabilities + +| Capability | Required SpaceRole | AuthLevel | Description | +|-----------|-------------------|-----------|-------------| +| `view_map` | VIEWER | BASIC | See map and participant locations | +| `add_markers` | PARTICIPANT | STANDARD | Add waypoints and POIs | +| `share_location` | PARTICIPANT | STANDARD | Broadcast own GPS location | +| `moderate_markers` | MODERATOR | STANDARD | Edit/delete others' waypoints | +| `configure_map` | ADMIN | ELEVATED | Change room settings, expiry, privacy defaults | + +### Module-Specific: Privacy Model + +Per-participant privacy settings override permission capabilities: +- **PrecisionLevel:** Controls location accuracy (exact → approximate fuzzing) +- **ghostMode:** Hides participant from map entirely +- Privacy is user-controlled, not admin-controlled + +### Current Auth Implementation + +- EncryptID optional (anonymous join allowed) +- Auth in localStorage (`rmaps-auth`) +- No room-level access control + +## API Endpoints + +| Method | Path | Auth Required | Capability | Description | +|--------|------|---------------|------------|-------------| +| GET | /api/health | No | — | Health check | +| GET | /api/c3nav/[event] | No | — | Proxy c3nav indoor map data | +| POST | /api/routing | — | — | Route calculation (planned) | + +No native CRUD API — rooms are in-memory. Future: WebSocket sync server. + +## Canvas Integration + +Embeds as shapes on rSpace canvas: +- **`folk-destination`**: Map location marker with emoji +- **`demo-map-marker`**: Interactive map POI +- Click to expand into full map view with participant locations + +## Cross-Module Dependencies + +| Module | Integration | +|--------|------------| +| **rSpace** | Canvas shape embedding (destination/marker shapes) | +| **rTrips** | Trip itinerary locations feed into map | +| **rCal** | Event locations shown on map timeline | +| **EncryptID** | Optional identity for persistent rooms | + +## Local-First / Offline Support + +- Fully client-side — works offline (GPS continues) +- Automerge sync planned for room state +- Offline waypoints queued for sync on reconnect + +## Migration Plan + +1. Add WebSocket sync server for real-time room state +2. Add Automerge CRDT for persistent rooms +3. Add EncryptID auth to WebSocket upgrade +4. Import `RMAPS_PERMISSIONS` from SDK +5. Add `resolveSpaceRole()` + `hasCapability()` at WS level +6. Keep per-participant privacy settings as user-controlled override