eleven / ocho Public

Multi-thread + DMs: threads, user keypairs, and the full message toolkit (#17)

Turns each lchat instance from one shared group chat into a multi-thread workspace:
DMs and groups are one primitive (a thread with N members), the instance is the
trust boundary (open roster + admin), and every thread has its own AES key wrapped
to each member's keypair (ECIES). The server still only ever sees opaque ciphertext
plus key blobs it can't open.

- User keypairs (ECDH P-256); per-thread keys wrapped per-member; instance key for
  all-members content (profile photos), server-blind.
- Master-detail UI (desktop) + stacked mobile nav; new-chat / new-group, members,
  add-people, leave, edit-group, edit-profile.
- Message toolkit: reactions, edits (15-min window), replies, typing indicators,
  time separators + hover times, link previews, attachments, avatars; desktop
  hover react/reply/edit affordances.
- Per-thread push (SW decrypts with the thread key); admin console is roster-only
  (no group key); script-post API + tool re-keyed to the keypair model.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Paul Campbell e7c12e446b6d91ff5f0295290c2b1c2376ecc7ee parent 3fa58c1
22 files changed, +3843 −2477
  • README.md +22 −20
  • db.go +349 −16
  • db_test.go +88 −12
  • docs/threads-and-dms.md +130 −0
  • handlers_test.go +61 −40
  • hub.go +69 −28
  • main.go +402 −11
  • push.go +26 −8
  • test/crypto.test.mjs +38 −0
  • test/format.test.mjs +60 −1
  • tools/lchat-post.mjs +45 −51
  • web/pages/admin.html +7 −37
  • web/pages/index.html +72 −36
  • web/static/admin.js +17 −123
  • web/static/chat.js +2074 −1894
  • web/static/crypto.js +52 −0
  • web/static/emoji.js +68 −0
  • web/static/format.js +40 −0
  • web/static/join.js +53 −171
  • web/static/push.js +3 −7
  • web/static/style.css +155 −15
  • web/static/sw.js +12 −7
README.md

Loading diff…

db.go

Loading diff…

db_test.go

Loading diff…

docs/threads-and-dms.md

Loading diff…

handlers_test.go

Loading diff…

hub.go

Loading diff…

main.go

Loading diff…

push.go

Loading diff…

test/crypto.test.mjs

Loading diff…

test/format.test.mjs

Loading diff…

tools/lchat-post.mjs

Loading diff…

web/pages/admin.html

Loading diff…

web/pages/index.html

Loading diff…

web/static/admin.js

Loading diff…

web/static/chat.js

Loading diff…

web/static/crypto.js

Loading diff…

web/static/emoji.js

Loading diff…

web/static/format.js

Loading diff…

web/static/join.js

Loading diff…

web/static/push.js

Loading diff…

web/static/style.css

Loading diff…

web/static/sw.js

Loading diff…