chore: add backlog tasks 74-76
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3808b51a64
commit
384ef23ae1
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
id: TASK-74
|
||||
title: Email forwarding via Mailcow aliases (username@rspace.online)
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-01 05:55'
|
||||
labels:
|
||||
- encryptid
|
||||
- email
|
||||
- infrastructure
|
||||
dependencies: []
|
||||
references:
|
||||
- src/encryptid/mailcow.ts
|
||||
- src/encryptid/server.ts
|
||||
- src/encryptid/db.ts
|
||||
- src/encryptid/schema.sql
|
||||
- docker-compose.encryptid.yml
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Users get username@rspace.online email addresses that forward to their personal email. Uses Mailcow API to create lightweight forwarding aliases — no full mailboxes needed. Users toggle it on in profile settings via API.
|
||||
|
||||
Pure alias approach: can be upgraded to hybrid (agent-processes-first) model later by swapping aliases for a catch-all.
|
||||
|
||||
## Implementation
|
||||
- New `mailcow.ts` API client wrapping Mailcow REST API (create/delete/update/find aliases)
|
||||
- Schema: `email_forward_enabled` + `email_forward_mailcow_id` columns on users table
|
||||
- DB layer: `getEmailForwardStatus()` + `setEmailForward()` functions
|
||||
- API endpoints: GET/POST `/api/account/email-forward` (status, enable, disable)
|
||||
- Profile email change hook: auto-updates or disables alias when profile email changes
|
||||
- Docker: encryptid container joins rmail-mailcow network for internal API access
|
||||
|
||||
## Infrastructure
|
||||
- rspace.online already configured as Mailcow domain with MX/SPF/DKIM/DMARC
|
||||
- Mailcow API key stored in /opt/encryptid/.env on server
|
||||
- Internal API URL: http://nginx-mailcow:8080 (via Docker network)
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 Mailcow API client creates/deletes/updates forwarding aliases
|
||||
- [ ] #2 GET /api/account/email-forward returns status and availability
|
||||
- [ ] #3 POST enable creates alias and stores mailcow ID in DB
|
||||
- [ ] #4 POST disable deletes alias from Mailcow and clears DB
|
||||
- [ ] #5 Profile email change auto-updates or disables active alias
|
||||
- [ ] #6 Schema migration is idempotent (ALTER TABLE IF NOT EXISTS)
|
||||
- [ ] #7 Graceful degradation when MAILCOW_API_KEY not set (available: false)
|
||||
- [ ] #8 Docker compose includes rmail-mailcow network and env vars
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Implemented email forwarding via Mailcow aliases. Created mailcow.ts API client (~112 lines), added 2 DB columns + 2 helper functions, 3 API endpoints (GET status, POST enable, POST disable), profile email change hook, and Docker networking. All infrastructure prerequisites were already in place (rspace.online domain, MX/SPF/DKIM/DMARC records). API key added to /opt/encryptid/.env on server. Merged dev→main and pushed.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
id: TASK-75
|
||||
title: 'Three-state FUN: Present → Forgotten → Deleted'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-01 19:44'
|
||||
labels:
|
||||
- canvas
|
||||
- FUN
|
||||
- UX
|
||||
dependencies: []
|
||||
references:
|
||||
- lib/folk-shape.ts
|
||||
- lib/community-sync.ts
|
||||
- server/community-store.ts
|
||||
- website/canvas.html
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
Shapes now have three visual states instead of two. "Forgetting" a shape fades it (35% opacity, greyscale) for all connected clients rather than hiding it. Other users can choose to "forget too", "remember" (restore), or "delete" (hard-remove). A forgottenBy map (DID → timestamp) tracks who forgot, enabling social signaling around shared attention. Automerge handles concurrent map writes cleanly.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 Close a shape → fades (greyscale, 35% opacity) for all connected clients
|
||||
- [ ] #2 Another user sees faded shape, right-click → 'Forget too' or 'Remember'
|
||||
- [ ] #3 'Remember' restores to full color for everyone
|
||||
- [ ] #4 Right-click faded shape → 'Delete' → disappears, shows in memory panel 'Deleted'
|
||||
- [ ] #5 Memory panel 'Restore' on deleted shape → back to present
|
||||
- [ ] #6 Memory panel shows forget count per shape
|
||||
- [ ] #7 Backward compatible with legacy forgotten boolean
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Implemented three-state FUN system across 4 files:\n\n- **folk-shape.ts**: Added `:state(forgotten)` CSS (opacity 0.35, grayscale 0.8) and `forgotten` property with getter/setter toggling ElementInternals states\n- **community-sync.ts**: New methods: `forgetShape(id, did)`, `rememberShape()`, `hardDeleteShape()`, `getShapeVisualState()`, `hasUserForgotten()`, `getFadedShapes()`, `getDeletedShapes()`. Updated `#applyDocToDOM` (renders faded, skips deleted) and `#applyPatchesToDOM` (emits `shape-state-changed`)\n- **community-store.ts**: `forgetShape()` adds DID to `forgottenBy` map; `rememberShape()` clears map + deleted flag\n- **canvas.html**: Right-click context menu (Forget/Remember/Forget too/Delete), two-section memory panel (Fading with forget count + Deleted with Restore), close button fades instead of removes, Delete key escalates (forget → hard-delete)\n\nCommit: 317bc46 on dev, merged to main.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
id: TASK-76
|
||||
title: 'Persist EncryptID login across subdomains, sessions, and browsers'
|
||||
status: Done
|
||||
assignee: []
|
||||
created_date: '2026-03-01 22:12'
|
||||
labels:
|
||||
- encryptid
|
||||
- auth
|
||||
- session
|
||||
dependencies: []
|
||||
references:
|
||||
- shared/components/rstack-identity.ts
|
||||
- src/encryptid/server.ts (refresh endpoint accepts expired tokens)
|
||||
priority: high
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||
EncryptID sessions were lost when navigating between rspace.online subdomains (e.g. demo.rspace.online → cca.rspace.online) because localStorage is per-origin. Sessions also didn't survive token expiry gracefully. Added cross-subdomain cookie persistence alongside localStorage, with automatic refresh of expired tokens via the server.
|
||||
<!-- SECTION:DESCRIPTION:END -->
|
||||
|
||||
## Acceptance Criteria
|
||||
<!-- AC:BEGIN -->
|
||||
- [ ] #1 Session persists when navigating between *.rspace.online subdomains
|
||||
- [ ] #2 Session survives browser close/reopen (30-day cookie)
|
||||
- [ ] #3 Expired tokens auto-refresh via server before being discarded
|
||||
- [ ] #4 Sign Out clears both localStorage and cookie
|
||||
- [ ] #5 Code that directly reads localStorage still works via early cookie→localStorage sync
|
||||
<!-- AC:END -->
|
||||
|
||||
## Final Summary
|
||||
|
||||
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
|
||||
Added cross-subdomain cookie (`eid_token`, `domain=.rspace.online`, 30-day max-age, `SameSite=Lax`, `Secure`) to `rstack-identity.ts`. Three layers of persistence:\n\n1. **Cookie helpers** — `_setSessionCookie()`, `_getSessionCookie()`, `_removeSessionCookie()` handle domain-wide cookie\n2. **`getSession()` fallback** — tries localStorage first, falls back to cookie, restores to localStorage for fast access\n3. **`#refreshIfNeeded()` upgrade** — attempts server refresh for expired tokens before giving up; server accepts expired tokens via `{ exp: false }`\n4. **Early IIFE sync** — at module load time, syncs cookie→localStorage so direct `localStorage.getItem()` callers (WebSocket auth, sync, shell scripts) see the session\n\nCommit: ef1d93d. Merged dev→main, pushed to Gitea.
|
||||
<!-- SECTION:FINAL_SUMMARY:END -->
|
||||
Loading…
Reference in New Issue