Kez/kez-chat/Cargo.toml
Jason Tudisco 60aeaedbad feat(kez-chat): Web Push notifications + WhatsApp-style chat bubbles
Server (kez-chat/src/)
  - push.rs: VAPID (PEM/PKCS#8) auto-generated on first run;
    StoredSubscription store table; PushSender using
    IsahcWebPushClient; fanout drops 410/404 subs automatically.
    Push payload carries metadata only ({type,to,seq}) — never
    plaintext or ciphertext.
  - api.rs: GET /v1/push/vapid-public-key,
    POST /v1/push/subscribe/:handle, POST /v1/push/unsubscribe/:handle.
    Auth via X-KEZ-Auth: <ts>:<sig>, canonical message binds the
    endpoint URL so headers can't be replayed against other subs.
  - messages.rs: after broker.publish, fire-and-forget
    push.fanout for offline recipients.
  - config.rs: --vapid-key-path, --vapid-subject (env-backed).
  - main.rs: load_or_generate_vapid on startup.

Web client (kez-chat/web/src/)
  - vite.config.ts: switched vite-plugin-pwa to injectManifest mode.
  - sw.ts: custom service worker with workbox precache,
    NetworkOnly for /v1/*, NavigationRoute SPA fallback, push +
    notificationclick handlers (focus existing tab via postMessage,
    or open a new one).
  - lib/push.ts: enablePush / disablePush / isPushSubscribed +
    iOS PWA-install detection.
  - routes/Settings.svelte: "Background notifications (Web Push)"
    section with toggle and iOS Add-to-Home-Screen nudge.
  - main.ts: bridge from SW navigate message to svelte-spa-router
    via location.hash.

Chat UX (routes/Messages.svelte)
  - Bubbles now shrink-wrap to content with WhatsApp-style asymmetric
    corners and inline bottom-right timestamps. Old layout used
    nested block-level divs inside max-w-[78%], which stretched
    every bubble to full width regardless of content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-06 21:47:07 -06:00

34 lines
1.1 KiB
TOML

[package]
name = "kez-chat-server"
version = "0.1.0"
edition = "2024"
license = "MIT OR Apache-2.0"
description = "Home server for kez-chat: handle registry + NATS auth callout + WebFinger + static SPA host. Designed in kez-chat/document.md."
[dependencies]
anyhow = "1"
axum = "0.7"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.5", features = ["derive", "env"] }
hex = "0.4"
kez-core = { path = "../rust/crates/kez-core" }
rusqlite = { version = "0.32", features = ["bundled"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"
tokio = { version = "1.48", features = ["macros", "rt-multi-thread", "sync", "signal"] }
tokio-stream = { version = "0.1", features = ["sync"] }
futures = "0.3"
web-push = "0.10"
base64 = "0.22"
p256 = { version = "0.13", features = ["pem"] }
rand = "0.8"
tower-http = { version = "0.6", features = ["trace", "cors", "fs"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[dev-dependencies]
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
sha2 = "0.10"
tempfile = "3"