Skip to content

docs(security): secrets change subscription and live scoped accessor#584

Merged
kriszyp merged 5 commits into
kris/secrets-docsfrom
dawson/secrets-subscribe-docs
Jul 14, 2026
Merged

docs(security): secrets change subscription and live scoped accessor#584
kriszyp merged 5 commits into
kris/secrets-docsfrom
dawson/secrets-subscribe-docs

Conversation

@dawsontoth

Copy link
Copy Markdown
Contributor

Stacks on #581 (targets its kris/secrets-docs branch). 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 a secrets.subscribe() example in its inline guidance and links here, so the docs need to cover it.

Changes to reference/security/secrets.md:

  • New ### 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-level for await doesn'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 reserved subscribe name.
  • Live scoped accessor — the "Read scoped secrets" section now notes that secrets.NAME is 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, with subscribe as a non-enumerable member.
  • Replaced "Healing after changes" with a per-tier "How each tier sees a change" table: scoped = live (accessor + subscribe); global/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. The kris/secrets-docs branch currently fails format:check on both operations.md and secrets.md; since CI runs prettier . --check repo-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 the jsonc envelope example — valid for that block).

Verification

  • npm run format:write + npm run format:check clean.
  • npm run build succeeds; the new #react-to-rotations-with-secretssubscribe cross-link resolves (the only broken-anchor warning is a pre-existing one on release-notes/v5-lincoln/5.1, unrelated to this change).

🤖 Generated with Claude Code

dawsontoth and others added 2 commits July 14, 2026 11:19
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>
@dawsontoth
dawsontoth requested a review from a team as a code owner July 14, 2026 15:20

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread reference/security/secrets.md
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584

This preview will update automatically when you push new commits.

@github-actions
github-actions Bot temporarily deployed to pr-584 July 14, 2026 15:22 Inactive
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>
@github-actions
github-actions Bot temporarily deployed to pr-584 July 14, 2026 15:26 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-584

This preview will update automatically when you push new commits.

@dawsontoth
dawsontoth requested a review from kriszyp July 14, 2026 15:27
dawsontoth added a commit to HarperFast/studio that referenced this pull request Jul 14, 2026
…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>
@github-actions
github-actions Bot temporarily deployed to pr-584 July 14, 2026 15:39 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your 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>
@github-actions
github-actions Bot temporarily deployed to pr-584 July 14, 2026 16:31 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your 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 kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

@kriszyp
kriszyp merged commit d0f1579 into kris/secrets-docs Jul 14, 2026
7 checks passed
@kriszyp
kriszyp deleted the dawson/secrets-subscribe-docs branch July 14, 2026 18:49
@github-actions

Copy link
Copy Markdown

🧹 Preview Cleanup

The preview deployment for this PR has been removed.

dawsontoth added a commit to HarperFast/studio that referenced this pull request Jul 17, 2026
…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>
dawsontoth added a commit to HarperFast/studio that referenced this pull request Jul 17, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants