Local chat for teams — in-app messaging surface #8

Open
opened 2026-05-07 13:51:13 +00:00 by mAi · 3 comments
Collaborator

Goal

Add a local in-app chat surface for paliad teams — messaging that lives inside paliad rather than spilling to email / WhatsApp / Slack. m raised this as a fresh feature 2026-05-07.

Why "local"

  • HLC-internal communication should not leak to external services for compliance + privacy reasons.
  • Existing channels (email, CalDAV invites) are heavyweight for quick coordination ("Anna, kannst du auf meine Frist 16.05. drauf schauen?").
  • The platform already knows who's on which team / project / partner-unit — chat can leverage that context (auto-target, reference, auto-include the right people) instead of re-resolving recipients each time.

Sketch

A new Chat surface inside paliad. Several plausible shapes — inventor picks one or proposes hybrid:

  • Per-project thread — one chat room per project (Client / Litigation / Patent / Case). Effective team is the participant set. Threads inherit the project hierarchy (a Client-level thread is visible to all descendants' teams).
  • Per-deadline / per-termin thread — short-lived, contextual. Surface from the deadline / termin detail page. Closes when the row resolves.
  • Direct messages (DMs) — 1:1 or small-group, no project context required.
  • Mentions across surfaces — reference a deadline / project / user from inside any thread (#frist-1234, @anna).
  • Cross-cutting "team room" — broader-than-project shared channels (e.g. partner-unit room).

m: pick the v1 set; the rest defer.

Open design questions (for inventor)

Surface + scope

  1. What chat surfaces ship in v1? Per-project, per-deadline, per-termin, DMs, partner-unit rooms, cross-cutting topical rooms. Pick v1 set + defer the rest. Recommend per-project + DMs as the minimum useful pair.
  2. Hierarchy + visibility. A Client-level chat — visible to all descendants' team members? Or strictly to the Client team? Coordinate with t-139 derivation: do partner-unit-derived members see project chats they're derived onto?
  3. Approval flow integration (t-138 cross-cut). When a deadline-approval pings the inbox, does the same event also surface in the project chat? Should "please approve this deadline" be sent as a chat message instead of (or in addition to) the inbox row?

Real-time + delivery

  1. Real-time architecture. Three plausible shapes:
    • (a) Polling — simple, scales OK at HLC's user count, lossy under tab-sleep
    • (b) SSE (server-sent events) — one-way push, easy in Go's net/http
    • (c) WebSockets — bidirectional, more infra (proxy, reconnect, heartbeats)
    • Recommend (b) for v1. m's call.
  2. Notification path. Beyond in-app:
    • Email digest of unread-since-last-login? Per-message? None?
    • Browser push notifications (PWA already wired)?
    • CalDAV alarm? (probably too noisy)
    • Recommend: in-app + browser-push opt-in. Email digest deferred.
  3. Read / unread + delivery state. Per-user per-thread last-read marker? Per-message read receipts (who read it)? Recommend the former; receipts deferred.

Content + features

  1. Message body. Plain text? Markdown? Rich-text WYSIWYG? Recommend Markdown rendering with a small subset (bold/italic/links/code/lists). No WYSIWYG editor.
  2. Mentions + entity references. @anna (autocomplete from project team), #frist-1234 (link to deadline), #projekt-.... The chat surface auto-renders these as links + drives notifications for the mentioned user. Recommend yes for v1.
  3. Attachments. Out of scope for v1? Or bring in early (PDFs especially)?
  4. Edits / deletions. Allowed? Edit window (e.g. 5 min)? Tombstones for deletions ("this message was deleted")?
  5. Replies / threading. Flat thread per project, or sub-threads (Slack-style "Reply in thread")? Recommend flat in v1.
  6. Search. Full-text across all visible chats? Per-project search? Defer if it adds significant complexity.

Persistence + retention

  1. Storage. New paliad.chat_messages table — schema shape? Inventor proposes columns. Indexes for thread + recency.
  2. Retention. Forever, or N-day rolling window? Compliance: HLC may need permanent archival for client-related conversations. Recommend forever in v1; archival/export later.
  3. Audit. Chat is user-to-user communication, not an audit trail. Should it appear in the project Verlauf at all? Recommend no by default, with optional "post to Verlauf as note" affordance for important messages.

Integration with existing surfaces

  1. Sidebar entry. Top-level "Chat" item with unread badge? Or per-project chat tab on the project detail page (no global Chat surface)? Recommend both — global Chat with overview + per-project tab as deep-link.
  2. Custom Views (#5) integration. Should chat messages be a 5th source in the ViewService union? Probably no — chat is conversation, not events. But mentions of deadlines/projects from chats might surface as "activity" rows. Inventor: scope the boundary.
  3. Bulk team email (#7) overlap. A team-wide announcement could be either an email (one-way, archived in inbox) or a chat post (threaded, replyable). Inventor: pin which fits when, recommend.

Permissions

  1. Who can chat? Anyone on the project team, or restricted by project_teams.role? Restrict observers (read-only)? Recommend: all team members can read+write; observers read-only.
  2. External counsel / experts. local_counsel and expert roles — included in chat or not? Compliance angle: HLC may not want external counsel reading internal coordination. Recommend opt-in per project.

Mobile / PWA

  1. PWA push notifications. paliad already has manifest + service worker. Chat messages → PWA push? On opt-in only?

Out of scope (v1)

  • Voice / video calls.
  • Cross-firm chat (external participants like opposing counsel).
  • Chatbots / automated agents.
  • Reactions (👍 / 👎) — flag as Phase 2.
  • File attachments (Phase 2).
  • End-to-end encryption (defer; HLC's existing storage assumptions are server-trusted).
  • Slack / Teams bridging.

References

  • paliad.project_teams — visibility participant set
  • paliad.partner_unit_members — derivation participant extension (t-139)
  • paliad.users — user identity + offices
  • paliad.notifications — does this exist? (inventor checks)
  • t-138 design docs/design-approvals-2026-05-06.md — approval-request flow, where chat may overlap
  • t-139 design docs/design-hierarchy-aggregation-2026-05-06.md — visibility predicate hooks
  • t-144 — Custom Views substrate (FilterSpec / RenderSpec); chat may or may not feed in
  • Issue #7 — bulk team email (related comms surface)

Inventor brief

  • Role: inventor
  • Worker: noether (deepest context on the existing data substrate; NOT cronus per memory: cronus retired from paliad)
  • Branch convention: mai/noether/inventor-local-chat
  • Deliverable: docs/design-local-chat-2026-05-07.md. Three coordinated sub-designs:
    1. Surface set + visibility model (Q1–Q3, Q19–Q20)
    2. Real-time + content + persistence (Q4–Q15, Q21)
    3. Integration with existing surfaces (Q16–Q18)
  • Inventor STOPs after design. No /mai-coder self-load. Awaits m's go on the design before any coder shift.
  • m available during the design pass to answer the 21 open questions above.
## Goal Add a local in-app chat surface for paliad teams — messaging that lives inside paliad rather than spilling to email / WhatsApp / Slack. m raised this as a fresh feature 2026-05-07. ## Why "local" - HLC-internal communication should not leak to external services for compliance + privacy reasons. - Existing channels (email, CalDAV invites) are heavyweight for quick coordination ("Anna, kannst du auf meine Frist 16.05. drauf schauen?"). - The platform already knows who's on which team / project / partner-unit — chat can leverage that context (auto-target, reference, auto-include the right people) instead of re-resolving recipients each time. ## Sketch A new Chat surface inside paliad. Several plausible shapes — inventor picks one or proposes hybrid: - **Per-project thread** — one chat room per project (Client / Litigation / Patent / Case). Effective team is the participant set. Threads inherit the project hierarchy (a Client-level thread is visible to all descendants' teams). - **Per-deadline / per-termin thread** — short-lived, contextual. Surface from the deadline / termin detail page. Closes when the row resolves. - **Direct messages (DMs)** — 1:1 or small-group, no project context required. - **Mentions across surfaces** — reference a deadline / project / user from inside any thread (`#frist-1234`, `@anna`). - **Cross-cutting "team room"** — broader-than-project shared channels (e.g. partner-unit room). m: pick the v1 set; the rest defer. ## Open design questions (for inventor) ### Surface + scope 1. **What chat surfaces ship in v1?** Per-project, per-deadline, per-termin, DMs, partner-unit rooms, cross-cutting topical rooms. Pick v1 set + defer the rest. Recommend per-project + DMs as the minimum useful pair. 2. **Hierarchy + visibility.** A Client-level chat — visible to all descendants' team members? Or strictly to the Client team? Coordinate with t-139 derivation: do partner-unit-derived members see project chats they're derived onto? 3. **Approval flow integration (t-138 cross-cut).** When a deadline-approval pings the inbox, does the same event also surface in the project chat? Should "please approve this deadline" be sent as a chat message instead of (or in addition to) the inbox row? ### Real-time + delivery 4. **Real-time architecture.** Three plausible shapes: - (a) Polling — simple, scales OK at HLC's user count, lossy under tab-sleep - (b) SSE (server-sent events) — one-way push, easy in Go's `net/http` - (c) WebSockets — bidirectional, more infra (proxy, reconnect, heartbeats) - Recommend (b) for v1. m's call. 5. **Notification path.** Beyond in-app: - Email digest of unread-since-last-login? Per-message? None? - Browser push notifications (PWA already wired)? - CalDAV alarm? (probably too noisy) - Recommend: in-app + browser-push opt-in. Email digest deferred. 6. **Read / unread + delivery state.** Per-user per-thread last-read marker? Per-message read receipts (who read it)? Recommend the former; receipts deferred. ### Content + features 7. **Message body.** Plain text? Markdown? Rich-text WYSIWYG? Recommend Markdown rendering with a small subset (bold/italic/links/code/lists). No WYSIWYG editor. 8. **Mentions + entity references.** `@anna` (autocomplete from project team), `#frist-1234` (link to deadline), `#projekt-...`. The chat surface auto-renders these as links + drives notifications for the mentioned user. Recommend yes for v1. 9. **Attachments.** Out of scope for v1? Or bring in early (PDFs especially)? 10. **Edits / deletions.** Allowed? Edit window (e.g. 5 min)? Tombstones for deletions ("this message was deleted")? 11. **Replies / threading.** Flat thread per project, or sub-threads (Slack-style "Reply in thread")? Recommend flat in v1. 12. **Search.** Full-text across all visible chats? Per-project search? Defer if it adds significant complexity. ### Persistence + retention 13. **Storage.** New `paliad.chat_messages` table — schema shape? Inventor proposes columns. Indexes for thread + recency. 14. **Retention.** Forever, or N-day rolling window? Compliance: HLC may need permanent archival for client-related conversations. Recommend forever in v1; archival/export later. 15. **Audit.** Chat is user-to-user communication, not an audit trail. Should it appear in the project Verlauf at all? Recommend no by default, with optional "post to Verlauf as note" affordance for important messages. ### Integration with existing surfaces 16. **Sidebar entry.** Top-level "Chat" item with unread badge? Or per-project chat tab on the project detail page (no global Chat surface)? Recommend both — global Chat with overview + per-project tab as deep-link. 17. **Custom Views (#5) integration.** Should chat messages be a 5th source in the ViewService union? Probably no — chat is conversation, not events. But mentions of deadlines/projects from chats might surface as "activity" rows. Inventor: scope the boundary. 18. **Bulk team email (#7) overlap.** A team-wide announcement could be either an email (one-way, archived in inbox) or a chat post (threaded, replyable). Inventor: pin which fits when, recommend. ### Permissions 19. **Who can chat?** Anyone on the project team, or restricted by `project_teams.role`? Restrict observers (read-only)? Recommend: all team members can read+write; observers read-only. 20. **External counsel / experts.** `local_counsel` and `expert` roles — included in chat or not? Compliance angle: HLC may not want external counsel reading internal coordination. Recommend opt-in per project. ### Mobile / PWA 21. **PWA push notifications.** paliad already has manifest + service worker. Chat messages → PWA push? On opt-in only? ## Out of scope (v1) - Voice / video calls. - Cross-firm chat (external participants like opposing counsel). - Chatbots / automated agents. - Reactions (👍 / 👎) — flag as Phase 2. - File attachments (Phase 2). - End-to-end encryption (defer; HLC's existing storage assumptions are server-trusted). - Slack / Teams bridging. ## References - `paliad.project_teams` — visibility participant set - `paliad.partner_unit_members` — derivation participant extension (t-139) - `paliad.users` — user identity + offices - `paliad.notifications` — does this exist? (inventor checks) - t-138 design `docs/design-approvals-2026-05-06.md` — approval-request flow, where chat may overlap - t-139 design `docs/design-hierarchy-aggregation-2026-05-06.md` — visibility predicate hooks - t-144 — Custom Views substrate (FilterSpec / RenderSpec); chat may or may not feed in - Issue #7 — bulk team email (related comms surface) ## Inventor brief - Role: inventor - Worker: noether (deepest context on the existing data substrate; NOT cronus per memory: cronus retired from paliad) - Branch convention: `mai/noether/inventor-local-chat` - Deliverable: `docs/design-local-chat-2026-05-07.md`. Three coordinated sub-designs: 1. Surface set + visibility model (Q1–Q3, Q19–Q20) 2. Real-time + content + persistence (Q4–Q15, Q21) 3. Integration with existing surfaces (Q16–Q18) - Inventor STOPs after design. No `/mai-coder` self-load. Awaits m's go on the design before any coder shift. - m available during the design pass to answer the 21 open questions above.
mAi self-assigned this 2026-05-07 13:51:13 +00:00
Author
Collaborator

PARKED 2026-05-07 17:03 (m): thought experiment, not pursuing now. Design doc preserved on main at docs/design-local-chat-2026-05-07.md (commit pushed). When it un-parks, restart from §6 lock recommendations + §7.1 sanity-check.

PARKED 2026-05-07 17:03 (m): thought experiment, not pursuing now. Design doc preserved on main at `docs/design-local-chat-2026-05-07.md` (commit pushed). When it un-parks, restart from §6 lock recommendations + §7.1 sanity-check.
mAi added the
deferred
label 2026-05-07 15:04:24 +00:00
Author
Collaborator

BLOCKED on m/mAi#207 (aichat backend) 2026-05-13

m's call 2026-05-13 11:43: keep on-hold, annotate.

Surface overlap with the aichat backend work (m/mAi#207, darwin inventor in flight) — both involve chat in paliad surfaces, even though AI-vs-human is different. Wait for aichat patterns to land before designing this; the data model + real-time architecture + skill-lift conventions may inform the local-chat design.

Revisit conditions:

  • aichat backend ships (m/mAi#207 merges)
  • m re-prioritises team chat above the Fristenrechner / Determinator workstream
## BLOCKED on m/mAi#207 (aichat backend) 2026-05-13 m's call 2026-05-13 11:43: keep on-hold, annotate. Surface overlap with the aichat backend work (m/mAi#207, darwin inventor in flight) — both involve `chat in paliad` surfaces, even though AI-vs-human is different. Wait for aichat patterns to land before designing this; the data model + real-time architecture + skill-lift conventions may inform the local-chat design. Revisit conditions: - aichat backend ships (m/mAi#207 merges) - m re-prioritises team chat above the Fristenrechner / Determinator workstream
Author
Collaborator

Discarded as a task on m's call 2026-05-18 (paliadin/head + m, queue cleanup). The mai-side task t-paliad-145 is set to cancelled.

Reason: not on the active workstream. The original aichat-pattern-blocker (m/mAi#207) has since shipped, but team-chat-in-paliad hasn't re-surfaced as a priority and the surface set + 21 open Qs in the issue body never got design work.

Issue stays open until m decides whether to close it permanently or revive it later. The 21 design questions in the body are preserved as the seed if revived.

— mAi (paliadin/head)

Discarded as a task on m's call 2026-05-18 (paliadin/head + m, queue cleanup). The mai-side task `t-paliad-145` is set to `cancelled`. Reason: not on the active workstream. The original aichat-pattern-blocker (m/mAi#207) has since shipped, but team-chat-in-paliad hasn't re-surfaced as a priority and the surface set + 21 open Qs in the issue body never got design work. Issue stays open until m decides whether to close it permanently or revive it later. The 21 design questions in the body are preserved as the seed if revived. — mAi (paliadin/head)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#8
No description provided.