8 Commits
Author SHA1 Message Date
ksmithandClaude Sonnet 5 b1c9a85ab3 Bump to v2026.9.4
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 21:38:02 -06:00
ksmithandClaude Sonnet 5 3be8d9d731 Bump to v2026.9.3
Switches to a date-based version scheme (YYYY.M.D, with .2/.3/etc.
appended for additional same-day releases) instead of semver.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 21:00:56 -06:00
ksmithandClaude Sonnet 5 f6c71753b5 Bump to v1.1.0 and bring all documentation current
Version bump in both pyproject.toml and package.json. Documentation
update covers everything shipped since v1.0.0 (direct messages,
message deletion, custom emoji, video attachments, DM/room email
notifications, active sessions, and more), and corrects claims that
had gone stale -- backend/README.md and DEPLOYMENT.md both still said
"no server-side session revocation" and backend/README.md said "no
custom/uploaded emoji," both now false.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 21:27:52 -06:00
ksmithandClaude Sonnet 5 0a91f4f347 Add an About section to the account menu (#51)
Shows the app version, links the AGPL-3.0-or-later license text, and
links the source repo -- AGPL's own suggested-usage text recommends
exactly this ("if your software can interact with users remotely...
its interface could display a 'Source' link"), not just a courtesy
credits screen.

Version comes from package.json at build time via a Vite `define`
(__APP_VERSION__), so it can't drift from what's actually released.
License text is served at /LICENSE via a frontend/public/ symlink to
the repo-root LICENSE, the same pattern already used for the user
guide. Also bumps both package manifests to 1.0.0 ahead of tagging
the first release.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 18:59:50 -06:00
ksmithandClaude Sonnet 5 3fdfbd96e2 License the project under AGPL-3.0-or-later
Adds the verbatim license text as LICENSE, sets license metadata in
both package manifests, and links it from both README.md files.
Chosen specifically for the network-copyleft clause (AGPL §13): a
modified version run as a hosted service must offer its source to
that service's users, which plain GPL's distribution-only trigger
doesn't cover.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 18:49:08 -06:00
ksmith 89be497fdb Add markdown rendering for chat messages (issue #14)
Renders message content with markdown-to-jsx: bold/italic/strikethrough,
inline code, fenced code blocks, blockquotes, lists (incl. nested and
task lists), tables, footnotes, headings, and highlight (==text==).
Raw HTML in message content is parsed to escaped literal text rather
than rendered (disableParsingRawHTML), which is the XSS mitigation for
this being user-generated content -- verified against both <img
onerror> and <script> probes. Markdown image embeds degrade to a link
instead of an <img>, since the app already has a first-class image
upload and a second silent remote-image-embed path would duplicate it
and leak the viewer's IP to arbitrary URLs.

The inline message-edit control is upgraded from a single-line <input>
to a <textarea> so multi-line markdown can actually be edited without
losing newlines, mirroring the Composer's Enter-sends/Shift+Enter-
newlines convention.

Since CommonMark treats a single newline as a soft break (collapses to
a space) rather than a visible line break, added a small code-fence-
aware preprocessor that converts single newlines to hard breaks --
without it, existing multi-line messages sent via the Composer's
Shift+Enter would silently collapse onto one line.

Also fixes heading levels rendering at an identical capped size
(should still step down by level, just capped lower than default), and
adds CSS for markdown constructs the library already parsed but hadn't
been styled for the dark theme: table borders, highlight/mark color,
task-list checkbox accent, and footnote divider.
2026-08-14 21:42:57 -06:00
ksmithandClaude Sonnet 5 d09bf4a30a Phase 4: Web Push notifications (pywebpush + VAPID)
Backend: PushSubscription model/migration, VAPID config + `cli.py
generate-vapid-keys`, push_service.send_push_to_user (upsert-by-endpoint
subscribe/unsubscribe, auto-cleanup of expired 404/410 subscriptions),
/api/push/* router, and ConnectionManager now tracks connected user IDs
per room so chat.py can push only to offline members after broadcasting
to online ones.

Two test-infra bugs found and fixed along the way: send_push_to_user
takes the caller's AsyncSession and is awaited inline rather than fired
via asyncio.create_task with its own session (background tasks were
outliving the test event loop); and the ws_client fixture now uses
NullPool to eliminate a connection-pool checkout race that was failing
WS tests intermittently.

Frontend: service worker rebuilt with vite-plugin-pwa's injectManifest
strategy (custom src/sw.ts) so it can add push/notificationclick
handlers alongside the existing precaching and StaleWhileRevalidate
routes ported over from generateSW. New subscribe/unsubscribe flow
(lib/push.ts, api/push.ts) with a toggle in the account menu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 06:53:07 -06:00
ksmithandClaude Sonnet 5 99aa029c0d Phase 1: auth, room CRUD, WebSocket chat, PWA frontend
Invite-only FastAPI + SQLAlchemy(async) + Postgres backend (session-cookie
auth via CLI-provisioned accounts, open-room CRUD, single-instance /ws/chat)
and a React + Vite PWA frontend (login, room list, chat view). Backend tests
pass against a local Postgres DB. See README.md and backend/README.md for
setup, and ARCHITECTURE.md for the full phased design.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 20:01:17 -06:00