You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Decouples the secret mechanism from Blocks branding so @aws-blocks/hosting
stays a framework-neutral leaf that any consumer (a plain framework app, a
future standalone hosting package) can use. No behavior change for Blocks users.
@aws-blocks/hosting (neutral engine):
- secretParameterName(key, prefix?) now takes an injectable SSM prefix,
defaulting to a neutral DEFAULT_SECRET_PARAMETER_PREFIX = '/aws-hosting/secrets'
(was hardcoded '/blocks/secrets').
- env var prefix renamed BLOCKS_SECRET_PARAM_ -> HOSTING_SECRET_PARAM_
(internal wiring, framework-neutral).
- Stripped Blocks-specific wording from doc comments + runtime error messages.
@aws-blocks/core (Blocks namespace):
- New secret-naming.ts: BLOCKS_SECRET_PARAMETER_PREFIX='/blocks/secrets' +
blocksSecretParameterName() = neutral engine + Blocks prefix. Single place
Blocks pins its namespace.
- hosting-secrets.ts (CDK wiring) and scripts/secret.ts (CLI) now route through
blocksSecretParameterName(), so Blocks secrets still land at /blocks/secrets/<KEY>
-> NO SSM-path migration, Blocks users unaffected.
Why: making the engine brand-neutral now turns a future standalone-secret
extraction into a mechanical move instead of a breaking SSM-path migration.
Full extraction into a standalone package is deliberately deferred to the
standalone-hosting work.
Tests: neutral-default + injected-prefix + neutral-env assertions (hosting),
new secret-naming test (core), updated CDK integration assertion to
HOSTING_SECRET_PARAM_. hosting 708 / core 507 green.
Copy file name to clipboardExpand all lines: .changeset/hosting-secrets.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,9 +9,11 @@ Introduces a `secret()` reference for sensitive values (API keys, third-party cr
9
9
10
10
-**`secret('KEY')` marker** — exported from `@aws-blocks/hosting` (and re-exported from `@aws-blocks/core` / `@aws-blocks/blocks`). A dependency-free value object so it can later be shared with `@aws-blocks/pipeline` without a dependency cycle. Pass it into `Hosting` props.
11
11
-**Two resolution strategies, chosen per prop:**
12
-
-`compute.environment` values resolve at **runtime** (the secure default): the SSM parameter *name* (never the value) is injected as `BLOCKS_SECRET_PARAM_<KEY>`, the compute role is granted `ssm:GetParameter` (scoped to that one ARN) + `kms:Decrypt` (conditioned on `kms:ViaService`), and the value is fetched + decrypted on first use via `getSecret('KEY')`. The secret stays encrypted at rest and never enters the template.
12
+
-`compute.environment` values resolve at **runtime** (the secure default): the SSM parameter *name* (never the value) is injected as `HOSTING_SECRET_PARAM_<KEY>`, the compute role is granted `ssm:GetParameter` (scoped to that one ARN) + `kms:Decrypt` (conditioned on `kms:ViaService`), and the value is fetched + decrypted on first use via `getSecret('KEY')`. The secret stays encrypted at rest and never enters the template.
13
13
-`domain.domainName` and `secret(..., { exposeAsEnv: true })` resolve at **synth time** via an SDK `GetParameter(WithDecryption)` call and are inlined as literals. `ssm-secure` CloudFormation dynamic references are restricted to an allowlist that excludes CloudFront `Aliases` and Lambda env vars, so synth-time SDK resolution is the correct mechanism; a domain is public anyway. Synth-time resolution is async — use the new `await Hosting.create(scope, id, props)`.
14
14
-**`getSecret('KEY')` runtime resolver** — reads `process.env.KEY` first (local dev / `exposeAsEnv`), else fetches + decrypts the injected SSM parameter, caching per cold start and coalescing concurrent calls. Mirrors the existing `AppSetting` / external-DB connection-string pattern.
15
15
-**`secret` CLI** (`runSecretCli`, `setSecret`, `listSecrets`, `removeSecret`) — `blocks secret set/list/remove` manage SecureStrings at `/blocks/secrets/<KEY>` (flat namespace, 1:1 key↔reference, no stage scoping). `list` returns names only, never values. Wired into the Next.js template as `npm run secret`.
16
16
17
-
Path convention is centralized in `secretParameterName()` (`/blocks/secrets/<KEY>`), alongside the existing `/blocks/{stage}/db-connection-string`. Backward compatible: `new Hosting(...)` keeps working for plain config and runtime secrets; only synth-time secrets require `Hosting.create()`.
17
+
**Framework-neutral by design (decoupling).** The secret *mechanism* in `@aws-blocks/hosting` carries no Blocks branding: it defaults to a neutral `/aws-hosting/secrets` prefix (`DEFAULT_SECRET_PARAMETER_PREFIX`) and a neutral `HOSTING_SECRET_PARAM_` env prefix, and `secretParameterName(key, prefix?)` takes an injectable namespace. Blocks pins its own `/blocks/secrets` namespace in `@aws-blocks/core` (`blocksSecretParameterName`, `BLOCKS_SECRET_PARAMETER_PREFIX`), so Blocks users see **no change** while a non-Blocks consumer (a plain framework app, or a future standalone hosting package) never inherits Blocks paths. This keeps `@aws-blocks/hosting` a zero-`@aws-blocks/*`-deps leaf and makes a future extraction of the secret engine into a standalone package a mechanical move rather than a breaking SSM-path migration (which is deliberately deferred to that extraction).
18
+
19
+
Path convention for Blocks is centralized in `blocksSecretParameterName()` (`/blocks/secrets/<KEY>`), alongside the existing `/blocks/{stage}/db-connection-string`. Backward compatible: `new Hosting(...)` keeps working for plain config and runtime secrets; only synth-time secrets require `Hosting.create()`.
0 commit comments