Skip to content

Configuration And Secrets

Configuration changes are cross-cutting. A single value can touch app env parsing, Docker builds, GitHub Actions, Pulumi outputs, runtime parameter stores, smoke tests, and operator runbooks.

Use this page when adding, renaming, removing, or changing the meaning of:

  • App environment variables.
  • Frontend build arguments.
  • Backend runtime settings.
  • i18n runtime or build settings.
  • GitHub Actions variables or secrets.
  • Pulumi config keys, Pulumi secret config keys, Pulumi outputs, or deployment contract fields.
  • SSM runtime parameter references.
  • CI, Playwright, smoke, or local .env values.

Environment names are allowed to appear in more than one place only when each place enforces a different boundary.

Good duplication:

  • App env schemas prove the process can parse the value it consumes.
  • .env.example files teach local developers what they need to provide.
  • Workflow manifests describe which values GitHub owns and which values GitHub must not own.
  • Deployment contracts describe sanitized cloud facts that routine deployment code can consume without direct Pulumi access or guessing provider resources.
  • Deployed-dev validators catch drift before AWS, SSM, Docker, or runtime hosts are involved.
  • Runtime parameter inventories describe the operator-facing names and value kinds.

Bad duplication:

  • Mirroring Pulumi outputs into GitHub environment variables because it is convenient.
  • Adding a runtime secret to GitHub when the host should read it from SSM.
  • Adding NEXT_PUBLIC_* values to runtime SSM parameters even though they are browser-bundled build inputs.
  • Repeating a value in docs without a validator, parser, fixture, or operational checklist that keeps it honest.

Docs explain the contract. Code-owned schemas, manifests, fixtures, scripts, Pulumi outputs, deployment contracts, and validators enforce it.

Before editing files, answer these questions:

  • Who consumes it: frontend browser, frontend server, backend, i18n package, deploy workflow, Pulumi, runtime host, tests, smoke checks, or an operator?
  • When is it needed: build time, runtime, deploy time, preview time, test time, or local development only?
  • How visible is it: public, restricted public, non-secret internal config, or secret?
  • Who owns the source of truth: repo default, .env file, GitHub environment, Pulumi config, deployment contract, SSM runtime parameter, CI setup, or operator action?
  • What should fail if it is missing: local boot, image build, preflight, deploy contract, runtime render, smoke, or a live cloud validation step?

If those answers are fuzzy, document the intended boundary before wiring the value into code.

SourceUse ForDo Not Use For
App env schemasValues the running process actually reads.Cloud resource discovery or workflow governance.
.env.example / .env.sharedLocal development discoverability and safe defaults.Real secrets or deployed cloud facts.
GitHub environment variablesDeploy bootstrap and governance values.App runtime config, cloud facts, Pulumi outputs, or repo-derived defaults.
GitHub environment secretsDeploy credentials or tokens GitHub itself must use.App runtime secrets that should stay at the runtime host boundary.
Pulumi stack configStack choices and infrastructure-owned config.App values that should vary through runtime parameters.
Pulumi secret configInfrastructure-owned secrets or restricted public provider config.Plain app runtime secrets that do not belong in infrastructure state.
Pulumi state backend profileInfra-operator state storage, locks, history, backups, and passphrase.Routine app/docs CD inputs or deployment contract artifact storage.
Pulumi outputsInfra-operator source facts that can be projected into deploy contracts.Routine app/docs CD inputs, plaintext secrets, or values GitHub can derive from the checkout.
Deployment contractsSanitized non-secret cloud facts for routine app/docs CD.Pulumi state, raw provider subtrees, secret values, or infrastructure backend details.
SSM runtime parametersDeployed app runtime config and runtime secrets.Frontend browser build inputs or deploy bootstrap credentials.
Docker build argsFrontend build-time values, especially browser-visible NEXT_PUBLIC_*Backend runtime secrets or values intended to change without a rebuild.
CI / Playwright injected envTest runner setup and hermetic smoke values.Production or deployed-dev source-of-truth registries.

Do not update every possible file by default. Update the surfaces that own the boundary you classified.

BoundaryCommon Files Or Contracts
Backend runtime envapps/wavemap-back-end/src/env.ts
Frontend browser envapps/wavemap-front-end/src/env/client.ts
Frontend server-only envapps/wavemap-front-end/src/env/server.ts
Shared i18n envpackages/i18n/src/env/client.ts, packages/i18n/src/env/server.ts
GitHub workflow vocabularyinfra/environments/deployed-dev/workflow-env.contract.json
Deployed-dev runtime parametersinfra/operations/src/deployed-dev/runtime-config-contract.ts
Deployed-dev deployment factsDeployment contracts, Pulumi outputs before projection, and infra/environments/deployed-dev/fixtures/runtime-deploy.outputs.valid.json when no-cloud deploy checks consume the shape.
Host env renderingRuntime env render helpers and the runtime deployment source that maps grouped parameters into backend, frontend, and Postgres env files.
Testing and smoke setupCI workflow env setup, Playwright runtime setup, smoke helpers, and Testing only when the verification command or expected config contract changes.
Operator proceduresRunbooks only when the changed value affects a repeated operator decision, live recovery path, readiness check, or mutation gate.

Local development .env.example files should change when a developer needs to provide a new local value. Real local secrets still stay out of git.

Deployed dev keeps workflow bootstrap, cloud facts, and app runtime config separate:

  • GitHub Actions reads the sanitized deployment contract, runtime parameter references, image tags, and deploy metadata.
  • GitHub Actions sends SSM command payloads that reference parameter paths.
  • The runtime host reads /wavemap/dev/runtime/* from SSM Parameter Store.
  • The runtime host renders backend, frontend, and Postgres env files locally.
  • Frontend NEXT_PUBLIC_* values are browser build inputs, not runtime SSM parameters.

Pulumi outputs and deployment contracts should expose parameter names and value kinds, not plaintext secret values. SSM metadata checks should validate names and String / SecureString types without decrypting values.

See Deployed Dev Environment for the environment shape and Runtime Config Readiness for the operator procedure.

Runtime config does not currently have a separate operations page. Keep cross-cutting source-ownership rules here, keep the deployed-dev environment shape in Deployed Dev Environment, and keep repeated live operator steps in Runbooks. Split out a dedicated operations page only when rotation, multi-environment promotion, or inventory lifecycle work grows beyond the runbook.

  • Never commit real secret values.
  • Never print secret values in scripts, workflow summaries, logs, fixtures, or docs.
  • Treat NEXT_PUBLIC_* values as browser-visible, even when the backing value is a restricted provider key.
  • Keep deployed app runtime secrets out of GitHub environment secrets unless there is a documented temporary bridge.
  • GitHub Actions must not decrypt or log SecureString runtime parameters.
  • Prefer presence, name, type, and path validation over value validation for secrets.
  • Redacted placeholders such as [required-secret] are acceptable in no-cloud plans and docs.

Run the narrowest command that proves the changed boundary first, then widen only as needed.

Common deployed-dev checks:

Terminal window
pnpm wavemap -- deploy dev frontend-build-inputs
pnpm wavemap -- deploy dev runtime-parameters
pnpm wavemap -- deploy dev runtime-config plan
pnpm wavemap -- deploy dev runtime-config populate
pnpm wavemap -- deploy dev runtime-config check
pnpm wavemap -- deploy dev runtime-config live
pnpm wavemap -- deploy dev runtime-env
pnpm wavemap -- deploy dev contracts
pnpm wavemap -- deploy dev preflight

Common repo checks:

Terminal window
pnpm verify:scripts
pnpm verify:github-actions
pnpm verify:i18n
pnpm -C apps/wavemap-front-end lint
pnpm -C apps/wavemap-back-end test

Use the app or package parser, lint, or test command when the change is local to one consumer. Use pnpm wavemap -- deploy dev contracts when the value crosses the deployed-dev workflow, build, or runtime boundary. Use pnpm wavemap -- deploy dev preflight before handing off a deployed-dev contract slice.

Treat renames and removals as migrations:

  • Remove the old parser entry only after all runtime, render, build, and workflow paths stop supplying it.
  • Keep compatibility aliases only when an active deployment or migration needs them.
  • Update docs and fixtures in the same slice so no-cloud checks fail on stale names.
  • Prefer failing early in preflight over discovering a missing value on the runtime host.

New frontend browser build value:

  • Add or update the frontend client env schema.
  • Decide whether it is public or restricted public.
  • Add the Docker build arg and deploy build-input resolver coverage.
  • Update the workflow environment manifest if it is part of deployed-dev build vocabulary.
  • Keep it out of runtime SSM unless the server also consumes a separate non-NEXT_PUBLIC_* runtime value.

New backend runtime secret:

  • Add the backend env schema entry.
  • Add a SecureString runtime parameter reference under the appropriate group.
  • Add a redacted placeholder in the runtime config population plan.
  • Add it to runtime inventory docs or runbooks when an operator must create or verify it.
  • Verify with runtime-parameters, runtime-config plan, runtime-config check, and then contracts.

New Pulumi-owned cloud fact:

  • Emit it as a non-secret Pulumi output.
  • Keep provider-specific details under provider.aws until a provider-neutral consumer exists.
  • Add it to the no-cloud fixture only if deploy scripts or validators consume it.
  • Do not mirror it into GitHub environment variables.