Skip to main content

Rule

Everything available to a public client build is public. Flutter Envied values, generated Dart, mobile artifacts, desktop app bundles, and release resources must never contain server-only secrets. obfuscate: true is not a security boundary. It only changes how a value is represented in generated code; users can still extract values from shipped apps.

Config Classes

ClassShips in public clients?ExamplesHandling
Public client configYesAPI base URL, non-sensitive flagsUse PUBLIC_ names and allowlist in app/config/client_env_policy.yaml.
Restricted public client keyYes, intentionallyGoogle Maps SDK key, public analytics ingestion keyAllowlist with owner, purpose, restrictions, and revocation path. Restrict at the vendor by bundle/package/API where possible.
Server-only secretNoOpenAI, Gemini, Anthropic, Deepgram, OAuth client secrets, service accounts, admin keysKeep in backend secret managers or server runtime only. Never expose to app env or artifacts.
Build or publish secretNoKeystores, provisioning credentials, App Store/Play publishing credentialsUse only in signing/publishing steps. Never copy into app resources.

Adding App Config

  1. Add the variable to app/config/client_env_policy.yaml.
  2. Add a placeholder to app/.client.env.example.
  3. Add it to scripts/create-public-client-env.sh.
  4. Add the value to the Codemagic environment group consumed by the app release workflows (currently app_env, unless the workflows import a dedicated public config group).
  5. Run:
python3 scripts/check-public-client-secrets.py
If the value can read private data, call a paid/provider API, bypass quotas, mint tokens, impersonate users, administer a vendor account, or access backend resources, it is not public client config.

Release Checks

Public release workflows must run both checks:
python3 scripts/check-public-client-secrets.py
python3 scripts/scan-public-artifact-secrets.py <artifact>
The first check validates source, policy, generated env inputs, and release workflow patterns. The second check extracts public artifacts and fails if server-only variable names, current CI secret values, service-account files, private keys, or signing material appear in the artifact.

Provider APIs

Public clients must not use Omi-owned provider credentials directly. Features that need OpenAI, Gemini, Anthropic, Deepgram, or similar providers should use:
public client -> Omi backend with user auth -> internal provider gateway -> vendor
BYOK flows require backend-owned secret storage. The app may collect a user key only for one-time authenticated submission, then local state should contain only a backend secret reference or configuration id. Legacy mobile custom-STT BYOK files are listed explicitly in legacy_direct_provider_domain_exceptions inside app/config/client_env_policy.yaml. Do not add to that list for new work. New provider integrations must use backend-owned BYOK storage and a provider proxy.