feat(provider): add dictionaryFromJson sync type - #44
Open
adrien-barret wants to merge 1 commit into
Open
Conversation
ESS can now create a CPLN dictionary secret from a single source secret
containing a JSON object — leaf values become dot-notation keys in the
dictionary. Removes the need to enumerate keys in sync.yaml when the
schema is unknown or evolving.
When the source value is not a parseable JSON object (raw string,
array, scalar, or malformed JSON), ESS falls back to a single-key
dictionary {__raw: <value>} instead of throwing. This avoids type-flip
delete/recreate cycles on transient bad pushes.
- Schema: dictionaryFromJson (string) added to SecretSchema
- New util: flattenJson(obj) → flat dict with dot paths
- Provider: branch in getSecret() handles fetch + parse + fallback
- 17 unit tests for flatten + tryParseJsonObject + schema validation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Adds a new sync type
dictionaryFromJson: <secret-path>that creates a Control Plane dictionary secret from a single source secret whose value is a JSON object. Leaf values are exposed under dot-notation keys, so consumers can reference nested fields via standard CPLN dot-notation (cpln://secret/<name>.<dot.path>).Motivation
We have a setup where:
dictionarywith flat keys.The existing options didn't cover this:
opaquedictionarywith explicit{KEY: {path, parse}}dictionaryFromProject: true(GCP)dictionaryFromJsonfills the gap: ESS fetches the source secret, parses its value as JSON, recursively walks the object, and exposes each leaf as a flat dot-path key in the resulting dictionary.Example
GCP secret
catalog-async-prodcontains:{ "db": { "user": "admin", "pass": "s3cret" }, "api_key": "abc123" }sync.yaml:
Result — CPLN dictionary secret
catalog-async-prod:Consumers can now use
cpln://secret/catalog-async-prod.db.user.Fallback behavior
If the source value cannot be parsed as a JSON object (raw string, JSON array, scalar, or malformed JSON), ESS falls back to a single-key dictionary
{ __raw: <raw-value> }instead of throwing. This avoids type-flip delete/recreate cycles when a dev pushes a transient bad value, and surfaces the issue clearly in the CPLN UI under the__rawkey.Implementation
src/config/syncConfig.ts— adddictionaryFromJson: z.string().nonempty()toSecretSchema, include in thexorrefinement and inisDictionarySecret.src/provider/util/flatten.ts— new utility withflattenJson()(recursive dot-path walk) andtryParseJsonObject()(safe parse with object-root guard).src/provider/provider.ts— new branch ingetSecret()andcheckSecret(); arrays are JSON-stringified to keep dict values as strings.src/sync/sync.ts— no changes needed; existingisDictionarySecret()path handles it.flatten.spec.tsandsyncConfig.spec.ts.Test plan
npm run buildpasses (TypeScript compiles)npx jest src/provider/util/flatten.spec.ts— 14 tests passnpx jest -t "dictionaryFromJson"— schema validation passesnpx jest -t "rejects multiple sync types"— xor refinement passesHappy to iterate on naming (
dictionaryFromJsonvsdictionaryFromJsonSecretvs something else), behavior (throw vs fallback), and depth limits if you have preferences.