Skip to content

Message deletion + dark-mode polish + map design doc#38

Merged
JosephMaynard merged 3 commits into
masterfrom
feat/message-deletion
Jul 3, 2026
Merged

Message deletion + dark-mode polish + map design doc#38
JosephMaynard merged 3 commits into
masterfrom
feat/message-deletion

Conversation

@JosephMaynard

Copy link
Copy Markdown
Owner

Message deletion + dark-mode polish + map design doc

One PR bundling a feature with two small riders (per your "fewer, bigger PRs" note).

1. Message deletion (the feature)

Closes the "no message deletion" gap in CLAUDE.md, in line with LOAM's trusted-host / admin-moderation model.

  • DELETE /api/messages/:messageId — an admin can delete any message (moderation); a non-admin can delete only their own, and only when the cascade won't remove another user's reply (clearing others' reactions is fine). A still-streaming message is refused (409) so its writer can't re-persist it.
  • Cascade — deleting a message also removes its reactions, and (for a channel post that roots a thread) its replies and the reactions on those. Extracted two shared helpers (collectDeletionSet, deleteMessages); the retention reaper now reuses deleteMessages, so the persist → broadcast → drop-from-memory ordering lives in one place.
  • Client — a "Delete" action on each message, shown for your own messages or (for admins) any message, never on a streaming one. Confirms, calls the endpoint, removes the target immediately; cascaded items arrive over the existing messageDeleted socket events. Hover-revealed on desktop, always visible on touch, danger-styled on hover.
  • Tests — 6 server route tests (author deletes own; non-author 403; admin deletes any; 404; thread-root cascade; non-admin blocked from deleting a thread others replied to, admin can).

2. Dark-mode completeness (rider)

The admin-channels CSS (from #36, which branched before dark mode) used 5 raw hex colours — the only non-adaptive colours left in the stylesheet. Tokenized them (--c-border, --c-surf-2, --c-ink-green, --c-danger, --c-white), so dark mode is now 100% adaptive. (This also resolves the sidebar-looks-light confusion — that was a stale preview artifact, not the shipped code; the sidebar has always been dark in both themes.)

3. Maps & location-sharing design doc (rider)

docs/10-maps-location-sharing.md — the investigation you asked me to write up: a MapLibre GL JS + PMTiles + Protomaps stack serving an OpenStreetMap vector basemap entirely from the host (no internet, no third-party calls), with opt-in, ephemeral, tap-to-drop-a-pin location messages. Documents the two real challenges (offline tile acquisition; Geolocation blocked over LAN) and the open scope questions. No code — a briefing for when you've decided.

Validation

Full build + suite green (server 79, client 36). CodeRabbit reviewed once against master; its one finding (align the delete fetch with the file's AbortController/timeout pattern) is fixed.

🤖 Generated with Claude Code

JosephMaynard and others added 3 commits July 3, 2026 10:21
…gap)

The admin channel-management CSS (from #36, which branched before dark mode
existed) used raw hex values, so those five rules were the only colours in the
stylesheet that didn't adapt to dark mode. Point them at the existing tokens
(--c-border, --c-surf-2, --c-ink-green, --c-danger, --c-white) so the admin
channels panel matches the rest of the admin UI in both themes. No light-theme
change (the tokens' light values equal the hexes they replace).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Captures the owner's map idea: a MapLibre GL JS + PMTiles + Protomaps stack that
serves an OpenStreetMap vector basemap entirely from the host (no internet, no
third-party calls), with tap-to-drop-a-pin location messages that are opt-in,
ephemeral, and flag-gated. Documents the two real challenges (offline tile-data
acquisition; Geolocation blocked over LAN's insecure context) and the open scope
questions. No code yet — briefing for a future decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a DELETE /api/messages/:messageId endpoint and a delete affordance in the
client — closing the "no message deletion" gap noted in CLAUDE.md and fitting
LOAM's trusted-host / admin-moderation model.

Server:
- DELETE /api/messages/:id. Authorisation: an admin may delete any message
  (moderation); a non-admin may delete only their own, and only when the cascade
  won't remove another user's reply (clearing others' reactions is fine). A
  message that's still streaming is refused (409) so its writer can't re-persist it.
- Cascade: deleting a message also removes its reactions, and — for a channel
  post that roots a thread — its replies and the reactions on those. Two shared
  helpers (collectDeletionSet, deleteMessages); the retention reaper now reuses
  deleteMessages, so the persist-then-broadcast-then-drop ordering lives in one
  place (broadcasting before the in-memory mirror is torn down keeps reaction
  DM-audience lookups resolvable).

Client:
- A "Delete" action on each message, shown for your own messages or, for admins,
  any message (never on a streaming message). Confirms, calls the endpoint, and
  removes the target immediately; cascaded replies/reactions arrive over the
  existing messageDeleted socket events. Hover-revealed on desktop, always shown
  on touch, danger-styled on hover.

Tests: 6 server route tests (author deletes own; non-author 403; admin deletes
any; 404; thread-root cascade removes replies + reactions; non-admin blocked from
deleting a thread others replied to while an admin can).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2ff0407e-00a6-4152-a6f5-29d3d8bc9179

📥 Commits

Reviewing files that changed from the base of the PR and between b669362 and d8f9096.

📒 Files selected for processing (5)
  • apps/client/src/app.tsx
  • apps/client/src/global.css
  • apps/server/src/app.test.ts
  • apps/server/src/app.ts
  • docs/10-maps-location-sharing.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/message-deletion

Comment @coderabbitai help to get the list of available commands.

@JosephMaynard JosephMaynard merged commit a7b5bc9 into master Jul 3, 2026
5 checks passed
@JosephMaynard JosephMaynard deleted the feat/message-deletion branch July 3, 2026 11:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant