feat(server,client): announcement channels (D1, closes A-2026-07-01)

Make 'announcement' a real channel type, resolving the contradiction where
it was documented and offered by the admin API but hard-rejected by the
migration-013 DB triggers.

Model: announcement channels are readable like text channels (same
READ_MESSAGES visibility), but posting is restricted to users with
MANAGE_MESSAGES — no new permission bit, migration, or client permission
plumbing needed.

Server:
- migrations/016: recreate the channel-type triggers to allow
  text/voice/announcement/dm.
- service/message.go: checkSendPermission now takes the channel type and
  rejects posts to announcement channels from users lacking MANAGE_MESSAGES
  (SendMessage + CanPost paths). Added a service test.
- Unread counts: ready-payload builder (ws/serve.go) and
  GetChannelUnreadCounts (db) now include announcement channels alongside
  text, so they track unread/last-message like text channels.

Client:
- ChannelSidebar renders announcement channels with a megaphone icon
  (added to the icon set) instead of the '#' text prefix; they otherwise
  behave like text channels (already typed in ChannelType).

Specs + trackers (api.md, protocol.md, schema.md incl. migration 016,
architecture/data-model.md, audit A-2026-07-01, decisions D1) updated.

Verified: go build ./...; go test ./service ./db ./ws ./api ./admin;
sqlc-verify; client tsc + oxlint + prettier clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
This commit is contained in:
Claude
2026-07-19 16:00:18 +00:00
parent f66d6c5274
commit 071426c0d8
14 changed files with 92 additions and 18 deletions
+6 -4
View File
@@ -58,6 +58,7 @@ CREATE TABLE IF NOT EXISTS schema_versions (
| `013_channel_type_constraint.sql` | INSERT/UPDATE triggers restricting `channels.type` to `text`/`voice`/`dm` |
| `014_events_table.sql` | Adds `events` — persistent broadcast log for reconnect cold-tier replay |
| `015_plugins.sql` | Adds `plugins` and `plugin_kv` for the WASM plugin runtime |
| `016_announcement_channel_type.sql` | Recreates the channel-type triggers to allow `announcement` |
---
@@ -151,10 +152,11 @@ CREATE TABLE channels (
);
```
Channel types: `text`, `voice`, `dm`. Migration 013 installs INSERT/UPDATE
triggers that reject any other value at the database layer. (An `announcement`
type is planned but not yet implemented — see the D1 decision in
[plans/audit-2026-07-19-decisions.md](plans/audit-2026-07-19-decisions.md).)
Channel types: `text`, `voice`, `announcement`, `dm`. Migration 013 installs
INSERT/UPDATE triggers restricting the value to this set (migration 016 added
`announcement`). Announcement channels are readable like text channels but
posting is restricted to users with `MANAGE_MESSAGES` (enforced in the service
layer, `Server/service/message.go`).
---