Skip to main content

Configuration

Certichain is configured only through environment variables. example.env in the repository root lists the names with empty values; real values live in .env or .env.local on a laptop (gitignored) and in the Vercel project settings for the hosted site. This page never shows a value.

Rules that apply to every variable​

  • Public or server only. A name starting with NEXT_PUBLIC_ is copied into the browser bundle at build time and is visible to every visitor. Anything else stays on the server. A secret must never get a NEXT_PUBLIC_ name.
  • Build time. NEXT_PUBLIC_ values are inlined when the app is built (src/lib/chain.ts reads them by literal name for that reason), so changing one needs a rebuild, not only a restart.
  • Features are off until configured. A server feature whose required settings are missing answers as switched off (usually 503 or CONFIG_MISSING) instead of failing the build. A malformed optional setting is an error that names the setting, never its value.
  • Sensitive in Vercel. Keys, tokens and secrets are stored as Sensitive variables. The agent rules of the project forbid reading .env files at all.

Chain and contracts (public)​

VariableRead byDefaultMeaning
NEXT_PUBLIC_NETWORK_IDsrc/lib/chain.ts, src/services/contracts/address-book.ts, and the config readers of sign-in, the API, status lists and the monitornoneChain id the build serves (11155111 Sepolia, 31337 local). Picks the deployment manifest. Required by every chain feature
NEXT_PUBLIC_CONTRACT_VERSIONsrc/lib/contract-version.tsv02Exactly v03 selects the v0.3 contract sets from the manifest; any other value or none selects the legacy v0.2 contract
NEXT_PUBLIC_CONTRACT_ADDRESSsrc/lib/chain.ts, src/services/contracts/address-book.ts, src/lib/server/config.tsnoneThe v0.2 AcademicRecords address. Required for v0.2 sign-in; unused on v0.3
NEXT_PUBLIC_START_BLOCKsrc/services/contracts/address-book.ts, src/services/domain/sharing-service.tsnoneBlock of the v0.2 deployment, where v0.2 share history scans start. v0.3 sets carry their own deploymentBlock in the manifest

Chain reads (RPC)​

VariablePublicRead byMeaning
NEXT_PUBLIC_RPC_URLSyessrc/lib/rpc/env.ts, browser gatewaysComma-separated endpoints for the browser, tried in order. Visible to visitors: use only keys you accept being public, restricted by domain at the provider
NEXT_PUBLIC_RPC_URLyessameSingle endpoint, tried last
RPC_URLSnosrc/lib/rpc/env.ts (serverRpcUrls)Server endpoints, in order. May carry provider keys
RPC_URLnosameServer last resort, and the older single setting

The server uses RPC_URLS, or NEXT_PUBLIC_RPC_URLS when that is empty, followed by RPC_URL or NEXT_PUBLIC_RPC_URL. Each endpoint gets 8 seconds; a failed one is skipped for 30 seconds. A list containing an address that is not http or https switches off the feature that needs it. Details: Reading the chain.

Issuer sign-in and sessions (server)​

VariableRead byMeaning
SESSION_SECRETsrc/lib/server/config.ts (readAuthConfig)Signs issuer sessions. At least 32 characters, or sign-in is off. Changing it signs everyone out
SIWE_ALLOWED_DOMAINSsameComma-separated domains a Sign-In with Ethereum message may name. Required in production (NODE_ENV=production), optional in development

Sign-in also needs NEXT_PUBLIC_NETWORK_ID, a server RPC endpoint and, on v0.2, NEXT_PUBLIC_CONTRACT_ADDRESS. Sign-in protects the upload and document routes; see Sign-in and sessions.

Shared store (server)​

VariableRead byMeaning
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKENsrc/lib/server/config.ts (readStoreConfig), src/lib/server/rate-limit.tsUpstash Redis for rate limits, used nonces, monitor state and history, and the pin ledger. KV_REST_API_URL and KV_REST_API_TOKEN are accepted as fallbacks

Without them, development keeps everything in the memory of one server process. In production getStore returns nothing and the routes that need a shared store answer CONFIG_MISSING; the verification API accepts per-instance counters only with API_ALLOW_LOCAL_LIMITS=true.

Documents and pinning​

VariablePublicRead byMeaning
PINATA_JWTnosrc/lib/server/config.ts (readPinataCredentials)Pinata token for uploads. Preferred. Needs file read and write access for key replacement and removal of old copies
PINATA_API_KEY, PINATA_API_SECRET_KEYnosameOlder key pair, used only when PINATA_JWT is empty
NEXT_PUBLIC_PINATA_GATEWAY_URLyessrc/lib/pinata.ts, src/services/react/browser-services.ts, src/lib/server/pinning/providers.tsGateway host the browser fetches containers from, and the first gateway the monitor reads pins back from
SECOND_PIN_PROVIDERnosrc/lib/server/pinning/providers.tsName of a second pin service adapter. Empty keeps one pin. The adapter table is empty as of 2026-10-24, so any name is a configuration error
PIN_READ_GATEWAYSnosameExtra gateways the monitor reads pins from, comma separated

PINATA_JWT_SECRET_ACCESS_TOKEN and PINATA_GATEWAY_ACCESS_KEY are listed in example.env but no code reads them. See Upload and documents.

Status lists​

VariablePublicRead byMeaning
STATUS_LIST_SIGNER_KEYnosrc/lib/server/status-lists/config.ts, src/lib/server/ops/wiring.tsPrivate key (0x and 64 hex characters) of a funds-free publisher that signs the lists
NEXT_PUBLIC_STATUS_LIST_BASE_URLyesstatus list config, src/services/index.tsSite address the list URLs in exported VCs point to
NEXT_PUBLIC_STATUS_LIST_PUBLISHERyessrc/lib/server/status-lists/wiring.ts, src/services/index.ts, monitorThe publisher's address that checkers pin
STATUS_LIST_CACHE_SECONDSnostatus list configServer cache, 0 to 300 seconds, default 300

The feature is on only with the signer key, the base address, a chain id and an RPC endpoint. See Status lists.

Verification API​

VariablePublicRead byMeaning
API_SIGNER_KEYnosrc/lib/server/api/config.ts, wiring.ts, monitorFunds-free key that signs every answer. Without it the API answers 503
NEXT_PUBLIC_API_SIGNERyesAPI wiring, monitor and probeIts address, which clients and the SDK pin
API_KEYSnosrc/lib/server/api/config.tsJSON list of { "id", "sha256", "tier" }, hashes only (make entries with npm run api:key -- <id>). Ids 1 to 40 lowercase letters, digits and hyphens; no repeats
API_CACHE_SECONDSnosameServer cache, 0 to 60, default 15
API_ALLOW_LOCAL_LIMITSnosrc/lib/server/api/instance.tstrue lets production run without the shared store, with per-instance limits (single-host setups)

See Verification API.

Monitor and reports​

VariableRead byDefaultMeaning
CRON_SECRETsrc/lib/server/ops/config.ts, instance.ts, slo/report-instance.tsnoneBearer secret for /api/ops/check and /api/ops/report, at least 32 characters. Without it the monitor is off
OPS_WEBHOOK_URLsamenonehttps incoming webhook for alerts and the monthly report
OPS_MAX_LAG_BLOCKSops config20An endpoint further behind warns
OPS_LOOKBACK_BLOCKSops config600, at most 50,000Window for administrative events; keep it longer than the schedule interval
OPS_WARN_DAYSops config14Days before a key expiry to warn
OPS_KEY_EXPIRIESops config, checks/key-expiry.tsnoneJSON object of names to YYYY-MM-DD dates
OPS_PROBE_API_URLops confignoneBase address of the verification API the canary probe calls (https, or http on loopback)
OPS_PROBE_CANARY_IDops confignoneCredential id of the canary (0x and 64 hex)
OPS_PROBE_API_KEYops confignoneOptional API key for the probe, 43 to 128 characters

The probe needs OPS_PROBE_API_URL, OPS_PROBE_CANARY_ID and NEXT_PUBLIC_API_SIGNER together. See Monitoring.

Build and runtime​

VariableRead byMeaning
NODE_ENVNext.js, src/lib/server/config.tsproduction makes SIWE_ALLOWED_DOMAINS and the shared store required
NEXT_DIST_DIRnext.config.tsBuild folder, default .next; the E2E harness uses .next-e2e

Contract scripts (blockchain/)​

blockchain/hardhat.config.ts loads the root .env (../.env). None of these are read by the app.

VariableUsed byMeaning
PRIVATE_KEYSepolia deploys and admin scripts, the access toolDeployer key. Testnet only; retired after the admin handover
INFURA_API_KEYSepolia network URLRequired with PRIVATE_KEY for any Sepolia script
ETHERSCAN_API_KEYverify* scriptsContract verification on the explorer
GUARDIAN_ADDRESS, ADMIN_DELAY_SECdeploy:v03:*Guardian of a new issuer registry; admin transfer delay (default 3 days)
ADD_SET, SET_LABEL, ISSUER_REGISTRY, ACTIVATE_SETdeploy:v03:*Add a set beside the others, its label, share an issuer registry, make it active
ADMIN_MULTISIGhandover, timelock and governance scriptsThe Safe's address
TIMELOCK_DELAY_SECdeploy:timelock:sepolia, governance checksThe timelock delay to deploy with or expect
SETverify, timelock, readiness and activation scriptsLabel of the set the command is about
TARGET, FUNCTION, ARGS, DELAY_SEC, SALT, SIGNOFF_FILE, LABELtimelock:propose:sepoliaThe call to schedule, its delay and salt, and the batch file label
INSTITUTION, SIGNOFF_FILE, FROM_BLOCKadmission:check:sepoliaWhich admission to look for, and from which block
ISSUERSissuers:v03:*0xAddr=Name;0xAddr=Name
SMOKE_WRITE, SMOKE_STUDENT_ADDRESS, SMOKE_UNIVERSITY_NAMEsmoke:sepolia (v0.2)Optional write checks
ACCESS_SUBMIT_KEYaccess submitKey of the account a proof was made for
INVARIANT_RUNS, INVARIANT_ACTIONS, INVARIANT_SEEDinvariantsSize of a run, or a seed to reproduce one
REPORT_GAS, REPORT_GAS_FILE, GAS_SNAPSHOT_WRITE, CIgas, gas:snapshotGas reporter output; snapshot writing, refused when CI is set

Source files​

  • example.env
  • src/lib/chain.ts, src/lib/contract-version.ts, src/lib/rpc/env.ts, src/lib/pinata.ts
  • src/lib/server/config.ts, src/lib/server/rate-limit.ts, src/lib/server/pinning/providers.ts
  • src/lib/server/status-lists/config.ts, src/lib/server/api/config.ts, src/lib/server/api/instance.ts, src/lib/server/ops/config.ts
  • next.config.ts, blockchain/hardhat.config.ts, blockchain/scripts/lib/network-env.ts, blockchain/scripts/lib/deploy-v03.ts, blockchain/scripts/lib/record-deployment.ts
  • Handbook: docs/process/runbooks/keys.md (the key inventory)

Tests​

  • src/lib/server/config.test.ts, src/lib/rpc/env.test.ts, src/lib/contract-version.test.ts
  • src/lib/server/status-lists/config.test.ts, src/lib/server/api/config.test.ts, src/lib/server/ops/config.test.ts
  • blockchain/test/v03/RecordDeployment.test.ts, blockchain/test/v03/Deploy.test.ts