56 Commits
Author SHA1 Message Date
asepharyana f20889868d feat(frontend): rebuild as SSR with server-authoritative shared state
Rombak total alur data frontend: dari static-export CSR (tiap browser
fetch sendiri + akumulasi state voice per-tab) jadi server-side rendering.

Frontend (Next.js):
- next.config: output export -> standalone; halaman jadi server components
- server data layer baru src/lib/api/server.ts (GMW_BACKEND_URL, no window)
- dashboard/media/messages/moderation/recordings/voice page -> RSC yang
  fetch backend di render-time, seed ke client view (SWR fallbackData)
- hook-hook utama terima initialData -> first paint data server, revalidate
  SWR setelahnya, tanpa spinner-blank-load
- messages: guild/channel/tab/selected dibaca dari URL di server, page awal
  di-fetch server-side

Shared realtime state (voice) server-authoritative:
- backend src/modules/voice/live-speaker.ts: agregat voice_active_user dari
  gateway jadi snapshot authoritatif (single source of truth semua browser)
- GET /api/voice/status kini include activeSpeakers
- WS initial states kirim voice_state snapshot saat connect (late join
  langsung dapat state yang sama, bukan daftar kosong)
- useSpeakers seed dari server snapshot + voice_state full-replace +
  voice_active_user delta upsert

Deploy:
- flake.nix: frontend package build SSR standalone (server.js wrapper,
  GMW_FRONTEND_PORT=4017); proxy nginx template proxy / -> Next server,
  /api + /ws tetap ke backend :4001
2026-08-07 10:44:03 +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
Developer 2addfb6492 fix(proxy): relative redirects so Traefik doesn't leak :8080 2026-07-31 16:54:41 +07:00
Developer 24aa2bca30 fix: nginx listen on 0.0.0.0:8080 for Docker Traefik access
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 3m14s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m28s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 2m38s
127.0.0.1 from inside Docker container is the container's own
loopback, not host's. Changed to listen 8080 (all interfaces)
so Traefik can reach it via host.docker.internal:8080.
2026-07-30 20:56:29 +07:00
Developer 05eb490214 fix: nix wrappers, path aliases, env config for systemd deployment
Build & Deploy (Nix) / build-and-deploy (backend) (push) Successful in 1m33s
Build & Deploy (Nix) / build-and-deploy (discord-gateway) (push) Successful in 2m33s
Build & Deploy (Nix) / build-and-deploy (proxy) (push) Successful in 2m36s
- Fix wrapper scripts: shebang at column 0, no $@ expansion
- Fix @/ path alias resolution in compiled JS (tsc doesn't resolve paths)
- Fix nginx log dirs (error_log, access_log, nginx.pid)
- Add correct env files with proper DB password
- Set user:group to gmw for env file access
- Tested: all 3 services active & healthy
2026-07-30 18:06:17 +07:00
Developer 0c6e18db77 perf: optimize Docker images - backend 294MB, gateway 1.89GB
Build & Deploy / build-and-push (backend) (push) Failing after 1m25s
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 26s
Build & Deploy / build-and-push (proxy) (push) Failing after 25s
Backend:
- node:22-alpine runtime (from 1.82GB to 294MB, 84% reduction)
- COPY --chown instead of chown -R layer
- pnpm install --prod after build for clean .pnpm store
- Pinned pnpm@10 to avoid v11 build-script lockout

Gateway:
- Fixed TypeScript errors (missing table defs in shared schema)
- Restored node-crc Rust patch for native compilation
- Multi-stage build with COPY --chown
- pnpm install --prod after build
- ffmpeg with --no-install-recommends

Proxy:
- Restructured for standalone build (build errors are pre-existing)

General:
- pnpm@10 in all builds (avoids ERR_PNPM_IGNORED_BUILDS)
- Clean .dockerignore (excludes docs/design/scripts)
2026-07-30 13:18:44 +07:00
Developer db021cb1f6 refactor: finalize standalone services cleanup
Build & Deploy / build-and-push (backend) (push) Failing after 39s
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 26s
Build & Deploy / build-and-push (proxy) (push) Failing after 24s
- Remove root pnpm-lock.yaml (stale monorepo lockfile)
- Rename root package from bete-monorepo to bete
- Clean up root scripts to use cd instead of pnpm --prefix
- Remove ignoreScripts/trustedDependencies from frontend package.json
- Optimize Dockerfiles with multi-stage builds and proper layer caching
- Update .dockerignore to exclude build artifacts
- Remove leftover pnpm test config file from frontend
2026-07-30 12:14:24 +07:00
Developer dcd13482c2 refactor: break monorepo into 3 standalone services (gateway, backend, frontend)
Build & Deploy / build-and-push (backend) (push) Failing after 35s
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 25s
Build & Deploy / build-and-push (proxy) (push) Failing after 25s
- Remove pnpm workspace, moon repo, and all monorepo tooling
- Delete packages/shared/, embed shared code directly into each service
- Copy packages/shared/src/* -> services/backend/src/shared/ and services/discord-gateway/src/shared/
- Replace all @bete/shared imports with @/shared/ path alias
- Remove @bete/shared workspace dependency from both services
- Update root package.json scripts from --filter to --prefix
- Rewrite Dockerfiles to build each service standalone
- Clean up biome.json, .gitignore, remove root drizzle.config.ts
2026-07-30 11:50:48 +07:00
DeveloperandClaude Opus 4.8 7bebb23c1d fix: add disk cleanup to CI and reduce Docker layers
Build & Deploy / build-and-push (backend) (push) Successful in 7m34s
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 8m19s
Build & Deploy / build-and-push (proxy) (push) Failing after 1m12s
Runner runs out of disk space during discord-gateway build.
Add docker system prune before build and combine Dockerfile
layers to reduce disk usage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-28 15:47:23 +07:00
DeveloperandClaude Opus 4.8 8d0f505784 fix: add --legacy flag to pnpm deploy for pnpm v11 compatibility
Build & Deploy / build-and-push (backend) (push) Successful in 27s
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 8m1s
Build & Deploy / build-and-push (proxy) (push) Failing after 8m2s
pnpm v11 requires --legacy flag (or inject-workspace-packages=true)
for pnpm deploy to work with non-injected workspace packages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 22:06:13 +07:00
DeveloperandClaude Opus 4.8 5802d02e29 refactor: large codebase cleanup - consolidate schemas, migrate to Drizzle ORM, extract frontend components, modernize Docker builds
Build & Deploy / build-and-push (discord-gateway) (push) Failing after 2m22s
Build & Deploy / build-and-push (backend) (push) Failing after 3m22s
Build & Deploy / build-and-push (proxy) (push) Successful in 1m36s
Build & Deploy / deploy (push) Skipped
- Consolidate all DB schema definitions into packages/shared as single source of truth
- Migrate backend from raw SQL to Drizzle ORM across all modules
- Extract frontend inline UI into separate component files
- Refactor discord-gateway circuitBreaker into conversationState + moderationState
- Convert messageStore to Proxy singleton pattern
- Add validateBody/validateQuery middleware + Zod schemas for API endpoints
- Modernize Docker builds with multi-stage + pnpm deploy
- Migrate CI/CD from deployment to image-based pipeline
- Remove 60+ unused/dead files (~15K lines)
- Update color scheme from sky-blue to teal-cyan
- Move DB connection management to @bete/shared/database

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 21:54:31 +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
asepharyana b5d4e46b79 fix(ci): deploy by SHA tag, not mutable :latest
Deploy now pulls images pinned to $CI_COMMIT_SHA instead of :latest,
eliminating race-condition deployments where a concurrent pipeline
overwrites the mutable latest tag before deploy runs.

Changes:
- docker-compose.yml: image tags use ${IMAGE_TAG:-latest} env var
- deploy step: IMAGE_TAG=$CI_COMMIT_SHA docker compose pull + up
- scp docker-compose.yml to VPS before running deploy commands
2026-07-05 03:43:13 +07:00
asepharyana 5fa97da969 chore: remove WASM MIME type declaration from nginx configuration 2026-07-04 05:02:25 +07:00
asepharyana 9614546243 feat: upgrade frontend deps — leptos 0.9.0-alpha, leptos-use 0.19, trunk 0.22.0-beta.1 2026-07-04 05:00:18 +07:00
asepharyana 27e929580e feat: update components and hooks to use get_untracked for improved performance 2026-07-04 03:03:36 +07:00
asepharyana c5a9371e71 fix(infra): nginx upstream DNS staleness — 502 after backend restart
- Replace upstream blocks with variable-based proxy_pass + Docker DNS
  resolver (127.0.0.11) so nginx resolves hostnames dynamically on
  each request instead of caching at startup only.
- Add explicit 'docker compose restart proxy' in CI deploy step
  (belt-and-suspenders: also forces nginx restart after deploy).
- Remove no-op sed commands from CI (docker-compose.yml already uses
  GitLab registry, no ghcr.io replacements needed).

Root cause: docker compose up -d only recreates containers whose image
changed. When backend container is recreated (new Docker IP), nginx
still caches the old IP → 502 Bad Gateway on /api/*
2026-07-02 04:22:16 +07:00
asepharyana fa82593a38 fix: switch to node:22-slim, install deps from npm, remove vendor 2026-07-02 04:07:18 +07:00
asepharyana 950bc03708 chore: update docker-compose to GitLab registry, remove .gitmodules 2026-07-02 04:03:21 +07:00
asepharyana d37cecdb38 Revert "fix(Dockerfile): use node:22-slim for backend (glibc), add linux-headers + nodedir for gateway"
This reverts commit 9e8f4377af.
2026-07-02 03:54:44 +07:00
asepharyana 81f541c080 Revert "fix(Dockerfile): switch discord-gateway to node:22-slim for opus compatibility"
This reverts commit 51d3e47fe3.
2026-07-02 03:54:44 +07:00
asepharyana c408a8d1f7 Revert "fix(Dockerfile): install Rust via rustup for node-crc compatibility"
This reverts commit 0200c77fc2.
2026-07-02 03:54:44 +07:00
asepharyana 91e14abbda Revert "fix: update nginx for Astro SSG — /_astro/ cache, remove SPA fallback"
This reverts commit 918e45f9da.
2026-07-02 03:54:44 +07:00
asepharyana 918e45f9da fix: update nginx for Astro SSG — /_astro/ cache, remove SPA fallback 2026-07-02 03:42:56 +07:00
asepharyana 0200c77fc2 fix(Dockerfile): install Rust via rustup for node-crc compatibility 2026-07-02 02:29:36 +07:00
asepharyana 51d3e47fe3 fix(Dockerfile): switch discord-gateway to node:22-slim for opus compatibility 2026-07-02 02:26:34 +07:00
asepharyana 9e8f4377af fix(Dockerfile): use node:22-slim for backend (glibc), add linux-headers + nodedir for gateway 2026-07-02 02:22:09 +07:00
MythEclipseandClaude Fable 5 490aad7704 fix(ci): add build tools to backend Dockerfile for native deps
@discordjs/opus requires Python and C++ build tools for native
compilation. The discord-gateway Dockerfile already had these but
the backend Dockerfile was missing them, causing CI build failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:58:47 +07:00
MythEclipse f04b0f0b42 refactor(voice): optimize recording pipeline and improve performance
Refactor the voice recording and playback systems to improve efficiency, reduce latency, and enhance Docker build performance.

- **Infrastructure**: Optimize Dockerfiles using build mounts for pnpm cache and reorder layers for better caching of dependencies and build tools.
- **Backend/Gateway**:
  - Refactor `broadcast` module to use a generic event-based system instead of hardcoded functions.
  - Simplify voice recording logic by merging metadata and segment management into a unified `segment.ts`.
  - Optimize audio downsampling in `streamSetup.ts` using `Int16Array` views for better performance.
  - Implement `withFallback` utility for more robust Redis/Database command execution.
- **Frontend**:
  - Optimize audio playback visualization using pre-computed level shapes and efficient RMS calculation.
  - Reduce latency in voice commands by prioritizing WebSocket communication over HTTP.
  - Improve base64 encoding efficiency in audio transmission.
- **General**:
  - Add default value for `ADMIN_PASSWORD` in shared config.
  - Fix Docker healthcheck to use `127.0.0.1` instead of `localhost`.
2026-06-09 22:04:05 +07:00
MythEclipseandClaude Opus 4.8 655380dd8d fix: build @bete/shared before frontend in Dockerfile
TypeScript compilation in the frontend Docker build fails with TS2307:
Cannot find module '@bete/shared' because the shared package's .d.ts
files in dist/ were never generated. The backend and discord-gateway
Dockerfiles already have this build step — frontend was missing it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 20:35:35 +07:00
MythEclipseandClaude Opus 4.8 3fcc727187 fix(docker): add ffmpeg to discord-gateway for voice transmit
Voice transmitter requires FFmpeg to encode PCM to OggOpus.
Previously missing from Alpine image, causing:
  spawn ffmpeg ENOENT

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 22:31:16 +07:00
MythEclipseandClaude Opus 4.8 60edb4576f fix(docker): create recordings directory with proper permissions
- Add recordings directory structure with .gitkeep, .gitignore, and README
- Update deployment script to set chmod 777 on recordings directory
- Fixes ENOENT/EACCES errors when discord-gateway tries to create user subdirectories
- Ensures container app user (UID 100) can write recording files

This resolves the crash on voice channel connection where the service
failed to create user-specific recording directories like:
- recordings/<user-id>/
- recordings/sessions/

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:31:43 +07:00
MythEclipse 6f4053c1cc fix(docker): add build tools for native dependencies in discord-gateway
Install python3, make, g++, rust, and cargo in Alpine image to resolve:
- node-crc native build failure (requires cargo)
- @discordjs/opus native build issues (requires build tools)

This fixes the GitHub Actions build failure in the discord-gateway service.
2026-06-08 20:16:47 +07:00
MythEclipseandClaude Opus 4.8 <noreply@anthropic.com d036fbf568 opt(deploy): multi-stage frontend (node→nginx), non-root user, healthchecks, resource limits
Frontend:
- Multi-stage build: builder (node:22-alpine) → runner (nginx:alpine)
  replaces vite preview (400MB RAM) with nginx static serving (<20MB RAM)
- New nginx-frontend.conf with gzip + long-term asset cache + SPA fallback

Backend & Discord Gateway:
- Add non-root user (USER app) for container security
- chown app files to avoid permission issues
- Add HEALTHCHECK: backend via /api/health, gateway via kill -0 1

Docker Compose:
- Remove unnecessary backend→gateway depends_on
- Add deploy.resources.limits.memory for all services
- Add healthchecks for all services

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com
2026-06-08 17:51:29 +07:00
MythEclipseandClaude Opus 4.8 0f32c2a83a fix(docker): build @bete/shared before backend and discord-gateway
@bete/shared emits dist/ artifact; imports resolve via
package.json "main"/"exports" pointing to dist/. Both
services need the shared package built before `tsc` sees it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:38:07 +07:00
MythEclipseandClaude Opus 4.8 cd181698bc fix(docker): copy packages/shared workspace dependency into backend and discord-gateway containers
Both services import from @bete/shared but Dockerfiles were missing the
packages/shared/ copy step, causing tsc errors on build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:33:53 +07:00
MythEclipseandClaude Opus 4.8 88a1b59f02 fix(docker): copy patches directory for pnpm patchedDependencies
pnpm install --frozen-lockfile fails in Docker with ENOENT when
pnpm-lock.yaml references patched dependencies (jsdoc@3.6.11.patch)
but the patches/ directory is not copied into the container.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 23:31:12 +07:00
MythEclipseandClaude Opus 4.8 73efc716a5 fix(ci): use git-pull pattern like ZeaVis-Edu, all images from GHCR
- Replace build: blocks with image: from ghcr.io
- Simplify deploy: git clone/pull on VPS, then docker compose pull/up
- Remove SCP step entirely — nginx.conf baked into proxy image
- Rename containers to imphenbot-* to match existing VPS setup
- Fix backend port to 3000 for production

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:41:38 +07:00
MythEclipseandClaude Opus 4.8 8c4b32f5e1 fix(ci): correct nginx conf path in Dockerfile.proxy
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:26:47 +07:00
MythEclipseandClaude Opus 4.8 6010319486 fix(ci): rename Dockerfile.nginx to Dockerfile.proxy to match workflow matrix
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:09:52 +07:00
MythEclipseandClaude Opus 4.8 bf0d0090c9 fix(ci): use SCP to copy docker-compose and nginx from repo instead of hardcoded cat
- Add proxy to build matrix
- Replace heredoc docker-compose generation with appleboy/scp-action
- Fix nginx upstream backend port to 3000 (matches prod WEBSERVER_PORT)
- Copy docker-compose.yml and nginx.conf from repo via SCP staging

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:03:13 +07:00
MythEclipseandClaude Opus 4.8 cbe63809dd fix(infra): use ^~ prefix location for /api and /ws to match without trailing slash
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:51:57 +07:00
MythEclipseandClaude Opus 4.8 2b8d1ac703 feat(infra): replace traefik path routing with nginx reverse proxy
- Add nginx service with /api, /ws, and / location routing
- Move traefik labels to proxy service only (port 80)
- Remove traefik labels from backend and frontend services
- Backend routes to :3001 via nginx upstream
- WebSocket upgrade enabled for /ws path

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 08:36:34 +07:00
MythEclipseandClaude Opus 4.8 5a094c926a fix(frontend): pass VITE_BE_API_URL and VITE_BE_WS_URL as Docker build args
Vite embeds env vars at build time, not runtime. The frontend code uses
VITE_BE_API_URL/VITE_BE_WS_URL but the workflow was setting wrong names
(VITE_API_URL/VITE_WS_URL). Now Dockerfile accepts build args and
workflow passes production URLs during docker build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 23:31:20 +07:00
MythEclipseandClaude Opus 4.6 0f6cdff8ee fix(frontend): set preview port to 3000 to match traefik loadbalancer
Vite preview defaults to port 4173 but traefik routes to port 3000.
Added --port 3000 to the preview script in package.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 23:11:47 +07:00
MythEclipseandClaude Opus 4.6 e2c1197caf fix(discord-gateway): generate Drizzle migrations and copy to Docker image
Container crashed with 'Can't find meta/_journal.json file' because
Drizzle ORM migration files were never generated. Generated migrations
for all 10 schema tables and updated Dockerfile to copy drizzle/ to
/app/drizzle/ where the migrator expects them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:52:03 +07:00
MythEclipseandClaude Opus 4.6 3afa6298e3 refactor(monorepo): remove root package deps, simplify Dockerfiles
Root package.json no longer a workspace member — no src/, no 38 shared
dependencies. Root is now workspace config with dev tooling only (biome,
drizzle-kit, tsx, typescript).

This means Dockerfiles only need:
- pnpm-workspace.yaml + pnpm-lock.yaml + package.json (workspace config)
- The specific service being built
- Only vendor/ packages that service actually depends on (discord-gateway → discord.js-selfbot-v13)

Before: each Dockerfile copied src/, vendor/*, packages/*, all services/
After: each Dockerfile copies only its service + needed vendor deps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-01 22:47:47 +07:00