Skip to content
env-sync-viewer
Menu

Fleet-wide secrets drift

See secrets drift across your fleet

A scheduled collector runs env-sync diff against every service in its inventory and records, per key, whether each target matches its 1Password source. A read-only viewer shows the latest state of every target. Silence reads as stale, never as healthy.

Sample target: svc-a · prod · vercel (made up)
  • ENV_VAR_ONEmatch
  • ENV_VAR_TWOdrift
  • ENV_VAR_THREEmissing
  • ENV_VAR_FOURpresent
  • ENV_VAR_FIVEunverifiable

key names and states only · no values · no fingerprints

What it does

  • 01

    One page for the whole fleet

    Every target’s latest state per key (match, drift, missing, present or unverifiable), plus the last 20 collector runs.

  • 02

    Silence reads as stale

    A target with no ok drift snapshot within STALE_AFTER_HOURS (26 by default) is flagged. A dead collector turns every target stale.

  • 03

    Never a secret value

    The database holds 12-character fingerprints, not values. The viewer compares them on the server and sends only the verdict to the browser.

  • 04

    Least privilege in the database

    The collector’s Postgres role can only insert; the viewer’s can only select. Row-level security is forced on every table.

  • 05

    Fail-closed credentials

    Each env-sync child gets an explicit, deny-by-default environment: a base floor plus only the credentials of the platforms it is scoped to.

  • 06

    A CLI contract, not a library

    The collector depends only on the JSON that env-sync diff --format json prints (schemaVersion: 1), never on env-sync’s code.

The product →

From inventory to dashboard

  1. Step 1

    Fetch the manifests

    The scheduled job fetches each service’s secrets.manifest.yml, which names its 1Password source and its targets.

  2. Step 2

    Pre-flight

    Every service is checked against the reviewed allowlist: known fields only, platforms with a platform rule only, and identity fields pinned to the allow record. A service that fails is dropped; the rest continue.

  3. Step 3

    Probe the guard

    Two credential-free probes run the pinned env-sync with an unknown and an empty platform scope and prove it refuses both. If the probe fails, the run stops with exit code 3 before any collection.

  4. Step 4

    Collect with scoped credentials

    Each env-sync child gets a fresh empty HOME, the base floor, the credentials of the platforms in its scope, and ENV_SYNC_ALLOWED_PLATFORMS. The collector’s own DATABASE_URL never reaches it.

  5. Step 5

    Write one collector run

    Each invocation becomes one collector run (success, partial or failed) with one drift snapshot per target, written in one transaction by the insert-only role.

  6. Step 6

    Read in the viewer

    Behind the access gate, the viewer selects the latest snapshot per target, compares fingerprints on the server, flags stale targets and renders key names and states.

The whole path →

Know which secrets drifted, without seeing them

env-sync-viewer is self-hosted: you run the collector and the viewer in your own infrastructure. Access to the repository is by request.