Moko Consulting 804b131ccb
Cascade Main -> Dev / Cascade main -> dev (push) Successful in 3s
Generic: Standards Compliance / Secret Scanning (push) Successful in 3s
Universal: Push Notifications / push-notify (push) Successful in 7s
Generic: Standards Compliance / License Header Validation (push) Successful in 3s
Generic: Standards Compliance / Repository Structure Validation (push) Failing after 5s
Generic: Standards Compliance / Coding Standards Check (push) Successful in 5s
Generic: Standards Compliance / Workflow Configuration Check (push) Failing after 4s
Generic: Standards Compliance / Documentation Quality Check (push) Failing after 3s
Generic: Standards Compliance / README Completeness Check (push) Failing after 3s
Deploy (Prod) / Deploy to Prod (push) Successful in 24s
Generic: Standards Compliance / Git Repository Hygiene (push) Successful in 4s
Generic: Standards Compliance / Line Length Check (push) Successful in 4s
Generic: Standards Compliance / Script Integrity Validation (push) Successful in 8s
Generic: Standards Compliance / File Naming Standards (push) Successful in 3s
Generic: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Generic: Standards Compliance / Version Consistency Check (push) Successful in 41s
Generic: Standards Compliance / Dead Code Detection (push) Successful in 5s
Generic: Standards Compliance / File Size Limits (push) Successful in 3s
Generic: Standards Compliance / Binary File Detection (push) Successful in 4s
Generic: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
Generic: Standards Compliance / Code Duplication Detection (push) Successful in 38s
Generic: Standards Compliance / Unused Dependencies Check (push) Successful in 37s
Generic: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 43s
Generic: Standards Compliance / Broken Link Detection (push) Successful in 3s
Generic: Standards Compliance / API Documentation Coverage (push) Successful in 3s
Generic: Standards Compliance / Accessibility Check (push) Successful in 3s
Generic: Standards Compliance / Performance Metrics (push) Successful in 3s
Generic: Standards Compliance / Enterprise Readiness Check (push) Successful in 40s
Generic: Standards Compliance / Repository Health Check (push) Successful in 39s
Generic: Standards Compliance / Terraform Configuration Validation (push) Successful in 7s
Generic: Standards Compliance / Code Complexity Analysis (push) Successful in 2m11s
Generic: Standards Compliance / Compliance Summary (push) Has been cancelled
feat(admin): access control — signup policy + multi-domain allow-list
Add an admin "Access" page to gate who can sign into the admin GUI via Google
OAuth. Replaces the single env-var domain check with GUI-managed policy:

- Signup mode (per-login decision): open (domain match auto-approves),
  approval (domain sign-ins queue as pending for admin approval), or
  allowlist/closed (only pre-approved emails).
- Multiple allowed domains (seeded once from MT_OAUTH_ALLOWED_DOMAIN).
- User allow-list: approve pending, add, block (kept so open-mode can't
  silently re-provision), remove. All actions audited.
- adminAuth re-validates the OAuth session against the store each request, so a
  block/removal revokes access immediately rather than at 12h cookie expiry.
  HTTP basic auth still bypasses (no lockout risk while tightening policy).

New store tables: settings (signup_mode, allowed_domains) + users. Blocked/
queued logins re-render the sign-in page with a status banner.

Tests cover domain matching (incl. suffix-spoof) and all three signup modes.

Authored-by: Moko Consulting
Claude-Session: https://claude.ai/code/session_015UauDPfYC8S2mdUhoSK8zQ
2026-07-22 08:53:41 -05:00

MokoTranslate

Go-based admin GUI + API gateway for a self-hosted LibreTranslate translation server.

LibreTranslate ships a great translation engine and REST API, but its only web surface is a translation playground — there is no admin GUI. API keys are managed with the ltmanage keys CLI against a SQLite database, rate limits are env vars, and metrics are a raw Prometheus endpoint. MokoTranslate fills that gap: it sits in front of a private LibreTranslate instance as the single public door and gives you a browser dashboard for keys, usage, and health.

client ──►  MokoTranslate  ──►  LibreTranslate
            :8080               :5000 (private, keys OFF)
            • API-key auth
            • per-key rate limits
            • per-key usage logging
            • admin dashboard
            • /healthz

Why a gateway (not a sidecar)

LibreTranslate does not record per-key usage, so an admin panel that merely reads its SQLite key DB could never show usage analytics. By making MokoTranslate the front door — it owns authentication and logs every request — the dashboard has real data, and the engine behind it becomes swappable (LibreTranslate today, something else later) without changing how clients authenticate.

Features

  • API-key management — issue, label, rate-limit, and disable keys from the web UI. Keys are shown once at creation and stored only as SHA-256 hashes.
  • Per-key usage — request counts, characters proxied, last-used, plus a recent-activity feed.
  • Per-key rate limiting — requests/minute, configurable per key (0 = unlimited).
  • Reverse proxy to the translation endpoints (/translate, /translate_file, /detect, /languages, /frontend/settings).
  • Translation playground (/admin/playground) — test translations from the browser; talks to the engine directly, no key needed.
  • Prometheus /metrics (admin-auth protected) — total + per-key request/char counters and engine reachability, for the monitoring stack.
  • Health endpoint (/healthz) for container/orchestrator probes.

Client usage

Clients authenticate to MokoTranslate with a bearer token (the issued mtk_… key):

curl -X POST https://translate.mokoconsulting.tech/translate \
  -H "Authorization: Bearer mtk_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"q":"Hello, world","source":"en","target":"es"}'

?api_key=mtk_… is also accepted for compatibility with LibreTranslate clients. /languages and /frontend/settings are open (no key) for capability discovery.

Configuration

All settings are environment variables (MT_*):

Variable Default Purpose
MT_LISTEN_ADDR :8080 Address to bind
MT_LIBRETRANSLATE_URL http://127.0.0.1:5000 Private upstream engine
MT_DATA_DIR /data Writable data directory
MT_STORE_PATH <MT_DATA_DIR>/mokotranslate.json JSON store location
MT_ADMIN_USER admin Admin basic-auth username
MT_ADMIN_PASSWORD (unset) Admin basic-auth password — required to use the admin UI (fail-closed if empty)
MT_PUBLIC_BASE_URL https://translate.mokoconsulting.tech Public URL shown in the UI
MT_DEFAULT_RATE_PER_MIN 60 Default per-key rate when a key sets none
MT_REQUIRE_KEY true Require an API key on translation endpoints

Run locally

cp .env.example .env      # then set MT_ADMIN_PASSWORD
docker compose up -d      # brings up LibreTranslate (private) + MokoTranslate
# admin UI: http://localhost:8080/admin/   (basic auth: admin / <MT_ADMIN_PASSWORD>)

First boot downloads all LibreTranslate language models (~1520 GB), so the engine's healthcheck has a long start period.

Architecture / layout

source/
  main.go              entry point, graceful shutdown
  config/              MT_* environment configuration
  store/               pure-stdlib JSON store (keys, usage, events)
  gateway/             reverse proxy to LibreTranslate
  httpapi/             HTTP server, admin handlers, gateway handler, middleware
    templates/         embedded server-rendered HTML

Storage

MokoTranslate v1 uses a pure standard-library JSON store (atomic temp-file + rename), so the module has zero third-party dependencies — no go.sum, a fully reproducible CGO_ENABLED=0 static binary, and a tiny image. It keeps per-key aggregate usage plus a bounded ring of recent events. If you later need historical time-series (usage-over-time charts, retention), the documented upgrade path is to swap store for SQLite behind the same interface.

Rate limiting

The per-key limiter lives in source/httpapi/middleware.go. Its Allow() method is intentionally a stub (allow-all) so you can choose the strategy — sliding window log, fixed window, or token bucket — that best fits your traffic. See the TODO(you) in that file.

Deployment

Production runs on the beelink as a .vault Docker stack at translate.mokoconsulting.tech, deployed through the restricted per-repo deploy pattern (deploy-mokotranslatemokocli → server-side deployer). The .mokogit/workflows/deploy-{dev,rc,prod}.yml thin triggers are synced from Template-Go.

License

GPL-3.0-or-later. See LICENSE. Copyright © 2026 Moko Consulting.

S
Description
Go-based admin GUI + API gateway for a self-hosted LibreTranslate translation server (key management, usage analytics, health, per-key rate limits).
Readme
756 KiB
Languages
CSS 38.5%
Go 37.2%
HTML 15.5%
Markdown 8.2%
Dockerfile 0.6%