(feat) Secret store harness - #19
Merged
Merged
Conversation
Signed-off-by: Whit Waldo <whit.waldo@innovian.net>
There was a problem hiding this comment.
🟡 Changes recommended
Address the unresolved moderate findings in DaprContainer and SecretStoreHarness before approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds local-file-backed Dapr secret-store support and a SecretStoreHarness for integration testing.
Changes:
- Adds secret-store validation, serialization, and file helpers.
- Integrates stores with
DaprContainerand exposes harness APIs. - Adds tests, fixtures, exports, and documentation.
File summaries
| File | Summary | Final review comments |
|---|---|---|
src/SecretStoreHarness.ts |
Dapr Secrets testing harness | Moderate (1): align missing-key behavior with documentation. Moderate (1): model or reject nested multi-valued results. Nit (1): add end-to-end multi-valued retrieval coverage. |
src/SecretStoreHarness.test.ts |
Harness integration tests | — |
src/SecretStore.ts |
Secret-store configuration and utilities | — |
src/SecretStore.test.ts |
Secret-store unit tests | — |
src/index.ts |
Public API exports | — |
src/DaprContainer.ts |
Secret-store registration and file provisioning | Moderate (3): prevent duplicate component names. Moderate (1): handle reserved kvstore/pubsub names. |
src/Constants.ts |
Default secret-store name | — |
src/__fixtures__/dapr-resources/secrets.json |
Secret fixture data | — |
README.md |
Secret-store usage documentation | Nit (1): fix the standalone example’s missing network setup. |
Review details
Suppressed comments (5)
README.md:101
- This standalone snippet references
networkwithout importing or creating it. SinceDaprContainer.start()requires a configured network, copying the example either fails TypeScript compilation or throws at runtime; add theNetworksetup/cleanup or show the harness-based approach instead.
const dapr = new DaprContainer()
.withNetwork(network)
.withSecretStore({ secrets: { alpha: "one" } })
.withSecretStore({ name: "second-store", secrets: { beta: "two" } });
src/DaprContainer.ts:461
- A store named
kvstoreorpubsubis currently overwritten at startup:beforeContainerCreatedadds those fallback components whenever no state/pubsub component exists (src/DaprContainer.ts:233-240), then the resource-writing loop writes the fallback YAML to the same/dapr-resources/<name>.yamlpath after this component. Reject these reserved names or make the generated fallback names collision-safe.
this.secretStores.push(resolved);
this.components.push(resolved.component);
src/SecretStoreHarness.ts:35
- The new
multiValuedoption is only covered by checking that metadata containsmultiValued: true; none of the integration tests retrieves a multi-valued secret. Since this option changes the response shape whilegetSecretValueand the public casts assume flat string maps, add an end-to-end assertion forgetSecret/getBulkSecretsso a runtime shape or handling regression cannot pass the suite.
/** When true, nested secrets are returned as multi-valued secrets rather than flattened. */
multiValued?: boolean;
src/SecretStoreHarness.ts:185
- The
@returnsdocumentation promisesundefinedfor a missing key, butgetSecretpropagates Dapr's not-found exception; the direct-container test inSecretStoreHarness.test.ts:184demonstrates thatsecret.getrejects for a missing secret. Catch only the not-found case (or change the return type and documentation), rather than leaving callers with a rejection contrary to this public contract.
* @returns The secret value, or undefined if not present.
*/
public async getSecretValue(key: string): Promise<string | undefined> {
const secret = await this.getSecret(key);
return secret?.[key];
src/SecretStoreHarness.ts:185
- With
multiValued: true, a top-level nested secret can be returned as an object, sosecret?.[key]may be an object even though this method promisesstring | undefined(andgetSecretdeclares all values as strings). The exported API is therefore unsound for an option this PR exposes; model the multi-valued response or explicitly reject/returnundefinedfor object values.
public async getSecretValue(key: string): Promise<string | undefined> {
const secret = await this.getSecret(key);
return secret?.[key];
- Files reviewed: 9/9 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+454
to
+456
| if (this.secretStores.some((s) => s.name === resolved.name)) { | ||
| throw new Error(`A secret store component named "${resolved.name}" has already been registered`); | ||
| } |
Resolve README and package export conflicts while preserving the secret store, pub/sub, and state management additions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Whit Waldo <whit.waldo@innovian.net>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adding support for a secret-store harness using local files
Issue reference
We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
Please reference the issue this PR will close: #[issue number]
Checklist
Please make sure you've completed the relevant tasks for this PR, out of the following list: