Skip to main content
This page documents secret names and configuration boundaries. It does not contain secret values.

General Rules

  • Store hosted deployment credentials in environment-scoped GitHub Actions secrets.
  • Store Vercel app runtime and build-time configuration in the Vercel project environment, not workflow-wide GitHub Actions environment variables.
  • Store local web runtime configuration in apps/web/.env.local.
  • Do not commit tokens, keys, passwords, or rendered env dumps.
  • Do not edit checked-in compose files to inject per-environment secrets.

Local And Self-Hosted Web

GitHub Actions Secrets By Area

Vercel-hosted web apps

Vercel workflows use GitHub Environments named vercel-preview-<app> and vercel-production-<app>. Keep the deployment secrets on those environments, not as workflow-level env: entries. Production environments should require reviewers and restrict deployment branches to production; preview environments should require review whenever branch pushes can run repository-controlled code with deployment credentials.
  • VERCEL_TOKEN
  • VERCEL_ORG_ID
  • App-specific VERCEL_PROJECT_ID values such as VERCEL_PLATFORM_PROJECT_ID and VERCEL_APPS_PROJECT_ID
  • Infrastructure deployments use VERCEL_INFRASTRUCTURE_PROJECT_ID in the vercel-preview-infrastructure and vercel-production-infrastructure GitHub Environments
  • QR deployments use VERCEL_QR_PROJECT_ID in the vercel-preview-qr and vercel-production-qr GitHub Environments

Turborepo remote cache

Remote-cache identity is repository-wide rather than app runtime configuration:
  • Store a dedicated, least-privilege Vercel team cache token as the repository secret TURBO_TOKEN. Rotate it independently from deployment tokens and revoke the previous token after trusted canaries pass.
  • Store the Vercel team slug as the repository variable TURBO_TEAM. Workflows temporarily accept secrets.TURBO_TEAM as a migration fallback; remove that secret after the variable is confirmed.
  • Leave TURBO_API unset for Vercel-managed remote caching.
  • Do not configure TURBO_REMOTE_CACHE_SIGNATURE_KEY until artifact signing is deliberately enabled and rolled out.
  • Optional repository variables ACTIONS_CACHE_NOTICE_PERCENT, ACTIONS_CACHE_WARNING_PERCENT, and ACTIONS_CACHE_CRITICAL_PERCENT override the weekly report’s 80/90/100 thresholds. Cache size and retention are not variables; the report discovers both from GitHub’s repository API.
Only pass these values as inputs to .github/actions/run-with-turbo-remote-cache/action.yml. The action places them on the wrapped command step, not the workflow, job, GITHUB_ENV, image layer, or deployment artifact. Never pass TURBO_TOKEN to pull-request or Dependabot jobs; secretless jobs use the task-family GitHub cache fallback.

Production and preview app configuration

These values belong in the Vercel project environment for each app and target. Do not export them from GitHub Actions workflows. The Vercel deploy workflows run repository code during install and build, so workflow-wide production runtime secrets are a supply-chain exposure path.
  • PRODUCTION_SUPABASE_URL
  • PRODUCTION_SUPABASE_PUBLISHABLE_KEY
  • PRODUCTION_SUPABASE_SECRET_KEY
  • ENCRYPTION_MASTER_KEY
Turborepo cache identity is the repository-level configuration described above, not a Vercel app runtime secret. Do not duplicate it into every project’s runtime environment. Individual workflows may also consume other application-specific secrets depending on the deployed app.

Integration-specific runtime secrets

  • SePay OAuth requires SEPAY_OAUTH_CLIENT_ID, SEPAY_OAUTH_CLIENT_SECRET, SEPAY_OAUTH_TOKEN_ENCRYPTION_SECRET, and a webhook auth secret such as SEPAY_WEBHOOK_API_KEY.
  • SePay web runtimes also require an app origin through WEB_APP_URL, NEXT_PUBLIC_WEB_APP_URL, or NEXT_PUBLIC_APP_URL so OAuth callbacks and webhook provisioning can generate stable platform URLs.
  • SePay workspace enablement is controlled by the workspace secret ENABLE_SEPAY_INTEGRATION=true.
  • SePay runtime overrides may optionally set SEPAY_OAUTH_AUTHORIZE_URL, SEPAY_OAUTH_BASE_URL, and SEPAY_API_BASE_URL when targeting non-default environments.
  • SePay OAuth state is stored in a short-lived HttpOnly callback cookie and is HMAC-signed. The signer uses SEPAY_OAUTH_STATE_SECRET when set; otherwise it falls back to the required SEPAY_OAUTH_CLIENT_SECRET.
  • Polar (inventory storefront checkout + workspace subscriptions) requires POLAR_ACCESS_TOKEN (platform-level org token) and POLAR_WEBHOOK_SECRET (webhook signature verification) on apps/pay. Set POLAR_SANDBOX=true to target Polar’s sandbox, and the optional POLAR_CURRENCIES to allowlist storefront currencies. Configure Polar to deliver webhooks to https://pay.tuturuuu.com/api/payment/webhooks; apps/web no longer owns payment API or webhook routes. See the Polar storefront integration runbook for details.
  • Square Terminal (Inventory + Storefront pay-at-terminal checkout) stores Square application credentials, OAuth/manual tokens, webhook signature keys, locations, terminal ids, and webhook notification URL overrides encrypted from Inventory settings. Do not configure Square credentials as deployment secrets. See the Square Terminal integration runbook for the complete setup and smoke checklist.

Supabase migrations

  • SUPABASE_ACCESS_TOKEN
  • STAGING_DB_PASSWORD
  • STAGING_PROJECT_ID
  • STAGING_DB_URL
  • PRODUCTION_DB_PASSWORD
  • PRODUCTION_PROJECT_ID
  • PRODUCTION_DB_URL
  • MODAL_TOKEN_ID
  • MODAL_TOKEN_SECRET
  • MODAL_ENVIRONMENT as a GitHub Actions variable

Mobile store beta deployment

mobile-deploy-stores.yaml uses the mobile-store-beta GitHub Environment and runs only from production pushes that touch apps/mobile/**, scripts/mobile-deployment/**, the workflow file, ci-check.yml, or tuturuuu.ts. Keep this environment branch-restricted to production. GitHub Environment secrets:
  • MOBILE_DEPLOYMENT_CI_TOKEN: issued from the root workspace mobile deployment vault and scoped to production mobile deployment.
If MOBILE_DEPLOYMENT_CI_TOKEN is not set yet, the mobile store workflow’s credentials preflight emits a notice and skips the Android and iOS publish jobs. Set the secret when the deployment vault is ready; invalid non-empty tokens still fail during bundle fetch so real misconfiguration remains visible. No Firebase, signing, store API, or mobile build secret values should be stored in GitHub Environment secrets or variables. Those resources live in the apps/infrastructure mobile deployment vault at /internal/mobile-deployment, which is root-workspace-only and requires manage_mobile_deployment_vault. apps/web deployment requirements:
  • ENCRYPTION_MASTER_KEY: required before uploads, activation, and CI bundle fetches can decrypt the per-version deployment data key.
  • Root workspace Drive/R2/Supabase storage must be available. File resources are stored as encrypted ciphertext blobs under the reserved .tuturuuu/mobile-deployment-vault prefix; normal Drive routes deny that prefix.
Vault resources required before activation:
  • Manage all non-file values in the vault’s Secrets panel. Build-time secrets are rendered into apps/mobile/.env.github during CI; built-in signing and store secrets are exported separately for the Android and iOS release steps. The expected production build-time keys are NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, API_BASE_URL, TURNSTILE_SITE_KEY, TURNSTILE_BASE_URL, GOOGLE_WEB_CLIENT_ID, GOOGLE_IOS_CLIENT_ID, MOBILE_TASK_DESCRIPTION_EDITING_ENABLED, and MOBILE_CALENDAR_INTEGRATIONS_ENABLED. Custom secrets are allowed when they use uppercase A-Z0-9_ names, do not collide with built-in secret names, and have single-line UTF-8 values.
  • CI file payload keys such as MOBILE_ANDROID_GOOGLE_SERVICES_JSON_B64 and MOBILE_IOS_GOOGLE_SERVICE_INFO_PLIST_B64 are rejected as secrets; upload those payloads through the file resources below.
  • Android files: production google-services.json, upload keystore, and Google Play service-account JSON.
  • Built-in Android secrets: ANDROID_KEYSTORE_ALIAS, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD, GOOGLE_PLAY_PACKAGE_NAME=com.tuturuuu.app.mobile, and GOOGLE_PLAY_TRACK=internal.
  • iOS files: production GoogleService-Info.plist, Apple distribution .p12, App Store provisioning profile, and App Store Connect .p8 private key.
  • Built-in iOS secrets: APPLE_BUNDLE_ID=com.tuturuuu.app.mobile, APPLE_DISTRIBUTION_CERTIFICATE_PASSWORD, APPLE_TEAM_ID, APP_STORE_CONNECT_API_KEY_ID, and APP_STORE_CONNECT_ISSUER_ID.
After every resource is uploaded, activate the ready draft version and issue a CI token. Store only that token in the mobile-store-beta GitHub Environment as MOBILE_DEPLOYMENT_CI_TOKEN.

Package publishing

Package publishing uses npm trusted publishing (GitHub OIDC), so no NPM_TOKEN secret is stored. The publish-npm job in each release-*-package.yaml workflow requests id-token: write, downloads the prepared tarball, and runs npm publish while npm exchanges the OIDC token for a short-lived publish credential.
  • Each publish job is bound to a per-package GitHub Environment (ui-release-production for @tuturuuu/ui, types-release-production for @tuturuuu/types), and the matching npm trusted publisher must reference this repository, the exact workflow filename, and that environment.
  • No npm registry token (NPM_TOKEN or NODE_AUTH_TOKEN) is set on these environments. Adding one would be unnecessary and would weaken the build-vs-publish job split.
See the trusted-publishing details in the GitHub Actions runbook.

Docker-Specific Notes

  • The Docker web helper auto-generates a stable local Redis token and injects UPSTASH_REDIS_REST_TOKEN, UPSTASH_REDIS_REST_URL, and the matching internal SRH_TOKEN value for the bundled serverless-redis-http container.
  • Watcher-managed Infrastructure projects do not inherit the integrated Docker Redis runtime. They start with Redis disabled, strip generic UPSTASH_REDIS_REST_* and Docker-specific DOCKER_UPSTASH_* values, and receive Redis only from project-scoped MANAGED_PROJECT_<PROJECT_ID>_UPSTASH_REDIS_REST_URL and MANAGED_PROJECT_<PROJECT_ID>_UPSTASH_REDIS_REST_TOKEN variables.
  • SRH_TOKEN is the container’s internal environment variable. The user-facing override surface is UPSTASH_REDIS_REST_TOKEN if you intentionally replace the helper-generated value.
  • The local dev compose file keeps a dev-only fallback token for direct local use, but production Redis compose requires UPSTASH_REDIS_REST_TOKEN during Compose interpolation. Use the Docker web helper or export a strong token before enabling the production redis profile directly.
  • Redis and serverless-redis-http host ports must stay loopback-bound. Do not publish those sidecars on all host interfaces or through Cloudflare Tunnel.
  • apps/web uses Redis for defense-in-depth one-time state such as CLI refresh-token replay protection. If UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are unavailable, CLI refresh requests continue after JWT validation and user lookup, while confirmed Redis-backed replays are still rejected.
  • docker compose config expands env values; treat its output as sensitive.

Supabase RPC Authorization Hardening

  • Treat every new SECURITY DEFINER function in public as externally callable until proven otherwise.
  • In the same migration that creates or replaces the function, enforce both:
    1. in-function authorization checks (auth.uid() plus workspace membership/permission gate), and
    2. explicit execute privileges (revoke all ... from public, then grant only required roles such as authenticated/service_role).
  • Do not rely only on apps/web page or API RBAC checks for tenant isolation when an RPC is exposed through the Data API.
  • During review, grep the migration for security definer, auth.uid(), has_workspace_permission, revoke, and grant execute before merge.

Change Management

When a new deployment flow is added:
  1. Add its secret names here.
  2. Add the workflow or runtime page to the relevant devops doc.
  3. Keep the boundary clear between repo config, GitHub Actions config, and machine-local config.