docs(security): secrets change subscription and live scoped accessor#584
Conversation
Pre-existing format:check violation on the kris/secrets-docs branch; the repo-wide prettier gate must be clean for CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…accessor Documents harper#1787 (live secret change detection) on the new secrets reference page: - secrets.subscribe(name) — async iterable yielding the current value then every change; shown as read-now + fire-and-forget background subscribe so module load isn't blocked (the practical hot-swap-on-rotation pattern). - Live scoped-tier accessor: a fresh secrets.NAME read reflects the latest value; a destructure is now called out as a point-in-time copy. - Reworked 'Healing after changes' into a per-tier 'How each tier sees a change' table (scoped = live; global/process.env = reload-only) and corrected the 'frozen' accessor description to the read-only live view, with subscribe as a non-enumerable member. Ships in v5.2.0 alongside the rest of the secrets store, so no differential VersionBadge (the page is uniformly 5.2.0 surface). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request updates the secrets documentation to explain the live nature of the scoped tier accessor and introduces the new secrets.subscribe() API for handling secret rotations. The review feedback suggests optimizing the provided code example for secrets.subscribe() to avoid a redundant client instantiation on startup by tracking the active key and only re-instantiating when it changes.
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584 This preview will update automatically when you push new commits. |
Address review on #584: secrets.subscribe() replays the current value first, so guard on key change to skip the redundant client rebuild on startup, and note that semantic inline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584 This preview will update automatically when you push new commits. |
…ance The inline 'How to read it in your component' guidance on the cluster Secrets config page now shows the live-change API from harper#1787: - Scoped-tier example reads the value immediately, then subscribes in a fire-and-forget background task so module load isn't blocked, guarding on change so the first (current-value) yield doesn't trigger a redundant rebuild. The global/process.env tier stays reload-only (subscribe there is not live), so its example is unchanged. - Outward links to the Harper secrets docs (reference/v5/security/secrets): one contextual link by the code example, one in the config page toolbar. Docs backing the example: HarperFast/documentation#584. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the studio review fix (HarperFast/studio#1501): the fire-and-forget subscribe loop is copy-paste code, so wrap it in try/catch and console.error the failure so a stream error can't become an unhandled promise rejection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584 This preview will update automatically when you push new commits. |
…ption Per feedback: reading secrets.NAME (undestructured) returns the live value on every read, so most components just use the secret where they need it — e.g. per request inside a resource — and get the current value with no subscription. Only a destructure takes a snapshot. Reframe subscribe() as the case for long-lived objects built from a secret (client/pool/signer) that must be rebuilt on rotation, and make the loader note's per-loader boundary explicit (vm/compartment read live anywhere; native resolves only during load). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584 This preview will update automatically when you push new commits. |
kriszyp
left a comment
There was a problem hiding this comment.
Accurate secrets docs and the examples handle secrets safely (no lingering plaintext). One minor nit worth a follow-up: the subscribe sample could use an undefined-guard, but nothing blocking. Approving.
🤖 Reviewed with KrAIs (Claude Opus 4.8)
🧹 Preview CleanupThe preview deployment for this PR has been removed. |
…ance The inline 'How to read it in your component' guidance on the cluster Secrets config page now shows the live-change API from harper#1787: - Scoped-tier example reads the value immediately, then subscribes in a fire-and-forget background task so module load isn't blocked, guarding on change so the first (current-value) yield doesn't trigger a redundant rebuild. The global/process.env tier stays reload-only (subscribe there is not live), so its example is unchanged. - Outward links to the Harper secrets docs (reference/v5/security/secrets): one contextual link by the code example, one in the config page toolbar. Docs backing the example: HarperFast/documentation#584. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ance The inline 'How to read it in your component' guidance on the cluster Secrets config page now shows the live-change API from harper#1787: - Scoped-tier example reads the value immediately, then subscribes in a fire-and-forget background task so module load isn't blocked, guarding on change so the first (current-value) yield doesn't trigger a redundant rebuild. The global/process.env tier stays reload-only (subscribe there is not live), so its example is unchanged. - Outward links to the Harper secrets docs (reference/v5/security/secrets): one contextual link by the code example, one in the config page toolbar. Docs backing the example: HarperFast/documentation#584. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ance The inline 'How to read it in your component' guidance on the cluster Secrets config page now shows the live-change API from harper#1787: - Scoped-tier example reads the value immediately, then subscribes in a fire-and-forget background task so module load isn't blocked, guarding on change so the first (current-value) yield doesn't trigger a redundant rebuild. The global/process.env tier stays reload-only (subscribe there is not live), so its example is unchanged. - Outward links to the Harper secrets docs (reference/v5/security/secrets): one contextual link by the code example, one in the config page toolbar. Docs backing the example: HarperFast/documentation#584. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stacks on #581 (targets its
kris/secrets-docsbranch). Documents the live secret-change feature that landed after #581 was written, so the secrets page backs the new API instead of still saying "no live re-materialization."What & why
Feature PR: harper#1787 — Add live secret change subscription and live scoped accessor (implements harper#1776), merged into
main(5.2.0-alpha.5). Studio's Secrets config page now shows asecrets.subscribe()example in its inline guidance and links here, so the docs need to cover it.Changes to
reference/security/secrets.md:### React to rotations with secrets.subscribe()— documents the async iterable (current value, then every change), with the practical pattern: read the value for immediate use, then subscribe in a background task so a top-levelfor awaitdoesn't block module load. Covers per-event authority re-eval (revoke/delete →undefined, stream stays open; re-grant resumes on the same iterator) and the reservedsubscribename.secrets.NAMEis live on the scoped tier, and that a destructure is a point-in-time copy (won't observe rotations). Corrected the old "frozen and enumerable" description to the read-only live view, withsubscribeas a non-enumerable member.process.env= reload-only (deliberate — inherited env + "real env wins" precedence). The reload-only healing note is retained for the global tier.Ships in v5.2.0 alongside the rest of the secrets store, so no differential
<VersionBadge>— the page is uniformly 5.2.0 surface (consistent with #581, which added none).Note on the extra commit
The first commit (
style(operations-api): …) is Prettier table alignment only — no content change. Thekris/secrets-docsbranch currently failsformat:checkon bothoperations.mdandsecrets.md; since CI runsprettier . --checkrepo-wide, that has to be clean for this PR to go green.secrets.md's pre-existing formatting is fixed within the content commit (Prettier also added a trailing comma to thejsoncenvelope example — valid for that block).Verification
npm run format:write+npm run format:checkclean.npm run buildsucceeds; the new#react-to-rotations-with-secretssubscribecross-link resolves (the only broken-anchor warning is a pre-existing one onrelease-notes/v5-lincoln/5.1, unrelated to this change).🤖 Generated with Claude Code