'up --force-recreate' after 'down' causes 'No such container' race.
After down, up creates fresh containers automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After removing root package deps, discord-gateway service was missing:
- axios (used in indonesianTextNormalizer.ts)
- ws (used in broadcaster.ts)
- @types/pg (needed for TypeScript pg declarations)
- @types/ws (needed for ws types)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
The VPS has orphan containers from previous deployments that conflict with
new compose up. Running compose down --remove-orphans first cleans them up.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pnpm install --frozen-lockfile at workspace root requires ALL workspace
members to be present. Previously vendor/ packages and root src/ were
missing, causing TS2307 'Cannot find module' errors during build.
- Copy vendor/ (discord.js-selfbot-v13, discord-video-stream, better-sqlite3, drizzle-orm)
- Copy root src/ and vite.backend.config.ts
- Copy all services/ to each Dockerfile
- Copy frontend/ and public/ assets to frontend Dockerfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root scripts point to old paths (src/, frontend/) that don't exist in the
services/ monorepo layout. Use pnpm --filter to invoke each service's
own build script (tsc) instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pnpm v10+ requires the built-in `node:sqlite` module which is only available
in Node 22+. All services now use node:22-alpine.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`github.repository_owner` returns 'MythEclipse' (mixed case) which GHCR rejects.
Hardcode lowercase 'mytheclipse' to match GHCR requirements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract services into services/{frontend,backend,discord-gateway}
- Create packages/shared/ for shared logger, errors, utils, types
- Setup Modular MVC pattern in backend (controller→service→repository)
- Setup event-driven architecture in discord-gateway with Redis pub/sub
- Move Docker files to infra/docker/ with per-service Dockerfiles
- Update docker-compose.yml to use Traefik-only routing (no port exposes)
- Update GitHub Actions deploy workflow for multi-service matrix build
- Fix all import paths and resolve type errors across all services
- All 3 services pass tsc --noEmit clean
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Count only flagged messages in the active users Flag column
- Coerce PostgreSQL count results to numbers before calculating violation_score
- Prevent string concatenation in flagged*3 + warned scoring
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
API provider returns 400 error for these params. Removed from all LLM calls
in llmModerationClient.ts and indonesianTextNormalizer.ts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove LOCAL_BADWORDS array (25 hardcoded words) and FALSE_POSITIVE_WHITELISTS
- Remove detectLocalBadwords function — all detection now goes through API pipeline
- Fix DEFERRAL_ANALYSIS_PATTERN: remove overly broad patterns (admin perlu, bisa berpotensi, maaf/sorry, saya tidak yakin)
- Expand DEFERRAL_EXCEPTION_PATTERN to catch more decisive-deferral variations
- Update tests to reflect API-only detection (local fallback removed)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add XML delimiters to prevent prompt injection (R1)
- Use JSON Schema response format instead of json_object (R2)
- Add concurrency limiter via p-limit (R3)
- Add timeout per media analysis call (R4)
- Resize images with sharp before vision API (R5)
- Split text batches when exceeding batch size limit (R6)
- Add few-shot examples to system prompt (R7)
- Modularize system prompt builder (R8)
- Enhance deferral detection regex with exception patterns (R9)
- Sanitize error messages to avoid leaking internals (R10)
New files: concurrencyLimiter.ts, imageResizer.ts, moderationPrompt.ts
Updated: llmModerationClient.ts, config.ts, package.json, tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Extract custom emoji metadata with Discord CDN URLs
- Download and send emoji images to vision model for moderation analysis
- Render custom emoji as inline images in dashboard instead of raw <:name:id> text
- Add emoji vision cache with deterministic keying by emoji ID
- Add custom emoji vision prompt for context-aware moderation
The NixOS base image lacks sed and coreutils in PATH. Native Node.js
post-install scripts (node-pre-gyp, prebuild-install) require sed and
other core utilities. Installing gnused and coreutils-full provides the
necessary binaries for native module compilation.
Also switched back to single nix profile install call (instead of
sequential per-RUN) since all packages now reference the same pinned
nixpkgs commit, eliminating version drift conflicts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The node-pre-gyp and prebuild-install wrapper scripts require sed, which
is not in PATH in the NixOS base container. Install coreutils first to
provide sed, dirname, basename, and other core utilities needed by
native module post-install scripts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pnpm's isolated store prevents native post-install scripts from finding
their dependency binaries (node-pre-gyp, prebuild-install). This causes
@discordjs/opus and @lng2004/node-datachannel to fail during pnpm install.
Enabling shamefully-hoist flattens node_modules so native scripts can
resolve their dependencies correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cacert 3.123 was installed first, but nodejs_22 pulls cacert 3.117 as a
transitive dependency, causing a file conflict on ca-bundle.crt.
Since all packages that need SSL certificates already pull cacert as a
dependency, installing it explicitly is redundant and causes conflicts.
Removing the explicit cacert install lets each package use its resolved
transitive cacert version.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues were causing Docker build failures:
1. Invalid nixpkgs commit hash (404 on GitHub archive)
2. Installing packages simultaneously caused version conflicts
(cacert 3.123 vs 3.117, git vs git-minimal)
Fix:
- Pin to valid nixos-unstable HEAD commit
- Install each package with sequential 'nix profile add' calls
so each package resolves dependencies before the next installs
- Remove explicit git (git-minimal pulled by yt-dlp is sufficient)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The nixos-unstable channel changes rapidly and causes file conflicts
between packages (cacert 3.123 vs 3.117, git vs git-minimal) because
different packages are resolved from different nixpkgs snapshots during
the same profile install.
Pinning to a specific commit ensures all packages are resolved from the
same nixpkgs snapshot, eliminating version drift and file conflicts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
yt-dlp already pulls git-minimal as a transitive dependency. Adding git
explicitly causes a file conflict on packinfo.pl. Removing git from the
install list resolves this since git-minimal provides all git functionality
needed for CI builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated .env.example to include Groq API configuration.
- Enhanced config schema in config.ts to support Groq API keys and settings.
- Implemented Groq moderation API call in indonesianTextNormalizer.ts as a fallback for badword detection.
- Removed the Indonesian slang normalization function and related tests to streamline moderation logic.
- Updated tests to reflect changes in moderation strategy, focusing on emoji normalization and badword detection.
fix(redis): enhance Redis connection handling with fallback to in-memory storage
chore(sql): create missing messages and attachments tables with necessary constraints and indexes
- Updated test files to use a separate test database configuration.
- Introduced a new helper module for managing test database operations.
- Added a setup file to configure the environment for tests.
- Created new database migration scripts to optimize message indexing.
- Added a sample environment file for test database configuration.