Docs · reference

quickstart walkthrough
overnight → morning merge

Quickstart reference — zero to your first overnight PR.

Five onboarding sections a brand-new user walks end to end on day one — connect the Driftlock GitHub App, declare the trigger entry point in a sealed-secret .driftlock/config.yaml, learn the canonical scan cadences, read the resulting PR with the SPDX 2.3 SBOM delta, and follow a five-step rollback recipe. Then the seven-step overnight deep reference scenario — a transitive dependency CVE surfaces at 02:14 UTC, Driftlock pins the alert id, drafts a byte-stable fix on a branch, replays the full monorepo test matrix in the sandbox under the pinned hermetic toolchain, signs the commit with cosign ECDSA P-256 over the SBOM sha256 + the approver-chain root SHA, attaches the SPDX 2.3 SBOM delta, and opens the PR ready for morning merge — a reviewer traces alert id → audit row in one click.

Trigger

dependency.advisory.detected

GHSA-xxxx-yyyy-zzzz · pkg:npm/lodash@4.17.20 — call-graph reachability marks the CVE in-scope.

Audit footprint

Seven columns, one row

alert · triage · drafted-fix · sandboxed-test · approver-chain · signed-commit · sbom — pinned to run id driftlock-run-2026-08-12-7421.

Sandbox

Hermetic · replayed

Toolchain nix:node-22 · hermetic build hash pinned to the run id · failing test test/checkout/refund.round_trip reproduces pre-fix, passes post-fix.

Signature + SBOM

cosign + SPDX 2.3

Cosign keyful ECDSA P-256 over commit SHA + SBOM sha256 + approver-chain root SHA. SPDX 2.3 emitted at registry.internal/<org>/<repo>/spdx/<sha256>.spdx.json.

byte-stable · replayable · KMS-resident

Connect GitHub

Install the Driftlock GitHub App — six steps from OAuth scope to a verified first delivery.

Every Driftlock trial begins with the GitHub App install. The six steps below are the day-one onboarding checklist — every row names both the platform-team action and the verification the operator runs to confirm the row landed. None of the steps ask for write scope on your repo; the Driftlock App manifest declares a read-only grant set and the platform team can revoke per-repo access without uninstalling.

#

step · verification command

01

Install the Driftlock GitHub App on your org

From the platform-team dashboard, install the Driftlock GitHub App on the org that owns the watched repos. The install URL is one-click; the App manifest declares the read-only Dependabot, pull_request, check_run, and branch_protection events the watcher subscribes to — no write scopes are requested at install.

02

Select the 2–10 watched repos

The App surfaces a per-repo grant screen at install. Pick the trial repos (typically 2 to 10 monorepos the platform team keeps under change-control). Least-privilege scope is enforced at the App manifest level — your team can revoke per-repo access without uninstalling.

03

Confirm OAuth permission scope

The Driftlock App declares read-only Dependabot + pull_request + check_run + branch_protection. The install screen enumerates each scope before confirmation. Bring your security reviewer to this step — the per-scope list is the audit-trail vocabulary the regulatory questionnaire expects.

04

Confirm the in-VPC webhook subscription

The install step opens a webhook from GitHub → your Driftlock receiver URL (the in-VPC endpoint the platform team registered at install). The first delivery fires within a minute; the receiver acks with a 200 + a delivery_id the watcher pins to the run id it will produce.

05

Verify the receiver acks the first delivery

In the Driftlock dashboard, the GitHub Webhook card reads `last delivery 200 · <delivery_id>`. The receiving endpoint HMAC-validates the X-Hub-Signature-256 header against your KMS-resident webhook secret before the payload lands. A mismatched signature fails closed — the watcher never sees it.

06

Bootstrap the .driftlock/config.yaml RBAC block

Commit a sealed-secret .driftlock/config.yaml to the watched repo. The block enumerates the six platform-team roles × eleven actions; every `+` cell surfaces a dual-approval sign-off marker. The config is the source of truth for approver chain on every PR the watcher drafts.

install · select-repos · scope-oauth · webhook-subscription · receiver-ack · rbac-bootstrap

Trigger entry point

The .driftlock/config.yaml declares which signal sources the watcher listens on.

The watcher subscribes to six signal classes. Each one is a key in `.driftlock/config.yaml` under the `sources:` block; turning a key off disables that trigger without redeploying. The snippet below is what a brand-new user drops into the watched repo on day one — the file is sealed-secret encrypted, reviewed by your platform team, and re-applied on every helm upgrade.

Day-one config snippet

sealed-secret
commit to watched repo
# .driftlock/config.yaml — committed to the watched repo, sealed-secret encrypted.
# Reviewed by your platform team; re-applied on every helm upgrade.

sources:
  dependabot:
    enabled: true                  # GitHub-native alerts for your direct deps
    severity_floor: medium         # drop LOW-severity alerts before they pollute the queue
    package_ecosystems: [npm, pip, cargo, go, maven]
  ghsa:
    enabled: true                  # GitHub Security Advisories · transitive reachability
    feed: https://api.github.com/advisories
    poll_interval_sec: 900
  nvd:
    enabled: true                  # NVD CVE feed — independent of GHSA
    poll_interval_sec: 3600
    cps_severity_floor: high
  osv:
    enabled: true                  # OSV.dev cross-ecosystem DB
    poll_interval_sec: 1800
  ci_failure:
    enabled: true                  # CI emits job.completed events on failure
    replay_first: true             # sandbox replays the failing test before diff is applied
    audience: driftlock            # OIDC audience claim the verifier checks
  on_call:
    enabled: false                 # opt-in: PagerDuty / Opsgenie / SLO burn alerts
    slo_burn_floor: 2.0

# The watcher ingests every source above and runs the call-graph reachability
# rule before drafting a fix. Out-of-scope dependencies do not produce runs.

The signal sources the snippet declares

  • Dependabot

    event-driven · GHSA-native · <60s to scrape

  • GHSA

    15-minute poll · transitive reachability scoring

  • NVD

    60-minute poll · CPS severity floor applied

  • OSV

    30-minute poll · cross-ecosystem dependency DB

  • CI failure

    event-driven · OIDC claim audited · replay-first

  • On-call

    opt-in · SLO burn-rate floor · PagerDuty / Opsgenie

sources dependabot · ghsa · nvd · osv · ci_failure · on_call — declared in .driftlock/config.yaml, applied on every helm upgrade.

Scan cadence

Five cadences a reviewer learns on day one.

Five cadences a reviewer learns on day one. Each runs inside the in-VPC sandbox with default-deny egress; a 4-hourly re-scan picks up advisories that gain a CVE after the nightly sweep. The cron syntax mirrors the schedule documented on `/docs/self-host#cron-and-scheduling` — the platform team can move each row without rewriting the pipeline. /docs/self-host › cron-and-scheduling carries the cron-syntax reference the platform team owns.

step 0102:14 UTC · nightly dependency-feed sweep

The nightly cron pulls NVD + OSV + GHSA into a single deduped envelope. The watcher cross-checks against the call-graph and updates the reachability cache. Run id is keyed off the UTC date — every artefact a 02:14 run produces carries the same run id, so an audit day can replay the whole sweep row by row.

step 02on-PR-trigger · within 60 seconds

A pull-request event triggers a sub-minute scan against the PR head SHA. The watcher opens a branch if the diff introduced a vulnerable PURL reachable from the review surface; no branch is opened when the diff is merge-conflict or already-fixed.

step 034-hourly · hot-CVE re-scan

CVEs that score above your CPS severity floor re-scan every four hours. The re-scan emits a fresh SBOM delta against the current main; an updated dep on a hot CVE fans out a new alert id and the watcher drafts a follow-up PR automatically.

step 04on-alert · within same run id

When the watcher detects a CVE, it replays the full monorepo test matrix under the pinned hermetic toolchain. Replay status (`REPLAYED_OK` / `REPLAYED_FAIL`) is stamped onto the audit-trail `sandboxed-test` row alongside the toolchain identity.

step 0524:00 UTC · sbom-reaper + rekor-prune cron

Two nightly housekeeping jobs close the ledger. The sbom-reaper links orphan SBOM hashes back to the owning PR for retention enforcement; the Rekor-prune job moves cold claims into the offline tier. Both run on Sunday only; their cron schedules share the schedule documented on `/docs/self-host#cron-and-scheduling`.

02:14 nightly · on-PR <60s · 4-hourly re-scan · on-alert replay · sbom-reaper + rekor-prune

Read the PR

Where the SBOM delta lands, and how a reviewer reads it at 08:00.

The Driftlock-stamped PR carries three artefacts a reviewer reads at the same time — the description body, the SBOM-hash diff table, and the in-PR trigger link that carries the alert id. The SBOM document itself lands at the content-addressed registry path registry.internal/<org>/<repo>/spdx/<sbom_sha256>.spdx.json — the same path the /docs/compliance › sbom-emission reference documents. A reviewer clicks the trigger link once and lands on the alert row in the audit-trail — alert, triage, drafted-fix, sandboxed-test, approver-chain, signed-commit, and sbom, one screen.

Reading order at 08:00

five sections
SPDX 2.3 · byte-stable
  • SummaryCVE id, advisory GUID, affected PURL list — pinned to the run id at the top of the description.
  • RiskCall-graph reachability verdict, egress verdict against the release registry, severity score.
  • Test evidenceToolchain identity, hermetic-build hash, replay status (REPLAYED_OK / REPLAYED_FAIL), sandbox log URL.
  • ComplianceAudit row id, SBOM sha256, cosign KID + Rekor claim payload — all five audit-trail columns in the table.
  • Reviewer checklistFive checkbox items — version bump, lockfile vs SBOM hash diff, cosign verify, rekor search, sign-off.

summary · risk · test evidence · compliance · reviewer checklist · audit-trail row pinned to run id

Rollback

Five steps the platform team runs on a bad merge.

When a merged PR needs to come back out — the test passes locally but fails in production, the CVE was mis-graded, or the lockfile churn unmasked a regression — the rollback recipe below is the canonical path. Every step is auditable; the cosign `verify-blob` confirmation ensures the head SHA on the Rekor log survives the revert. /docs/install › upgrade-rollback carries the install-side flip side of the same recipe — pre-flight, apply, rollback — for the platform team that owns the helm chart.

  1. rollback · step 01

    Revert the merge commit and push

    Run `git revert -m 1 <merge-sha> && git push origin main`. The revert commit carries the original PR head SHA in its message; the watcher re-runs the pup-line SBOM delta table against the revert and stamps a new run id onto the audit-trail `drafted-fix` slot for the revert itself.

  2. rollback · step 02

    Close any follow-up PRs that depended on the reverted SHA

    Run `gh pr close <pr-number>` on every PR that referenced the reverted head SHA in its `risk` section. Driftlock stamps a `reverted-by=<merge-sha>` trailer onto each closed PR so a future audit day can trace the chain.

  3. rollback · step 03

    Re-open the /demo review queue

    On the /demo dashboard the queue card flips from `merged` to `reverted`. Reviewers get an inbox ping on every PR whose `risk` section still pins to the reverted SHA. The queue drift surfaces in the audit-trail `approver-chain` row — no PR is silently skipped.

  4. rollback · step 04

    Stamp audit row `rollback-issued`

    The audit-trail row for the original merge receives a `rolled-back-by <revert-sha> at <UTC>` line. The existing Rekor claim stays valid — the rolled-back commit is still in the transparency log — but the live `signed-commit` row now points at the revert. A regulator tracing the chain reads the trail intact, with the rollback stamped onto the original row.

  5. rollback · step 05

    Re-run cosign `verify-blob` against the SBOM sha256

    Run `cosign verify-blob --key kms://<your-kms-key-alias> --signature <sig-b64> <sbom-sha256>.spdx.json`. The exit code is `0` for already-verified commits: the Rekor claim is still valid even after the revert. The full upgrade / rollback lifecycle is documented on `/docs/install#upgrade-rollback`.

revert · pr-close · queue-reopen · audit-stamp · verify-blob · Rekor-anchored

The scenario

Ingest → triage → draft → sandbox test → sign → SBOM delta → open PR.

Seven ordered steps the watcher runs to take a CVE from "detected" to a PR ready for morning merge. Every step pins a write onto the audit-trail record — a reviewer traces back through PR description → SBOM hash → approver-chain → commit signature → sandbox run id → alert id → advisory GUID in one hop. The full pipeline diagram + audit-trail vocabulary lives on /architecture.

step 01overnight · 02:14 UTC → 08:00 PR

Ingest — the dependency feed surfaces a transitive CVE while you sleep.

02:14 UTC. The in-VPC watcher pulls the GHSA / NVD / OSV feed. The incoming payload matches the dependency-advisory envelope from /docs/webhooks; the watcher pins the advisory GUID + the affected PURL list to a per-PR alert id and lands the row on the audit-trail `alert` slot. No human intervention, no on-call page — by the time the watcher moves on, the alert sits pinned to the run id it will produce.

step 02overnight · 02:14 UTC → 08:00 PR

Triage — call-graph reachability marks the CVE in-scope.

The watcher runs the call-graph reachability rule (`deps.reachable.npm.lodash` style). It walks the import graph from your review surface to the affected PURL and writes the verdict onto the audit-trail `triage` row. The egress verdict against the release registry is logged against `triage.egressVerdict`. A pinned PURL + alert id is the pair the rest of the run hangs off of; flip the dependency out of scope and the run halts, no PR is opened.

step 03overnight · 02:14 UTC → 08:00 PR

Draft — byte-stable fix lands on a branch with the lockfile churn.

The watcher opens a branch, pins the affected package to the patched version, and writes the exact byte-stable diff onto the audit-trail `drafted-fix` slot — same bytes across reruns, pinned to the run id that produced it. The lockfile churn is part of the diff, not a follow-up commit, so reviewers diff the lockfile and the SBOM hash together in one motion.

step 04overnight · 02:14 UTC → 08:00 PR

Sandbox test — full monorepo test matrix, hermetic, replay succeeds.

The sandbox runner takes the drafted fix and replays the full monorepo test matrix under the pinned hermetic toolchain. The audit-trail `sandboxed-test` row carries the toolchain identity, the hermetic-build hash, the exact failing test that triggered the run, and the replay status — `REPLAYED_OK` only when the test reproduces and the proposed fix passes it. Egress is bounded by the platform team’s allow-list; an outbound call to a host the team has not reviewed fails the run with a `triage.egressVerdict` reject line.

step 05overnight · 02:14 UTC → 08:00 PR

Sign — cosign ECDSA P-256 commit, Rekor claim pinned to the run.

The signing-controller stamps the cosign ECDSA P-256 signature over the commit + the SBOM sha256 + the approver-chain root SHA. The Rekor transparency-log claim payload carries `run_id`, `sbom_sha256`, and `approver_chain_root` — the same payload documented on /docs/compliance › cryptographic-signing. KMS-resident by default; on Enterprise tier the platform team’s HSM holds the private half, never the signing workload itself.

step 06overnight · 02:14 UTC → 08:00 PR

SBOM delta — SPDX 2.3 emitted at the content-addressed registry path.

The sandbox runner emits the SPDX 2.3 document for the new commit and writes it to the content-addressed registry path — `registry.internal/<org>/<repo>/spdx/<sbom_sha256>.spdx.json` — the same path the /docs/compliance › sbom-emission reference declares. The SBOM hash diff against last main is attached to the PR description so reviewers see the dependency delta in one glance, and the audit-trail `sbom` slot pins the document to the run id.

step 07overnight · 02:14 UTC → 08:00 PR

Open PR — PR ready in the queue, reviewer traces alert id → audit row.

A PR lands in the queue with Driftlock-stamped PR description, the SBOM delta table, and an in-PR trigger link that carries the alert id. The reviewer clicks once and lands on the audit row — alert, triage, drafted-fix, sandboxed-test, approver-chain, signed-commit, sbom — all on one screen. Approve, merge, and the run closes out idempotently; reject, and the run halts before the signing step.

ingest · triage · draft · sandbox-test · sign · sbom-delta · open-pr · byte-stable · KMS-resident · Rekor-anchored

Incoming notification

The wrapper shape — HMAC + signing header, then the alert-id pin.

The wrapper around the dependency advisory carries the same HMAC + signing-header surface every Driftlock inbound envelope uses — cryptographic signing covers the verifier path. The receiver-key on the in-VPC webhook receiver accepts the payload before the watcher pins the alert id, so a tampered advisory fails closed before the run begins.

Example payload

Incoming notification — `dependency.advisory.detected`

The dependency webhook that fires the run. Shape mirrors the example on /docs/webhooks › dependency-advisory-detected; the wrapper preserves the HMAC + signing header so the receiver-key on the in-VPC webhook receiver accepts the payload before the watcher pins the alert id.

{
  "delivery_id": "019284f3-1a6c-71e2-b4f1-9c8a7e2d4a55",
  "event": "dependency.advisory.detected",
  "webhook_id": "dependency-webhook",
  "advisory_id": "GHSA-xxxx-yyyy-zzzz",
  "source": "GHSA",
  "cve": {
    "id": "CVE-2026-9999",
    "cvss_v3": 7.5
  },
  "affected": [
    { "purl": "pkg:npm/lodash@4.17.20" }
  ],
  "call_graph": [
    "api/users",
    "middleware/audit",
    "utils/dep"
  ],
  "severity": "high",
  "first_detected": "2026-08-12T02:14:09Z",
  "ingested_at": "2026-08-12T02:14:11Z",
  "alert_id_hint": "driftlock-alert-2026-08-12-7421",
  "headers": {
    "X-Driftlock-Advisory-Signature": "t=1762884849,v1=2cf24d…",
    "X-Driftlock-Delivery":         "019284f3-1a6c-71e2-b4f1-9c8a7e2d4a55"
  }
}

dependency · advisory · detected · HMAC-SHA256 · alert_id hint

PR description template

Driftlock-stamped Markdown body — five sections, audit-trail mapped.

Each section header below maps 1:1 to a column on the merge audit-trail record (/docs/compliance › merge audit trail): Summary → Risk → Test evidence → Compliance → Reviewer checklist. The template pins the PR body to the run id so a regulator can trace any merged PR back to its alert, its sandbox run, its SBOM, and its Rekor claim.

Markdown body

PR description — Driftlock-stamped body a reviewer reads at 08:00.

The Markdown body Driftlock stamps onto the PR. Each section header corresponds to one audit-trail row — alert → triage → drafted-fix → sandboxed-test → approver-chain → signed-commit → sbom — so the PR body and the audit-trail record walk the reader down the same columns.

## Summary

- Bump `lodash` from `4.17.20` to `4.17.21` to address CVE-2026-9999.
- Triggered by `dependency.advisory.detected` for advisory `GHSA-xxxx-yyyy-zzzz`.
- Pinned to run id `driftlock-run-2026-08-12-7421`.

## Risk

- Scope: `pkg:npm/lodash@4.17.20`, reachable from `api/users`, `middleware/audit`, `utils/dep`.
- Triage verdict: **in-scope** (rule `deps.reachable.npm.lodash`).
- Egress verdict: `triage.egressVerdict = ALLOW` against `registry.npmjs.org`.
- Severity: high (CVSS v3 7.5).

## Test evidence

- Toolchain: `nix:node-22` · hermetic build hash `9e2f…`.
- Failing test pre-fix: `test/checkout/refund.round_trip` — replay-passed post-fix.
- Replay status: `REPLAYED_OK` · sandbox log ref: `/var/lib/driftlock/runs/7421/sandbox.log`.

## Compliance

- Audit row: `pr_id=acme/checkout-svc#4215` · `head_sha=8f6c1d5b9c2f…`.
- SBOM: SPDX 2.3 · sha256 `3f6e…` · registry path:
  `registry.internal/acme/checkout-svc/spdx/3f6e….spdx.json`.
- Signature: cosign ECDSA P-256 · KMS-resident signer
  `driftlock/commit-signer`.
- Rekor claim payload: `run_id`, `sbom_sha256`, `approver_chain_root`.

## Reviewer checklist

- [ ] Confirm the version bump is the patched release the advisory
      recommends (no unrelated upgrades).
- [ ] Confirm the lockfile churn matches the SBOM hash delta (no
      silent drift).
- [ ] Re-run `cosign verify --certificate-identity-regexp ".*" <head_sha>`
      — expect `0` exit.
- [ ] Run `rekor search --artifact <head_sha>` — expect one inclusion
      claim with the run id.
- [ ] Approve or request changes — both land on the approver-chain row
      before merge.

summary · risk · test evidence · compliance · reviewer checklist · pinned to run id

Back to the runbook

The parent /docs page covers the four reference sections — this page walks the pipeline that ties them together.

The walkthrough above composes the audit-trail vocabulary from /docs/compliance, the dependency-advisory envelope from /docs/webhooks, and the audit-trail diagram from /architecture into one overnight scenario — the alert id travels through every artefact, every verifier command, every reviewer checklist.

Request a deeper-docs walkthrough

We'll reply with a calendar link and the air-gap or key-handling runbook relevant to your scope.