feat(agent-config): overlay validation, config diff and display helpers [5/21] - #326
gusfcarvalho wants to merge 2 commits into
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Large arrays can produce misleading change counts, and the credential-sanitization path lacks regression coverage.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds reusable agent-configuration validation, structural diffing, and display utilities for the future Configuration tab.
Changes:
- Adds client-side overlay validation and scalar coercion.
- Adds structural and element-level configuration diffing.
- Adds display helpers and unit tests.
| File | Description |
|---|---|
src/utils/agent-config/validation.ts |
Validates overlays and detects masked values. |
src/utils/agent-config/display.ts |
Adds sanitization and formatting helpers. |
src/utils/agent-config/config-diff.ts |
Computes structural configuration differences. |
src/utils/agent-config/__tests__/validation.spec.ts |
Tests validation and coercion. |
src/utils/agent-config/__tests__/display.spec.ts |
Tests relative-time formatting. |
src/utils/agent-config/__tests__/config-diff.spec.ts |
Tests configuration and array diffing. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (n * m > LCS_LIMIT) { | ||
| for (let k = 0; k < Math.max(n, m); k++) { | ||
| if (k < n && k < m && deepEqual(before[k], after[k])) { | ||
| steps.push({ op: 'eq', i: k, j: k }); |
There was a problem hiding this comment.
Fixed in a5066a0. arrayElementChanges matches the common prefix and suffix before the LCS, so a single insertion, removal or edit aligns exactly at any size in linear memory. Only a middle that is still larger than the limit falls back to index by index. Regression test: 600 vs 601 items with an insertion at the front and in the middle, a removal and an edit.
| export function sanitizeForDisplay<T>(doc: T): T { | ||
| if (!isPlainObject(doc)) return doc; | ||
| const out = clone(doc) as ConfigDoc; | ||
| if (isPlainObject(out.api) && isPlainObject(out.api.auth)) { | ||
| delete out.api.auth.client_secret; | ||
| } | ||
| return out as T; |
There was a problem hiding this comment.
Fixed in a5066a0. display.spec.ts now checks that api.auth.client_secret is removed from the returned copy, that the input document is unchanged, that a plugin config key named client_secret is kept, and that documents without api.auth or non-objects pass through.
0b7a0cb to
ca212ff
Compare
| * The client-only checks of an overlay (R89). Blocking issues disable Review & save and the | ||
| * live preview. | ||
| */ | ||
| export function validateOverlayClientSide(overlay: OverlayDoc): ClientIssue[] { |
There was a problem hiding this comment.
[Blocker] Infinity, NaN and huge numbers in policy_data are sent as null, deleting the key
Introduced in #326 (also reachable through #337 PolicyDataSection.vue:182 onInput and #335 RawOverlayDialog via yaml.ts parseYaml). The raw JSON view goes from JSON.parse straight to diffOps without the hasUnstorableNumber check that parseNewValue uses, and the raw YAML dialog loads .inf/.nan (CORE_SCHEMA) as Infinity/NaN. Neither this validator, opsSetNullKey nor maskedPointers looks at numbers, and jsonBody (JSON.stringify) writes non-finite numbers as null, which RFC 7396 treats as a delete. Raw JSON {"limit": 1e999} over a base with limit: 5 saves {"policy_data":{"limit":null}}, removing limit on every host. Integers above 2^53 are silently rounded (12345678901234567890 becomes 12345678901234567000). The review dialog renders the in-memory Infinity (SavePreviewPanel.vue:375), so the user is never shown the deletion.
Why: A value the user typed is turned into a delete of that key on every instance, with no warning anywhere in the flow.
Fix: Reject non-finite numbers and integers outside Number.isSafeInteger in validateOverlayClientSide (blocking issue at the pointer), and run the same hasUnstorableNumber check in PolicyDataSection onInput. Add specs for 1e999, .inf, .nan and a 20-digit integer in both raw views.
Severity basis: no rule matched; decision tree: security, data or released-contract risk.
ccf-review · 2babb07b8736 · rules@6be9e11b8bc6
There was a problem hiding this comment.
Fixed across the stack:
- feat(agent-config): overlay validation, config diff and display helpers [5/21] #326 a5066a0:
validateOverlayClientSideblocks any number that cannot be saved as typed (not finite, or an integer past 2^53) at its pointer, in every field. That disables Review & save for the draft, whichever view produced it. - feat(agent-config): policy_data model and minimal merge patches [7/21] #328 f12948f:
policy-data.tsreuses the sameisStorableNumber. - feat(agent-config): structured policy_data tree editor [16/21] #337 7af204d: the raw policy_data JSON view refuses such numbers in
onInputbeforediffOps, with a spec in feat(agent-config): plugin summary card [17/21] #338 (0fad0b6) for1e999and a 20-digit integer. - feat(agent-config): JSON merge-patch, JSON pointer, overlay ops and YAML helpers [2/21] #323 c157be1: the raw YAML dialog rejects
.inf/.nanand 20-digit integers at parse time (specs inyaml.spec.ts).
Since the draft can no longer hold Infinity, the review dialog never renders one.
Layer 5 of 21 in the stacked split of #318. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eir common ends - validateOverlayClientSide blocks Infinity, NaN and integers past 2^53 anywhere in the overlay: JSON.stringify writes non-finite numbers as null, which RFC 7396 reads as deleting the key on every host - arrayElementChanges matches the common prefix and suffix before the LCS, so one insertion in an array past the LCS limit is still one addition (regression test at 600 x 601) - sanitizeForDisplay spec: client_secret removed from the copy only - plugin-name cases join the agentconfig conformance table Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ca212ff to
a5066a0
Compare


Part 5 of 21 of the stacked split of #318 (agent remote configuration). Every layer adds the final version of its files from #318, and only imports from layers below it, so each layer passes
make reviewableon its own. Nothing is reachable in the app until layer 20 wires the Configuration tab in.What
Overlay validation (shape, schedule, policy sources), a structural config diff used by the save preview, and display formatting helpers.
Tests
Unit specs for each.
🤖 Generated with Claude Code