Skip to content

Variable Classification

REP classifies every environment variable into one of three security tiers based on its prefix. This is the foundational design decision — it forces an explicit security choice for every variable.

PrefixTierBehaviourSDK Access
REP_PUBLIC_*PUBLICPlaintext JSON in page sourcerep.get('KEY') (sync)
REP_SENSITIVE_*SENSITIVEAES-256-GCM encrypted blobawait rep.getSecure('KEY')
REP_SERVER_*SERVERNever sent to clientN/A
REP_GATEWAY_*(config)Gateway configuration, not app varsN/A

Variables without a REP_ prefix are ignored by the gateway entirely. This prevents accidental exposure of system variables like PATH, HOME, or database credentials.

  1. Classification is determined exclusively by prefix. There is no override mechanism.
  2. The gateway will not inject any variable without a REP_ prefix.
  3. Prefixes are stripped before injection: REP_PUBLIC_API_URL becomes API_URL in the payload.
  4. Names must be unique after stripping. If REP_PUBLIC_API_URL and REP_SENSITIVE_API_URL both exist, the gateway refuses to start.

Use this guide to classify each variable:

Does the value contain credentials, tokens, or keys?
├── Yes → Does it need to reach the browser at all?
│ ├── No → REP_SERVER_*
│ └── Yes → REP_SENSITIVE_*
└── No → Is it configuration the app needs at runtime?
├── Yes → REP_PUBLIC_*
└── No → REP_SERVER_* or don't use REP_ prefix
VariableWrong TierCorrect TierReason
DATABASE_URLPUBLICSERVERDatabase credentials must never reach the browser
STRIPE_SECRET_KEYSENSITIVESERVERSecret keys should never be decryptable client-side
STRIPE_PUBLISHABLE_KEYSERVERPUBLICPublishable keys are designed to be public
API_URLSENSITIVEPUBLICAPI endpoints are visible in network requests anyway
JWT_SECRETSENSITIVESERVERSigning secrets must stay server-side
OAUTH_CLIENT_IDSERVERSENSITIVEClient IDs are needed browser-side but not public
ANALYTICS_WRITE_KEYPUBLICSENSITIVEWrite keys allow data ingestion — encrypt them
FEATURE_FLAGSSENSITIVEPUBLICFeature flag names have no security value
SENTRY_DSNPUBLICSENSITIVEDSNs contain project-specific ingestion endpoints
APP_VERSIONSENSITIVEPUBLICVersion strings are informational, not secret
INTERNAL_SERVICE_TOKENSENSITIVESERVERService-to-service tokens must not reach the browser
CDN_BASE_URLSENSITIVEPUBLICCDN URLs are visible in every asset request

At startup, the gateway scans all REP_PUBLIC_* values for patterns indicating potential misclassification:

DetectionDescription
Shannon entropy > 4.5Random-looking strings typical of API keys and tokens
Known key formatsAWS keys (AKIA...), JWTs (eyJ...), GitHub tokens (ghp_...), Stripe keys (sk_live_...), private keys (-----BEGIN)
Length anomaliesStrings > 64 characters that may be encoded secrets

When a potential misclassification is detected:

  • The gateway logs a WARNING with the variable name (never the value)
  • In --strict mode, the gateway refuses to start
  • The gateway never silently changes classification — you must fix the prefix

When a .rep.yaml manifest is present, the gateway can validate at startup that:

  • All required variables are present in the environment
  • Variable values match declared types (url, number, enum, etc.)
  • Variables are in the correct tier

See the Manifest guide for details.