Skip to content

docs(security): secrets store, secrets operations, and deploy_component registryAuth - #581

Merged
Ethan-Arrowood merged 5 commits into
mainfrom
kris/secrets-docs
Jul 27, 2026
Merged

docs(security): secrets store, secrets operations, and deploy_component registryAuth#581
Ethan-Arrowood merged 5 commits into
mainfrom
kris/secrets-docs

Conversation

@kriszyp

Copy link
Copy Markdown
Member

Summary

Adds v5 reference documentation for the encrypted secrets store and the deploy_component private-registry auth path. None of this was previously documented in v5 — the only secret-adjacent page was environment-variables/overview.md, which covers loadEnv/.env only.

Covers the feature shipped across harper#1550/#1554/#1582 (the store, operations, and component consumption) and harper#1717 — feat: registry-auth via the hdb_secret store (private-registry credentials on deploy_component).

What's included

  • reference/security/secrets.md (new — the hub): the hdb_secret store model; custody as a Harper Pro capability vs. what OSS core can do (store/replicate client-encrypted envelopes, but not decrypt); the two mutually-exclusive delivery tiers (globalprocess.env, scopedgrants + the secrets accessor); the config.yamlenv: declaration block (declarations are requests, not grants); the import { secrets } from 'harper' accessor and recommended top-level-destructure idiom; the full client-side enc:v1: envelope format with a Node reference client; and the threat model. Added to the Security sidebar.
  • reference/operations-api/operations.md: a new ## Secrets section documenting all six operations (set_secret, grant_secret, revoke_secret, list_secrets, delete_secret, get_secrets_public_key) with request/response shapes, plus a registryAuth subsection under deploy_component.
  • reference/components/javascript-environment.md: adds secrets to the Harper API globals list.
  • reference/environment-variables/overview.md: cross-links to the secrets store as the production alternative to a committed .env.

Verification

  • All cross-links and heading anchors resolve.
  • Content checked against the source: config.env wiring (componentLoader.ts), custody OSS/Pro split (secretDecryptor.ts — "Core ships no custody"), and the envelope format (ported from harper's own docs/env-secret-encryption.md).
  • ⚠️ A full docusaurus build was not run in my environment (the @signalwire/docusaurus-plugin-llms-txt dependency wasn't installed locally). Please confirm a clean build in CI / a deps-installed checkout before merging.

Reviewer notes

  • Custody is framed as a Harper Pro capability rather than naming the specific component — confirm that's the right public positioning.
  • Design rationale (custody key model / decision records) is intentionally kept out of public docs.

🤖 Generated with Claude Code

…mponent registryAuth
Adds v5 reference documentation for the encrypted secrets store (#1550/#1554/
#1582) and the deploy_component private-registry auth path (#1717), none of
which was previously documented.
- reference/security/secrets.md (new): store model, custody (Pro) vs OSS core,
the two delivery tiers (process.env global vs scoped grants), the config.yaml
`env:` declaration block, the `import { secrets } from 'harper'` accessor,
full client-side `enc:v1:` envelope format + Node reference client, and the
threat model. Added to the Security sidebar.
- reference/operations-api/operations.md: new Secrets section (set_secret,
grant_secret, revoke_secret, list_secrets, delete_secret,
get_secrets_public_key) plus a registryAuth subsection under deploy_component.
- reference/components/javascript-environment.md: add `secrets` to the Harper
API globals list.
- reference/environment-variables/overview.md: cross-link to the secrets store
as the production alternative to a committed .env.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kriszyp
kriszyp requested a review from a team as a code ownerJuly 13, 2026 17:25

@gemini-code-assistgemini-code-assistBot 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 introduces comprehensive documentation for Harper's new encrypted and replicated secrets store, detailing its concepts, delivery tiers, management operations, and client-side encryption. The review feedback focuses on improving the documentation's clarity and professionalism, specifically by clarifying security risks in configuration files, refining grammar, replacing colloquial phrasing, and adding a response example for the list_secrets operation.

Comment threadreference/security/secrets.md Outdated
Comment threadreference/security/secrets.md Outdated
The `secrets` object is frozen and enumerable (`Object.keys(secrets)`, spread). Global-tier secrets are read from `process.env` as usual and do not need the accessor.

:::note
Under the VM/compartment component loaders the `harper` module is per-scope, so `import { secrets } from 'harper'` binds to the loading component exactly. Under the native loader the `harper` package is a process-wide singleton, so `secrets` binds to the current component via the component-load context; accessing it **outside** a component-load context fails loudly rather than guessing which component is asking. The module-top-level destructure above is exact in all modes.

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.

medium

Add commas after introductory adverbial phrases to improve the readability of the explanation.

Suggested change:
Under the VM/compartment component loaders, the harper module is per-scope, so import { secrets } from 'harper' binds to the loading component exactly. Under the native loader, the harper package is a process-wide singleton, so secrets binds to the current component via the component-load context; accessing it outside a component-load context fails loudly rather than guessing which component is asking. The module-top-level destructure above is exact in all modes.

Suggested change
Under the VM/compartment component loaders the `harper` module is per-scope, so `import { secrets } from 'harper'` binds to the loading component exactly. Under the native loader the `harper` package is a process-wide singleton, so `secrets` binds to the current component via the component-load context; accessing it **outside** a component-load context fails loudly rather than guessing which component is asking. The module-top-level destructure above is exact in all modes.
Under the VM/compartment component loaders, the harper module is per-scope, so import { secrets } from 'harper' binds to the loading component exactly. Under the native loader, the harper package is a process-wide singleton, so secrets binds to the current component via the component-load context; accessing it outside a component-load context fails loudly rather than guessing which component is asking. The module-top-level destructure above is exact in all modes.

Comment threadreference/security/secrets.md Outdated

### Healing after changes

Materialization happens once per load cycle — there is no live re-materialization. A secret that was granted late, rotated, or whose custody came up after boot heals on the next **restart or component reload**, when the store is re-read.

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.

medium

The word "heals" is a bit colloquial for technical documentation. Using "is resolved" or "becomes available" is more professional and clear.

Suggested change
Materialization happens once per load cycle — there is no live re-materialization. A secret that was granted late, rotated, or whose custody came up after boot heals on the next **restart or component reload**, when the store is re-read.
Materialization happens once per load cycle — there is no live re-materialization. A secret that was granted late, rotated, or whose custody came up after boot is resolved on the next **restart or component reload**, when the store is re-read.

Comment threadreference/operations-api/operations.md
@github-actions
github-actionsBot temporarily deployed to pr-581 July 13, 2026 17:28 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

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

This preview will update automatically when you push new commits.

Comment threadreference/operations-api/operations.md
…584)
* style(operations-api): apply prettier table alignment
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>
* docs(security): document secrets change subscription and live scoped 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>
* docs(security): dedupe the subscribe example's startup rebuild
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>
* docs(security): guard the subscribe example against unhandled rejections
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>
* docs(security): lead with the live accessor; subscription is the exception
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>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

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

This preview will update automatically when you push new commits.

@github-actions
github-actionsBot temporarily deployed to pr-581 July 14, 2026 18:52 Inactive
…deploy auth
deploy_component's registryAuth field was renamed to a general-purpose
`credentials` array (harper#1797) that now carries both npm-registry
(`registry`) and git-host (`host`) credential entries; the git-over-HTTPS
path (harper#1792) serves the token to git from memory via a credential
helper. Update the operations reference and the secrets page accordingly,
including the derived secret-name conventions and a rename note.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
github-actionsBot temporarily deployed to pr-581 July 16, 2026 14:36 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

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

This preview will update automatically when you push new commits.

- Note that Harper Studio offers a graphical interface for managing secrets
(Dawson's suggestion) on both the Secrets page and the operations section.
- Clarify that a string env value is stored plaintext in config.yaml (VCS).
- Add a list_secrets response example.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

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

This preview will update automatically when you push new commits.

Co-Authored-By: Codex <noreply@openai.com>
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

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

This preview will update automatically when you push new commits.

@github-actions
github-actionsBot temporarily deployed to pr-581 July 18, 2026 00:56 Inactive

@Ethan-ArrowoodEthan-Arrowood 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.

LGTM — I verified the security-relevant claims against source (secretOperations.ts, secretEnvelope.ts, merged harper#1717/#1797): operation names, roles, payloads/responses, the envelope codec, and the custody model all check out, and the doc actively steers away from insecure handling (plaintext-in-config warning, threat model, delete ≠ erasure, super_user-only). Accurate and well-scoped.

sent with Claude Opus 4.8

@Ethan-Arrowood
Ethan-Arrowood merged commit 37dd347 into mainJul 27, 2026
7 checks passed
@Ethan-Arrowood
Ethan-Arrowood deleted the kris/secrets-docs branch July 27, 2026 14:30
@github-actions

Copy link
Copy Markdown

🧹 Preview Cleanup

The preview deployment for this PR has been removed.

dawsontoth added a commit that referenced this pull request Jul 29, 2026
Conflict in reference/operations-api/operations.md was additive: main added the
`credentials` parameter plus its "Deploy credentials" section (#581) where this
branch adds the two-phase parameters. Kept both — the parameter list now carries
activate/deployment_id/revert_on_failure/ignore_replication_errors/
deployment_timeout/two_phase AND credentials, followed by main's credentials
section. main's get_deployment_payload / delete_deployment_payload docs (#600)
are untouched.
Sign up for freeto 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.

3 participants

@kriszyp@dawsontoth@Ethan-Arrowood