Commit Graph
100 Commits
Author SHA1 Message Date
aseph f84bf723c5 ci: use free GHA Nix cache (disable FlakeHub cache, not subscribed) 2026-08-03 16:44:06 +07:00
asepharyana 24db0f19b1 ci: enable FlakeHub Cache (id-token: write + use-flakehub) 2026-08-03 16:20:15 +07:00
asepharyana ce5db6aa3c fix(media): normalize activeMode in backend MediaState (FE relies on it)
Gateway publishes {playing, activeMode, musicVolume, current, queue} but the
backend MediaState interface + normalizeMediaState dropped activeMode, so the
FE's 'Screen share active' / 'Music playing' badge never rendered. Carry it
through so the FE↔BE media contract stays in sync.
2026-08-03 10:09:19 +07:00
asepharyana 44a0358b0c fix(voice): screen share restore is best-effort — Discord session teardown race
GoLive (dank074 Streamer) needs the single voice session; after the stream
ends, an automatic @discordjs/voice reconnect often races Discord's session
teardown and times out (AbortError). Restore is now best-effort with a 5s
delay; if it fails the FE shows disconnected and the user clicks Connect —
an accepted tradeoff for one-voice-session-per-user.
2026-08-03 09:33:29 +07:00
asepharyana d36c8777fe fix(voice): delay voice restore after screen share — avoid session teardown race
Immediate reconnect after Streamer.stop() races Discord's voice session
teardown → AbortError. Wait 4s so the old session is fully released before
re-joining with @discordjs/voice.
2026-08-03 09:21:10 +07:00
asepharyana 9fd4ded9c8 fix(voice): restore voice after screen share — pass pre-release status to callbacks
The restore callback previously read getVoiceStatus() AFTER disconnectGuild
had already cleared it, so it never knew which guild/channel to reconnect.
Now release/restore receive the status captured BEFORE the audio connection
is released, so reconnect actually happens after the GoLive stream ends.
2026-08-03 09:07:57 +07:00
asepharyana 55d28dc928 style(voice): biome format media handler + screen controller 2026-08-03 08:49:59 +07:00
asepharyana 02e2243a98 fix(voice): screen share releases audio connection so Streamer owns voice session
The dank074 Streamer creates its own WebRTC voice connection, but Discord
allows only ONE voice session per user. When VoiceController (audio) was
already connected, the Streamer join hung forever (never got
VOICE_SERVER_UPDATE). Now:

1. ScreenShareController takes releaseVoice/restoreVoice callbacks.
2. Before joining, it disconnects the @discordjs audio connection via
   VoiceController.disconnectGuild.
3. Streamer joins + streams GoLive.
4. After the stream ends, restoreVoice reconnects the audio connection so
   mic/listen keep working.
5. media.handler wires these via a new setVoiceController accessor from
   commandHandler; VoiceController is the single source of truth.

Also adds caller-bound timeouts & safe .catch() everywhere so a stream
failure can never become an unhandledRejection again.
2026-08-03 08:41:00 +07:00
asepharyana 8528f2c73d fix(voice): screen share join timeout — Streamer join hangs with dual voice conn 2026-08-03 08:19:05 +07:00
asepharyana 53f26185bc fix(voice): screen share crashed gateway — Streamer never joined voice + unhandledRejection
Root cause: ScreenShareController created @dank074 Streamer but never called
streamer.joinVoiceChannel() — playStream threw 'Bot is not connected to a
voice channel', and since the code only used .finally() (no .catch), the
rejection became an unhandledRejection that took down the whole gateway
(graceful shutdown triggered, systemd restarted).

Fixes:
1. Resolve active channel + streamer.joinVoiceChannel(channel) before
   prepareStream/playStream (dank074 needs its OWN WebRTC voice connection).
2. .catch() on the playStream done promise — log + kill ffmpeg instead of
   crashing the process.
3. .catch() on playback.done in media.handler too.
4. stop() now kills ffmpeg AND stops the streamer's voice connection.
2026-08-03 08:05:02 +07:00
asepharyana a57eeb2e22 fix(voice): media queue field mismatch, voice joinable filter, connect error toast
Audit voice (kirim/terima/music/screenshare) menemukan 3 masalah:
1. media:queue SILENT no-op — backend publish {source,mode} tapi gateway
   handler baca payload.url → selalu 'received without a URL'. Backend
   sekarang kirim {url,mode}, gateway terima url ATAU source (robust).
2. Voice connect gagal diam-diam saat user pilih channel tanpa permission
   (joinable=false, contoh Music 32/64/128/256k). Backend+gateway sekarang
   expose joinable; FE disable channel 'no akses' + empty state.
3. FE tidak kasih feedback saat connect gagal — tambah toast.error dengan
   pesan dari backend.

Verified live: @discordjs/voice connect ke Lofi Radio joinable sukses
(VOICE READY, DAVE session OK) — pipeline voice sebenarnya sehat, masalah
utama UX. media:queue fix akan di-verify setelah deploy.
2026-08-03 07:48:50 +07:00
asepharyana 9abb09dd33 feat(frontend): add light mode with runtime theme toggle
- globals.css: split theme tokens into :root (light default) + .dark
  overrides; switch @theme inline → @theme so utilities reference
  var(--color-*) and a runtime class swap actually re-skins the UI
  (inline inlines literal values and ignores .dark overrides)
- layout.tsx: drop the beforeInteractive inline theme script (it caused
  hydration instability); theme is applied client-side only
- top-nav: apply persisted theme on mount, default light, toggle
  updates <html> class + localStorage
- glass-intense: light variant (white card on light canvas); chart grid
  line uses var(--color-border); attachment chip uses bg-glass-bg
- Verified in static export: toggle dark↔light both directions,
  chatbot panel renders clean in both themes
2026-08-03 07:20:09 +07:00
asepharyana 831254bb71 fix(nix): filter build artifacts from frontend source
path: literals in flakes do NOT respect .gitignore, so a dirty local
out/ (stale chunks from previous builds, e.g. 3y39nidcm2n_s.js from
the removed quick-prompt button) leaked into the sandbox and got
served forever. Add filterSource helper that excludes out, .next,
node_modules, pnpm-lock.yaml from the frontend derivation source.
2026-08-03 06:53:46 +07:00
asepharyana 9718940258 fix(chatbot): FAB opens chat directly — remove extra toggle + UX polish
- chatbot-container: remove chatOpen layer — the minimized bubble now
  expands straight into the chat panel (single click, no extra button)
- Remove the redundant 'Tanya soal server...' quick-prompt button and
  the PanelLeft collapse toggle (one less state to fight)
- Bubble fixed h-[460px], chat panel flex-fills remaining space
- chat-panel: suggestion chips on empty state (suasana server, channel
  paling ramai, total pesan, pesan bermasalah) so first-time users can
  start with a single click
- Input: roomier padding, more descriptive placeholder, bigger send
  button, autoComplete off
- Drop chatOpen/setChatOpen from context (dead state)
2026-08-03 06:44:23 +07:00
asepharyana d1c1f3e4a7 feat(chatbot): per-user history via X-User-Id + agentic tools calling
Backend:
- New chatbot.tools.ts: 4 tools (get_server_stats, get_top_channels,
  get_recent_activity, get_top_flagged) with real DB executors
- chatbot.service: agentic loop — stream:true, parse SSE, execute
  tool_calls, feed results back, up to 4 rounds
- controller: resolve userId from X-User-Id header (no-login device
  uuid) with auth middleware precedence; history/clear scoped per user

Frontend:
- use-chatbot-user: mint UUID in localStorage, send as X-User-Id
- chatbotApi.send/getHistory/clearHistory accept userId header
- client.ts: apiRequest supports custom headers per call
- provider: history load + send + clear keyed to device user id
2026-08-03 06:24:19 +07:00
asepharyana 7513681b4b feat(frontend): remove ugly canvas placeholder from chatbot
- Delete chatbot-canvas.tsx (placeholder face canvas) + its export
- Remove canvas area from chatbot container; chat panel gets the freed
  space (248px → 300px) and bubble height drops 440px → 400px
2026-08-03 06:11:06 +07:00
asepharyana 2b815e156c feat(frontend): rebuild chatbot UI to match backend — wider panel, guild context, Indonesian
- Chatbot bubble: 220px → 320px wide, 440px tall; proper header with
  drag handle; quick-prompt row when chat is closed
- ChatPanel: show ALL history (not last 8), Indonesian placeholder/empty
  state/error copy (backend speaks Indonesian), timestamps (id-ID),
  clear-history button, typing indicator bubbles, Enter-to-send
- Send active guildId as context so backend answers reference the real
  server (serverInsights path in chatbot.service)
- GuildId sync from layout → ChatbotProvider via ChatbotGuildSync
- chatbotApi.send(message, guildId) → POST /api/chat {message, context}
  matching BE zod schema (guildId optional)
2026-08-03 06:04:25 +07:00
asepharyana 03d59f0738 feat(frontend): lazy-load images, add lightbox viewer, polish AI panel
- Add loading=lazy + decoding=async to all <img> (message card preview,
  attachments grid, image grid, avatars via ui/avatar)
- New Lightbox component: fullscreen image viewer with keyboard nav
  (←/→/Esc), counter, click-to-close; wired into messages page + detail
- Attachments grid: click image to open, image counter badge, grouped
  non-image attachments
- AI analysis panel: line-clamp-3 with Show more/less toggle
- Message card: preview image is now a clickable button opening detail
2026-08-03 05:08:08 +07:00
asepharyana 5cc0f8a243 docs: frontend README dev note 2026-08-02 16:46:22 +07:00
asepharyana 12c55ef486 docs: sync remaining md (AGENTS, ARCHITECTURE, READMEs to 4001/4009, Nix) 2026-08-02 16:42:57 +07:00
asepharyana 38c27eb5bb chore: ARCHITECTURE.md DB pool example 2026-08-02 16:23:01 +07:00
asepharyana bd044e95c3 chore: env.test.example and ARCHITECTURE pool 6432 2026-08-02 16:22:48 +07:00
asepharyana ec64a078bf chore: fix-missing-tables.sql imrnes IP 2026-08-02 16:22:30 +07:00
asepharyana 37defa5915 chore: Dockerfile.backend expose port 4001 2026-08-02 16:21:48 +07:00
asepharyana 39421c39cb chore: sync port references and docs to 4000s infra 2026-08-02 16:20:27 +07:00
asepharyana 1d27f67788 chore: update gmw-proxy nginx template ports to 4009/4001 2026-08-02 15:16:16 +07:00
asepharyana d1e6f3b47a chore: update ports to 4000-range (4000/4001) 2026-08-02 14:30:54 +07:00
asepharyana dbcf9d68f2 fix(media): publish status when a track ends naturally
The Redis media:status key was only rewritten after a command received via
Redis. When the last track ended naturally (AudioPlayer Idle -> advanceQueue
with an empty queue), currentTrackItem was cleared but the status key was not
persisted — so the backend's cached status and the frontend's 10s polling
stayed stuck showing the finished track as 'playing' forever.

Wire a media-status sink (commandHandler provides the real redisPub to
MediaHandler) and re-publish status after auto-advance, so natural track end
updates the UI.
2026-08-02 10:43:34 +07:00
asepharyana ef4281cd1f fix(voice): activity tab rendered a permanently empty chart
VoiceActivityTimeline was never given a data prop — the Activity tab always
showed an empty Recharts bar chart while the connection tab already had live
speaker state. Replace the dead chart with a live speaker/activity list fed
from the same WebSocket data, so the tab reflects real state instead of
misleading empty bars.
2026-08-02 10:38:02 +07:00
asepharyana 25f6609a9f fix(recordings): stop faking duration from file size + render edited content in search
The voice_recordings table has no duration column, but the backend aliased
duration_bytes = size_bytes (file size in bytes) and RecordingCard divided it
by 60 as if it were seconds — a 3MB MP3 rendered as a nonsensical '55924:3'
fake timestamp. Drop the fabricated field and show real file size instead.

Also render edited_content fallback in the analysis search results for
consistency with message cards/detail.
2026-08-02 10:32:58 +07:00
asepharyana 3f199aa70d fix(messages): merge partial WS updates + display edited content
message_updated broadcasts only {id, edited_content, edited_at} (+ reset
ai_* fields), but the frontend replaced the whole cached record, wiping
username/content/channel_id/created_at -> blank cards and the
'the channel_id of undefined' crash on /messages. Merge partials over the
existing record (list + detail), make list-patching channel-filter aware,
show edited content/badge, and fix the message_updated WS type.

Also broadcast type:'edited' + ai reset in message_updated so the live UI
matches the DB update.
2026-08-02 10:27:41 +07:00
asepharyana a82265f4a9 chore: remove outdated README.md file 2026-08-02 10:18:56 +07:00
asepharyana 78d514b73d feat(dashboard): message activity timeline + moderation donut
Backend:
- GET /api/dashboard/activity?days=1..90 — daily buckets (messages,
  flagged, active_users) + hourly distribution last 24h
- clamped days param, reuses existing indexes (idx_messages_created,
  ai_status_created)

Frontend:
- ActivityChart: area chart messages+flagged per day, 7/14/30d range
- HourlyActivityChart: 24h bars with peak highlight
- ModerationDonut: clean/flagged/warned/error breakdown with live
  summary line (server X% clean)
- Dashboard layout: activity 2/3 + donut 1/3, hourly + top channels

Verified: endpoint returns real data from prod DB (784/1897/8 msgs
per day), tsc clean backend+frontend.
2026-08-01 23:06:00 +07:00
asepharyana 7d2bd75f6c ci: exclude e2e.test.ts from CI unit run (needs live backend API_BASE) 2026-08-01 22:21:55 +07:00
asepharyana b3a2f2ec10 ci: add test+typecheck gate before deploy
Sebelumnya CI hanya build nix -> deploy tanpa verifikasi — placeholder
tests sempat rusak berbulan-bulan tanpa terdeteksi. Job 'test' baru:
- pnpm install + tsc --noEmit + vitest run untuk backend & discord-gateway
- biome check (errors fail, warnings pass)
- build-and-deploy now needs: test
2026-08-01 22:10:28 +07:00
asepharyana 6293d588bc chore(lint): biome cleanup across services — format, sort imports, drop unused
- discord-gateway: 74 lint errors -> 0 (format, import sorting, unused
  imports/vars, dead breath var)
- backend: format + sort imports (11 warnings left: noExplicitAny)
- frontend: remove unused imports, drop dead breathing var, fix
  useExhaustiveDependencies (scroll keyed on messages), a11y biome-ignore
  for drag surface + stopPropagation container (mouse-only gestures)
- remaining warnings are false positives: index keys on static lists,
  <img> in static export (next/image unsupported), noExplicitAny

tsc --noEmit clean on all 3 services; vitest green (60+36).
2026-08-01 22:09:02 +07:00
asepharyana 2357421841 fix(test): repair placeholder tests referencing deleted @bete/shared package
packages/shared dihapus (5802d02), modul pindah ke src/shared/. Update
import placeholder.test.ts (gateway + backend) ke path lokal + aktifkan
tests/ di backend vitest config dengan alias @. Sebelumnya vitest run
gateway selalu gagal; sekarang 60+36 tests pass.
2026-08-01 22:08:54 +07:00
asepharyana 308be9f05a fix(nix): restrict flake to x86_64-linux (nixpkgs 26.11 dropped darwin) 2026-08-01 18:03:41 +07:00
asepharyana a0b3f7e9b2 ci: publish flake to FlakeHub (rolling) 2026-08-01 17:58:19 +07:00
asepharyana 98064d1dd9 feat(fe): recordings — visible playing/loading/paused states
- recording-card: kartu aktif di-highlight (ring primary + glow pulse),
  badge 'Now Playing'/'Loading'/'Paused', tombol play berubah jadi Pause
  saat playing dan spinner saat loading, waveform equalizer beranimasi
  (animate-eq, delay per bar) saat playing / pulse saat loading.
- recording-player: jadi now-playing panel — tombol play/pause + spinner
  loading, progress bar + waktu (current/duration), status 'loading…',
  audio element pindah ke sini + event onPlay/onPause/onWaiting/onCanPlay/
  onPlaying/onError naik ke page.
- recordings/page: state isPlaying/isLoadingAudio + audioRef, togglePlay
  (klik card lain = ganti track, klik card sama = pause/resume).
- globals.css: keyframes eq-bounce + card-glow.

Verified: FE tsc0, next build 10/10 static pages.
2026-08-01 16:54:58 +07:00
asepharyana 0daee56213 ci: migrate CI to GitHub Actions (deploy nix + mirror ke Gitea backup)
Mirror to Gitea / mirror (push) Successful in 26s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Failing after 32m40s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Failing after 18m0s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Failing after 18m0s
2026-08-01 16:40:27 +07:00
asepharyana 762e78d6b6 feat(fe): play Discord voice live + fix recording play/download
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m42s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m11s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m4s
Voice page (connection tab):
- ListenControl baru: toggle Listen (Headphones) — mulai PcmPlayer dari
  user gesture, subscribe onPcm WS, volume slider, bar level per-user
  REAL dari PCM (bukan random).
- lib/audio/pcm-player.ts (baru): ScriptProcessorNode mixer — ring buffer
  2s per user (hash FNV-1a sama dengan gateway), upsampling 24k→48k
  linear, mix semua user ke mono, gain volume, cleanup ring diam 5s.
- useVoiceListen + hashUserId di hooks; auto-stop saat disconnect.

Recordings:
- recording-player: reset src+load+play() eksplisit (bukan autoPlay doang),
  tampilkan filename + error state 'playback failed' kalau file rusak.
- recording-card: tombol Download fetch blob (CORS tele open) → objectURL
  → force download dengan nama asli; fallback buka tab baru kalau fetch
  gagal; spinner saat mendownload.

Verified: FE tsc 0, next build 10/10 static pages.
2026-08-01 16:30:56 +07:00
asepharyana 6ce784471e fix(gateway): repair Ogg page CRCs + deliver recordings as MP3
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m44s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m13s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m33s
Root cause rekaman gak bisa dibuka: prism-media OggLogicalBitstream
dipanggil dengan crc:false (node-crc dihapus dari dependency tree) —
semua page Ogg punya checksum 0 — player strict (ffmpeg, iOS) tolak
dengan 'CRC mismatch / End of file'. Rekaman 13:11 terbukti CRC-invalid.

Fix:
1. recorder/oggCrc.ts (baru): recompute CRC-32 (RFC3533, poly 0x04c11db7,
   initial 0, MSB-first) tiap page OggS in-place — pure JS tanpa native dep.
2. segmentFinalizer.ts: panggil fixOggCrc sebelum upload/merge.
3. recorder/uploader.ts: transcode segment ke MP3 (libmp3lame 128k 48k
   stereo) sebelum upload tele — universal playback. filename+size DB
   di-update; source OGG tetap untuk transkripsi.
4. muxer.ts + recorder.ts: merged session file juga .mp3.

Verified: ffprobe baca segmen yang tadinya CRC mismatch, MP3 valid.
2026-08-01 16:05:51 +07:00
asepharyana 0ef2b715c4 fix(gateway): enable stream for all LLM calls — router always streams SSE
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m36s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m9s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m29s
Audit lanjutan: 6x 'LLM API request failed: Request was aborted' per jam.
Root cause: 9router/omniroute SELALU balas SSE (data: chunks) walau request
tanpa stream:true — SDK OpenAI non-stream menunggu FULL body sebelum parse,
jadi batch moderasi besar yang upstream-nya lambat kena timeout 30-60s dan
di-abort. llmClient sudah punya agregasi streaming (chunks → ChatCompletion).

Fix: stream:true di llmCaller (moderasi batch/individual), llmVision,
cultureLearner, userProfileLearner. Verified: SDK stream test 806ms vs
sebelumnya abort. Caller lain (recovery worker dll) lewat llmCaller sama.
2026-08-01 15:00:59 +07:00
asepharyana dfe689bdec fix(gateway): mediaAnalysis ffprobe path, fallback error-log, generic closer sanitize
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m47s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m11s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m36s
Audit log produksi (sejak deploy13:38) menemukan 3 isu:
1. mediaDownloader.ts spawn /usr/bin/ffprobe + /usr/bin/ffmpeg (path keras) —
   ENOENT di Nix karena binary cuma di ffmpeg-headless closure. Pakai
   PATH-resolved ('ffprobe'/'ffmpeg') seperti voice-recording module
   (ffmpegProcess.ts/transmitter.ts) — 5 media warning hilang.
2. individualFallbackProcessor log error 'Success' di level50 tiap fallback
   BERHASIL (logModerationError dengan new Error('Success')) — ganti
   logger.info dengan verdict yang sama; error log cuma untuk error asli.
3. moderationResponseParser: strip frasa penutup generik ('Tidak ada
   indikasi pelanggaran.') yang masih sering dikeluarkan LLM walau prompt
   melarang (277/1486 analisis mengandung frasa, termasuk hari ini).
   sanitizeGenericCleanCloser hanya mencocok frasa di AKHIR, teks substantif
   tetap utuh. Unit test: 6/6 pass.
2026-08-01 14:00:43 +07:00
asepharyana ada7a768f8 fix(gateway): bump 0011 voice_transcription journal when above applied max
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m15s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m23s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 10m59s
Migration 0011 (add voice_recordings.transcription) when=1781388000000
lebih kecil dari 0010 (1781390000000) yang sudah ter-apply — drizzle
skip diam-diam (folderMillis <= max(created_at)), kolom transcription
tidak pernah dibuat. Recording OGG sukses tapi INSERT voice_recordings
gagal 42703 di produksi.

Fix: when=1785600000000 (> max applied 1785551832190) + apply manual
ALTER TABLE + insert row __drizzle_migrations dengan hash file yang
sama (c368acb0...) supaya gateway restart berikutnya skip (idempotent).
2026-08-01 13:15:03 +07:00
asepharyana 493bca590d fix(infra): build native voice deps (opus, datachannel) in Nix closure
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 4m21s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 4m22s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 11m31s
pnpm 11 rebuild hanya jalanin script package yang di-approve via
pnpm-workspace.yaml (allowBuilds) DAN abort di kegagalan pertama.
Yaml harus tracked (flake source cuma ikut file git). Tapi pnpm rebuild
tetap gagal karena: (1) node-crc MSRV cargo:: error — dead dep, dihapus
dari deps+patch; (2) sharp install script gagal di sandbox — binary-nya
prebuilt @img, script cuma validasi — dikeluarkan dari approval list;
(3) node-datachannel prebuild CLI TypeError + cmake-js butuh cwd benar.

Fix: loop eksplisit di buildPhase gateway yang jalankan install script
tiap native dep (opus/node-datachannel/zeromq) dengan cwd package dir,
+ cmake (dontUseCmakeConfigure biar stdenv nggak auto-configure),
+ opensslDevEnv = symlinkJoin pkgsStatic.openssl.out (libcrypto.a —
CMakeLists set OPENSSL_USE_STATIC_LIBS=TRUE; pkgs.openssl default
output = bin tanpa lib) + openssl.dev (headers),
+ git (libdatachannel FetchContent clone dari GitHub).

Verifikasi: result store punya opus.node (compile source), node_datachannel.node
(compile source), node-av prebuilt, zeromq prebuilt; runtime smoke test:
PeerConnection instantiate+close OK, OpusEncoder encode OK, dank074
Streamer/prepareStream/playStream load OK.
2026-08-01 12:44:01 +07:00
asepharyana 823b484497 chore(gateway): pnpm 11 build-script approvals (allowBuilds) for native voice deps
pnpm 11.17 mengabaikan field pnpm.onlyBuiltDependencies di package.json.
Native deps voice (@discordjs/opus, @lng2004/node-datachannel, zeromq, dll)
tidak pernah kebangun di Nix store karena flake pnpmInstall pakai
--ignore-scripts dan pnpm rebuild tanpa approval. Hasil: receiver/rekaman/
GoLive diam-diam tanpa decoder/encoder native.

pnpm approve-builds --all menulis allowBuilds:true per package di
pnpm-workspace.yaml (harus tracked — flake source cuma ikut file git).
node-crc tetap gagal build (MSRV cargo:: check) tapi tidak pernah
di-import di source — harmless.
2026-08-01 11:47:01 +07:00
asepharyana 891c1305f0 feat(gateway): restore Discord GoLive screenshare (dulu pernah ada, hilang saat split microservices)
User: 'dulu sharescreen juga bisa'. Terbukti: commit d50ce86 (Mei 2026)
punya src/media/screenShareController.ts + vendor @dank074/discord-video-stream,
hilang saat rombak monolith -> microservices. Interface ScreenShareController
masih ada di mediaTypes.ts tapi implementasinya tidak.

Restore:
- dep @dank074/discord-video-stream@6.0.0 (npm, dibangun untuk
  discord.js-selfbot-v13 — cocok dengan stack gateway)
- mediaSource.getDirectVideoUrl (yt-dlp --get-url bestvideo+bestaudio)
- screenShareController.ts (BARU): Streamer(client) + prepareStream H264
  720p30 + playStream go-live; owner check via discordPlayer
- media.handler: mode:'screen' di media:queue -> screen path; status
  expose activeMode; stop matiin screen
- FE: tombol Screen di MusicPlayer + hook useMediaQueue({url, mode})

Verifikasi: gateway tsc PASS, FE tsc PASS, biome 0 error, next build PASS.
Nix build pending (dep native @lng2004/node-datachannel butuh pnpm rebuild).
2026-08-01 11:36:40 +07:00
asepharyana 189ab1c1f6 feat(fe): real mic capture for voice transmit (kirim suara)
Sebelumnya tombol Live/Muted cuma kirim voice:transmit:start/stop ke
gateway — TIDAK ADA audio yang dikirim (0 getUserMedia/AudioContext di
frontend). MicControl cuma toggle state kosong.

- lib/audio/mic-transmit.ts (BARU): getUserMedia → AudioContext 48kHz →
  AudioWorklet (downsample 24kHz mono s16le + volume + chunk 20ms) →
  frame 'PCM\0' + Int16LE → ws.sendBinary. Worklet inline via Blob URL
  (aman untuk static export).
- useMicTransmit(ws): aktif = start capture + voice:transmit:start;
  nonaktif = stop capture + voice:transmit:stop; setVolume untuk slider.
- voice page: volume slider sekarang beneran ngatur gain mic; disconnect
  ikut matiin mic.

Verifikasi: tsc PASS, biome 0 error, next build PASS. Test mic butuh
real device (headless browser tidak punya mic) — protokol: connect voice
→ Live → ngomong → orang di channel denger.
2026-08-01 11:26:18 +07:00
asepharyana 9d60f00934 fix(infra): add ffmpeg + yt-dlp to gmw-discord-gateway runtime
Root cause voice tidak berfungsi di produksi: ffmpeg & yt-dlp cuma ada
di devShell, bukan di package discord-gateway. Bukti dari log gateway:
'FFmpeg/avconv not found!' saat voice:transmit:start (mic -> Discord),
yang juga mematikan music playback (StreamType.Arbitrary butuh ffmpeg)
dan segment muxing rekaman.

- buildInputs: pkgs.ffmpeg-headless + pkgs.yt-dlp
- wrapper export PATH ke keduanya sebelum exec node
Verifikasi: nix build PASS; closure berisi ffmpeg-8.1.2 + yt-dlp-2026.07.04;
wrapper PATH mengarah ke keduanya; ffmpeg/yt-dlp jalan.
2026-08-01 11:22:20 +07:00
asepharyana 903e7c4aeb feat(fe): remove Settings page from dashboard
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m7s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m28s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m28s
Hapus halaman /settings + nav item Settings (TopNav/HiddenSidebar
via navItems). GlassDivider ikut dihapus (cuma dipakai settings).
useConfig tetap (dipakai guild-selector).

Verifikasi: tsc PASS, biome 0 error, next build PASS (10 halaman
static, settings hilang).
2026-08-01 11:13:47 +07:00
asepharyana 0771e62223 feat(fe): remove Live tab from dashboard
Hapus tab Live + komponennya (LiveStream, ModQueue) dari halaman
dashboard — tab Stats/Users/Channels tetap. useReview tetap dipakai
messages page (review tab), jadi hook tidak dihapus.

Verifikasi: tsc PASS, biome 0 error, next build PASS.
2026-08-01 11:10:36 +07:00
asepharyana 8e7ba67248 fix: message detail shows only its own images, not everyone's
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m47s
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m12s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m12s
useMessageDetail fetch attachments per-channel -> detail view nampilin
10 image terbaru di channel itu (semua orang), bukan image pesan yang
diklik. Root cause: getAttachmentsByChannel cuma filter channel_id.

- backend: messageQuerySchema + messageId optional; repository
  tambah eq(message_id) pas messageId ada. Sudah ada index
  idx_attachments_message.
- frontend: getAttachments(channelId, limit, cursor, messageId);
  useMessageDetail pass id pesan.

Verifikasi: backend tsc PASS, frontend tsc PASS + next build PASS.
E2E local (tsx + env prod, port 3901): tanpa messageId -> 3 row
(termasuk image.png punya message lain); dengan messageId -> tepat
2 row milik pesan itu. psql juga konfirmasi channel-only 3 vs
message-filtered 2.
2026-08-01 10:59:54 +07:00
asepharyana 8a4024f619 fix(fe): crash 'reading charAt' on message avatar fallback
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m47s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m2s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m19s
msg.username bisa undefined saat pesan live masuk lewat WS
(message_updated Partial payload / capture tidak lengkap) ->
msg.username.charAt(0) TypeError, halaman /messages mati.

- message-card + search-panel: username?.charAt(0) ?? '?'
- created_at di-guard juga biar tidak render 'Invalid Date'
Verifikasi: tsc PASS, build PASS, biome 0 error. DB saat ini 0 row
null username (1176 total) — crash murni dari jalur WS live.
2026-08-01 10:37:21 +07:00
asepharyana ec89d64dbf fix(fe): crash 'reading channel_id' + recharts width/height warnings
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m14s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m53s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m15s
- useMessageDetail: guard attachments fetcher — revalidate bisa race
  detail load, detail.data undefined saat fetcher jalan ->
  TypeError 'Cannot read properties of undefined (reading channel_id)'
  yang bikin halaman /messages mati (Next error boundary). Sekarang
  fetcher balikin [] kalau channel_id belum ada; hapus non-null
  assertion. Diverifikasi: /messages sebelumnya crash, sekarang render
  dengan data asli (list, verdict, confidence, sticker, emoji).
- ResponsiveContainer (recharts 3.8): initialDimension -1 di render
  pertama -> warning 'width(-1) and height(-1)'. Pakai height numerik
  tetap (192/160/48) + minWidth/minHeight 0 -> calculatedHeight >0,
  warning hilang; width tetap responsif via ResizeObserver. Chart
  baru dirender setelah mount (useMounted) biar container punya ukuran.
  Diverifikasi console: 0 warning, 0 error di dashboard & voice.
2026-08-01 10:21:23 +07:00
asepharyana 6f41c22cb5 fix(db): migration 0013 rename mascot_chat_messages to chatbot_messages
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m17s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m59s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m7s
/api/chat/history 500 (relation "chatbot_messages" does not exist):
codebase di-rename mascot->chatbot (977a6f9) tapi tabel DB tidak
pernah di-migrate — backend SELECT dari chatbot_messages, DB masih
mascot_chat_messages dengan kolom mascot_response.

- Migration 0013 (idempotent): ALTER TABLE mascot_chat_messages RENAME
  TO chatbot_messages, RENAME COLUMN mascot_response -> bot_response,
  RENAME INDEX -> idx_chatbot_messages_user_created; journal when >
  max(created_at) di __drizzle_migrations (0012)
- Diterapkan live via psql; riwayat chat lama tetap ada
- Verifikasi: GET /api/chat/history 200 + data, POST /api/chat 200
  + tersimpan (total history 1 -> 2)
2026-08-01 09:38:27 +07:00
asepharyana 01c18b2060 refactor(fe): replace TanStack Query with SWR + UI/data cleanup
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 2m56s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 3m42s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 3m59s
Rombak data layer frontend:
- Hapus @tanstack/react-query (package.json, lockfile, provider di
  dashboard layout) — ganti SWR 2.4.2 + SWRConfig (revalidateOnFocus
  false, deduping 10s, no retry on 404)
- Semua hooks data ditulis ulang ke useSWR; useAction() helper baru
  pengganti useMutation dengan surface kompatibel (mutate/mutateAsync/
  isPending/error)
- useMessages + useMessagesHasMore share satu SWR key — probe cursor
  yang tadinya dobel fetch API sekarang deduped
- WS sync (messages/media/recordings) pindah dari queryClient ke
  SWR mutate dengan filter key + revalidate:false
- useMessageSearch() dipakai search-panel & search-overlay; search
  overlay backdrop div -> button (fix a11y lint)

Rapikan UI + isi data:
- Tab stats recordings: placeholder 'coming soon' diganti stat asli
  (total, ukuran, speaker unik, top speakers)
- Empty states konsisten via EmptyState (images/review/recordings),
  EmptyState terima className
- biome check --write: 0 error, 8 warning pre-existing
- Verifikasi: tsc --noEmit PASS, next build PASS (11 halaman static),
  API live dicek — semua endpoint dashboard/messages/guilds/config/
  voice/media/recordings/review balikin data
2026-08-01 09:19:39 +07:00
asepharyana 1f91f99de3 feat(automod): render sticker, role & user names in moderation views
QoL lanjutan dari fix60084b3: content pesan mentah masih nampilin
snowflake (<@&roleid>, <@userid>, <:emoji:id>) di log moderasi dan
prompt LLM. Sekarang dirender ke nama yang bisa dibaca:

- Gateway capture: metadata menyimpan mentionedRoles + mentionedUsers
  (id+name) dari message.mentions, disimpan ke metadata JSON
- renderDiscordMentions(): <@&id> -> @RoleName, <@id> -> @Username,
  <:name:id> -> :name:, fallback @role/@user — dipakai di
  conversationContext (konteks LLM) dan moderationBuilders
  (getAnalysisContent) sehingga LLM lihat nama role/user beneran,
  bukan placeholder generik
- Frontend renderMessageContent() (mirror gateway) dipasang di semua
  tempat nampilin content: message-card, message-detail(-view),
  search-overlay, search-panel, users/channels section, live-stream,
  mod-queue, review list; sticker-only message tetap [Sticker: name],
  pesan teks+sticker kini ikut nampilin nama sticker
- tsc --noEmit PASS di gateway & frontend; renderDiscordMentions
  diverifikasi manual (6 kasus: role/user/emoji/unknown/plain)
2026-08-01 08:56:10 +07:00
asepharyana 9ba2262446 refactor: improve image handling and accessibility in MessagesPage
Deploy to VPS / deploy (push) Successful in 2m17s
2026-07-26 17:31:44 +07:00
asepharyana eca0a378f9 fix: increase max length for user profile summary and sanitize function
Deploy to VPS / deploy (push) Successful in 2m19s
2026-07-26 17:27:51 +07:00
asepharyana b886b71bad feat: add user detail and selection functionality to dashboard
Deploy to VPS / deploy (push) Successful in 2m23s
2026-07-26 17:15:08 +07:00
asepharyana 05bbae66da Refactor voice page and hooks to use React Query for data fetching
Deploy to VPS / deploy (push) Successful in 2m57s
- Updated VoicePage component to utilize useVoiceConnect, useVoiceDisconnect, and useMicTransmit mutations.
- Replaced local state management with React Query's useQuery for voice status, guilds, and channels.
- Removed custom useAsync hook and replaced it with useQuery in useConfig, useStats, useUsers, useChannels, and useMessages hooks.
- Simplified useRecordings and useSpeakers hooks to leverage React Query for data fetching and mutations.
- Removed deprecated use-async hook and related code.
- Enhanced error handling and loading states across various hooks.
2026-07-26 16:55:20 +07:00
asepharyana 323fa207af refactor: streamline data fetching in various hooks and components
Deploy to VPS / deploy (push) Successful in 2m39s
2026-07-26 16:46:53 +07:00
asepharyana 1021301656 fix: add error logging for various API calls across components
Deploy to VPS / deploy (push) Successful in 2m20s
2026-07-26 16:34:06 +07:00
asepharyana 74eabb7231 feat: enhance guild selection logic with auto-selection based on config
Deploy to VPS / deploy (push) Successful in 2m25s
2026-07-26 16:25:04 +07:00
asepharyana 39a3bc6269 fix: add missing draining state variable in VoiceTransmitter class
Deploy to VPS / deploy (push) Successful in 2m18s
2026-07-26 16:18:33 +07:00
asepharyana d5a547eb25 feat: add app header, sidebar, and mobile navigation components
Deploy to VPS / deploy (push) Failing after 1m45s
- Implemented AppHeader component with theme toggle and connection status.
- Created AppSidebar component for navigation with connection status indicator.
- Added MobileNav component for mobile navigation with responsive design.
- Introduced shared components: DetailStat, EmptyState, ErrorState, LoadingSkeleton, and StatCard for consistent UI.
- Developed hooks for async data fetching: useAsync, useConfig, useDashboard, useGuilds, useMedia, useMessages, useRecordings, and useVoice.
- Added chatbot API functions for sending messages and managing chat history.
2026-07-26 16:14:32 +07:00
asepharyana 726ea8fca5 fix: improve readability of download URL handling in RecordingsPage
Deploy to VPS / deploy (push) Successful in 2m7s
2026-07-26 15:45:29 +07:00
asepharyana 779fb6b338 fix: prevent opening undefined download URLs in RecordingsPage
Deploy to VPS / deploy (push) Failing after 1m31s
2026-07-26 15:43:10 +07:00
asepharyana 300512b2cb refactor: clean up code formatting and improve consistency across multiple components
Deploy to VPS / deploy (push) Failing after 1m59s
2026-07-26 15:39:41 +07:00
asepharyana c2502a0e5f feat: add recordings, settings, and voice pages with WebSocket integration
Deploy to VPS / deploy (push) Failing after 1m36s
- Implemented RecordingsPage to display and manage voice recordings with live updates via WebSocket.
- Created SettingsPage for user preferences, including theme toggling and server configuration display.
- Developed VoicePage for managing voice connections, including guild and channel selection, and active speaker display.
- Introduced GuildSelector component for selecting Discord guilds with error handling and loading states.
- Added utility functions for formatting numbers and bytes, and safely parsing JSON.
- Established navigation structure for the dashboard with relevant links for new features.
2026-07-26 15:34:08 +07:00
asepharyana eae0d7ce56 feat: enhance MessagesPanel with improved UI components and functionality
Deploy to VPS / deploy (push) Successful in 2m13s
- Refactored MessagesPanel to utilize new UI components such as Avatar, Badge, Button, Card, Dialog, Input, Progress, ScrollArea, Select, Skeleton, and Tabs.
- Improved error handling and loading states with enhanced user feedback.
- Updated message rendering logic to support new design patterns and animations.
- Added support for image previews and improved layout for message details.
- Enhanced mobile responsiveness with useIsMobile hook adjustments.
- Cleaned up utility functions for better readability and consistency.
2026-07-26 15:13:18 +07:00
asepharyana f57a1caf62 refactor: standardize import statements and improve code consistency across components
Deploy to VPS / deploy (push) Failing after 1m35s
- Updated import statements to use consistent semicolon usage.
- Refactored component code to ensure consistent formatting and style.
- Improved readability by adding missing semicolons and adjusting spacing.
- Ensured all components follow the same structure for props and return statements.
2026-07-26 14:52:38 +07:00
asepharyana e2c2365208 feat: add UI components including Skeleton, Slider, Sonner, Spinner, Switch, Table, Tabs, Textarea, Toggle Group, Toggle, Tooltip, and custom hook for mobile detection 2026-07-26 14:45:47 +07:00
asepharyana 4e28136538 feat: enhance image message rendering with metadata extraction and error handling
Deploy to VPS / deploy (push) Successful in 2m12s
2026-07-26 14:42:16 +07:00
asepharyana 12b23b4632 fix: initialize release variable to prevent potential errors in start/stop methods
Deploy to VPS / deploy (push) Successful in 2m9s
2026-07-26 14:30:36 +07:00
asepharyana 0a6a9fd982 feat: update dependencies and improve dashboard functionality
Deploy to VPS / deploy (push) Failing after 1m43s
- Added new dependencies for Next.js and lucide-react in pnpm-workspace.yaml.
- Refactored DashboardPage component to improve readability and error handling.
- Enhanced Header component to display error status with an alert icon.
- Updated MobileTabBar and Sidebar components to use a centralized tabs definition.
- Improved ChannelsView in dashboard-panel to handle channel fetching more cleanly.
- Fixed ActiveSpeaker type to use camelCase for userId.
- Updated MessagesPanel to handle guildId checks more gracefully.
- Adjusted API calls in dashboard and messages to align with backend expectations.
- Refined type definitions across various interfaces for consistency and clarity.
2026-07-26 14:27:36 +07:00
asepharyana 9ecc4a6caa refactor(docs): update project documentation for clarity and accuracy
Deploy to VPS / deploy (push) Failing after 1m38s
2026-07-26 13:45:05 +07:00
asepharyana 702f96262e ci: add frontend to pnpm workspace via services/*
Deploy to VPS / deploy (push) Successful in 2m26s
- Change pnpm-workspace.yaml from specific paths to services/* and packages/*
- Remove bun.lock (frontend now uses pnpm lockfile)
- Use --no-frozen-lockfile so lockfile auto-updates in CI
2026-07-26 13:13:59 +07:00
asepharyana d5253ebab0 ci: fix frontend build outside pnpm workspace
Deploy to VPS / deploy (push) Failing after 1m47s
Frontend not in pnpm workspace (uses bun.lock locally), so build it
directly with pnpm install + build in its own directory.
2026-07-26 13:03:49 +07:00
asepharyana cedce85087 ci: fix lint errors for CI
Deploy to VPS / deploy (push) Successful in 1m47s
- Fix noImplicitAnyLet: add type to let match variable
- Fix noAssignInExpressions: use matchAll() + for-of instead of while
- Suppress useExhaustiveDependencies in mascot scroll effect
- Suppress useSemanticElements for message card click handler
2026-07-26 12:01:51 +07:00
asepharyana 42595a75f3 ci: merge biome configs to fix nested config error
Deploy to VPS / deploy (push) Failing after 1m28s
Root and services/frontend each had a biome.json causing Biome to
error on nested configuration. Merged frontend-specific rules and
domains (next, react) into root biome.json, removed nested config.
2026-07-26 11:55:10 +07:00
asepharyana a85c7da5ed ci: add Rust for node-crc native build
Deploy to VPS / deploy (push) Failing after 1m26s
Install dependencies step fails because node-crc requires cargo
to compile its native N-API module. Restore Rust setup in CI.
2026-07-26 11:45:49 +07:00
asepharyana 2ecba1691b docs: update all markdown files, switch remote to Gitea
Deploy to VPS / deploy (push) Failing after 34s
- Update root README.md: remove Leptos/WASM/SQLite, document Next.js
- Update frontend README.md: replace create-next-app boilerplate
- Update frontend AGENTS.md: project-specific overview
- Update CLAUDE.md: remove all auth references
- Update backend ARCHITECTURE.md: remove adminAuth from middleware list
- Switch git remote from gitlab to gitea (origin → gitea)
2026-07-26 11:38:53 +07:00
asepharyana 831fddd1bf refactor(backend): remove auth for public API
Deploy to VPS / deploy (push) Failing after 35s
- Remove auth module (auth.routes.ts, /api/auth/login)
- Remove adminAuth middleware from voice and media routes
- Remove adminAuth() function from shared middlewares
- Remove auth-related e2e test
- Clean up .env.example
2026-07-26 11:33:45 +07:00
asepharyana f9f1313ccd refactor: remove login/auth for public dashboard
Deploy to VPS / deploy (push) Failing after 34s
- Remove login page, redirect / to /dashboard directly
- Remove AuthProvider, DashboardGuard from dashboard layout
- Remove use-auth hook and auth API module
- Remove X-Admin-Password header from API client
- Remove logout button from sidebar
2026-07-26 11:30:27 +07:00
asepharyana 5e01ec0806 feat: migrate Leptos frontend to Next.js 16 (React 19)
Deploy to VPS / deploy (push) Failing after 42s
Complete migration from services/frontend.old/ (Leptos 0.7 WASM + Rust)
to services/frontend/ (Next.js 16 static export + TypeScript + Tailwind v4).

Summary:
- Port all shared types (message, guild, voice, media, dashboard, recording, ui)
- Build fetch-based API client covering all 30+ backend endpoints
- WebSocket client with auto-reconnect (exponential backoff, 20 attempts)
- React context provider for WS with typed event subscription (22 event types)
- Login page with localStorage auth + auto-redirect
- Dashboard layout with sidebar, header (WS status + theme toggle)
- Messages: feed, search, images tab, review tab, channel filter, detail modal
- Live: voice connection, music player, recordings, mic transmit, active speakers
- Dashboard: stats, user list, channel list, detail views
- Mascot chatbot with history + clear
- uiStateApi persistence for selected tab
- Add static export config, update deploy scripts and CI
2026-07-26 11:27:21 +07:00
asepharyana cbbe939fad ci: build shared package before services
Deploy to VPS / deploy (push) Successful in 10m26s
2026-07-08 01:52:51 +07:00
asepharyana 9621317a3c chore: format files for lint
Deploy to VPS / deploy (push) Failing after 8m8s
2026-07-08 01:37:46 +07:00
asepharyana a5cf780a65 ci: add gitea deploy workflow 2026-07-08 01:36:51 +07:00
asepharyana df5571664d ci: make deploy script provider neutral 2026-07-08 01:35:58 +07:00
asepharyana 7a4a9350b1 docs: add gitea migration implementation plan 2026-07-08 01:35:52 +07:00
asepharyana 74b05ee667 docs: add gitea migration design 2026-07-08 00:56:06 +07:00
asepharyana af3c852a5b Refactor code structure for improved readability and maintainability 2026-07-06 00:58:41 +07:00
asepharyana 0ba4228042 feat: add WebSocket connection handling and UI styles
- Implemented WebSocket connection management in `connection.rs` with automatic reconnection and event handling.
- Created `handlers.rs` to define WebSocket event and status enums.
- Added global CSS reset styles in `reset.css`.
- Introduced design tokens in `tokens.css` for consistent theming.
- Developed UI component styles in `ui.css`, including buttons, cards, badges, and modals.
- Added utility classes in `utilities.css` for layout, spacing, and typography.
2026-07-05 21:18:59 +07:00
asepharyana e7d4a45391 feat: add design specifications for AeroNet Visualization, Nexus Capital Render, and Summit Cloud Migration Platform 2026-07-05 20:33:13 +07:00
asepharyana e3228af196 feat(logging): Implement structured logging across the frontend
- Introduced a new `logger` module for structured logging with levels, timestamps, and styled console output.
- Replaced ad-hoc console logging with structured logger in various modules including API client, WebSocket, auth, and feature components.
- Enhanced logging in `app.rs`, `auth.rs`, `dashboard`, `messages`, `live`, and `polish` features.
- Updated UI components to include logging for user interactions and state changes.
- Rewrote `app.css` for a premium design overhaul, introducing glassmorphism, gradients, and improved responsiveness.
- Added a new `plan.md` file outlining the scope and changes made in this commit.
2026-07-05 19:55:13 +07:00
asepharyana 03b257d5a7 fix(deploy): use trunk build for frontend, not pnpm 2026-07-05 07:06:34 +07:00
asepharyana 0668862db5 fix: use bind mounts for hot-deploy so changes survive container restart
deploy.sh now writes to host directories bind-mounted into containers
instead of docker exec tar-pipes (volatile). Added bind mounts to
docker-compose.yml for all 3 services (frontend, backend, gateway).

Memory: hotpatch-volatile-container.md
2026-07-05 07:05:01 +07:00