Skip to content

open-chat-labs/translation_proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenChat translation proxy

A small AWS Lambda that sits between the OpenChat frontend and the Google Translate API. It exists so that:

  • the Google API key never ships in the client bundle
  • access is enforced server-side via an OpenChat-issued JWT (diamond members and platform moderators only)
  • translations are cached, so repeated text is only ever paid for once
  • usage is rate-limited per user with a global daily spend kill switch

API

POST /translate
Headers:
  x-auth-jwt: <JWT issued by the OpenChat local_user_index access_token_v2 endpoint,
               claim_type "Translate", ES256, claims { user_id, exp }>
Body:
  { "texts": ["Bonjour", ...], "target": "en" }   # 1-128 texts, <= 20k chars total

200 -> { "translations": ["Hello", ...] }         # same order as texts
400 -> invalid body / target locale
401 -> missing/invalid/expired token (client should refetch its token and retry once)
413 -> request too large
429 -> per-user rate limit hit
502 -> Google call failed
503 -> global daily budget exhausted

How it works

  • Auth: verifies the ES256 signature against the OpenChat public key (mirrors the jwt library in the open-chat repo), checks claim_type and expiry. The user_id claim keys the rate limits.
  • Cache: DynamoDB, keyed on sha256(target, text) — content-addressed, so edited/deleted messages need no invalidation and identical text dedupes globally. Entries expire after 30 days via DynamoDB TTL.
  • Rate limits (DynamoDB atomic counters, all configurable via template parameters):
    • per-user requests/minute (default 30)
    • per-user translated chars/day, cache misses only (default 100k)
    • global chars/day kill switch (default 2.5M ≈ $50/day at Google's $20/M)

Deploy

Prerequisites: sam CLI, cargo-lambda, an AWS profile.

  1. Store the Google API key (restrict it to the Cloud Translation API in the Google console first):

    aws ssm put-parameter \
      --name /openchat/translation-proxy/google-api-key \
      --type SecureString \
      --value <the-key>
    
  2. Get the OpenChat public key from the user_index canister metrics (oc_public_key).

  3. Build and deploy:

    sam build
    sam deploy --guided   # first time; pass OcPublicKeyPem when prompted
    

    Gotcha: when passing the PEM via --parameter-overrides, sam splits on whitespace even inside a shell-quoted string, silently truncating the value at the first space. Wrap the value in embedded double quotes and escape the newlines:

    sam deploy ... --parameter-overrides 'OcPublicKeyPem="-----BEGIN PUBLIC KEY-----\nMFkw...\n-----END PUBLIC KEY-----"'
    

    To test against a local OpenChat replica, deploy with the local user_index's oc_public_key instead, then restore the mainnet key afterwards (same command, different PEM).

  4. The stack outputs FunctionUrl — set OC_TRANSLATE_PROXY_URL to it in the OpenChat frontend .env (and the GH_TRANSLATE_PROXY_URL secret for the android release workflow).

Notes

  • The Lambda has no fixed egress IP, so the Google key can't be IP-restricted without adding a VPC + NAT gateway. API-restricting the key (Cloud Translation only) plus the rate limits above is the v1 posture; revisit if the key ever leaks.
  • Old Google API keys baked into previously shipped OpenChat client bundles must be revoked once this proxy is live.
  • There is no per-IP pre-auth rate limit in the Lambda itself (an invocation has already happened by the time we could check). If unauthenticated junk traffic ever becomes a cost problem, put AWS WAF or CloudFront in front of the function URL.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages