# Credential rotation sample

Local rehearsal for rotating one existing application environment credential:
issue a replacement, apply a revision-checked Bex update, verify named
consumers, then retire the old credential explicitly. This tree does **not**
call live Bex or a real identity provider unless you opt into reader-run live
steps. Upstream CAS contracts are recorded in
[`source-review.md`](./source-review.md).

## Requirements

- Node.js ≥ 22.12

## Local fixture commands

```bash
cd examples/credential-rotation
npm test
npm run rehearse          # overlap + revoke on the synthetic issuer
npm run stage -- happy    # deploy → refresh consumers → verify → retire
npm run stage -- save-only-stale
npm run stage -- mixed
npm run scenarios -- stale-revision
npm run scenarios -- partial-activation
npm run scenarios -- premature-revoke
npm run scenarios -- interrupt-uncertain
```

All JSON reports include `"evidence":"local_fixture"` and credential **ids**
only (secrets are never printed by reports).

### What each stage proves

| Stage | Proves | Does not prove |
| --- | --- | --- |
| Issuer overlap | Old and new synthetic credentials can both authenticate | Live IdP behavior |
| `update.mjs` / CAS patch | One key updated with `expectedEnvRevision`; unrelated keys kept | Consumers reloaded the value |
| `rolledOut: true` | `saveMode: deploy` requested a platform rollout | Every replica / consumer ready |
| Activation verify | Named fixture consumers present the expected credential id | All load-balanced replicas |
| Retirement | Explicit revoke after `all_new` only | Provider restore of a revoked key |

## Hosted Bex steps (reader-run)

```bash
export BEX_API_ORIGIN=https://api.bex.co
export BEX_ACCESS_TOKEN=…          # never commit
export BEX_SERVICE_ID=svc_…
export BEX_ENV_KEY=APP_TOKEN
export BEX_ENV_VALUE=…             # replacement; never commit / log
export BEX_SAVE_MODE=save_only     # or deploy
node update.mjs
```

Revision-checked updates use `PATCH /v1/services/{id}/environment` with
`expectedEnvRevision` — see [`source-review.md`](./source-review.md). On
`ENVIRONMENT_REVISION_CONFLICT`, refresh and retry; do not overwrite another
editor. Saving or `rolledOut` alone does not prove consumers adopted the new
value — verify application-owned consumers before retiring the old credential
at its issuer.

If consumers cannot be enumerated, or the external provider lacks overlap,
leave verification incomplete and follow that provider's procedure rather than
claiming a certified zero-downtime rotation.
