Skip to content

feat(config): add agentsync config command and [security] schema section - #185

Merged
chrisleekr merged 2 commits into
mainfrom
feat/config-foundation
Jun 20, 2026
Merged

feat(config): add agentsync config command and [security] schema section#185
chrisleekr merged 2 commits into
mainfrom
feat/config-foundation

Conversation

@chrisleekr

@chrisleekr chrisleekr commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Why

There was no way to change vault configuration without hand-editing agentsync.toml inside the vault clone — enabling an agent, tuning the daemon debounce, or (soon) setting secret-handling policy all meant editing TOML by hand and remembering to commit + push it. This PR adds a proper config surface and lays the schema foundation the next PR (secret-scanner) builds on.

Second PR in the key-lifecycle / discovery / daemon / configurability series (follows #184).

What

  • agentsync config list | get <key> | set <key> <value> — view or change config by dotted key (agents.vscode, sync.debounceMs, security.secretScan, …). set validates the mutated config against the full Zod schema (so an out-of-range debounce or a bad enum is rejected before anything is written), then — because agentsync.toml is shared across machines — reconciles fast-forward, commits, and pushes, exactly like key add.
  • [security] schema sectionsecretScan (standard/strict/off), allowSecretValues (string[]), redactBase64Values (bool), all optional with safe defaults. The schema is non-.strict(), so old agentsync.toml files load unchanged and no vault version bump is needed. The section is the config surface only — the push-time secret scanner starts honouring it in the follow-up PR (marked inert in the schema comment and docs so nobody is misled).
  • Protected sections (version, recipients, remote) are refused by config set; recipients stay under key, the remote stays at init.

Security

The review panel caught a reachable prototype-pollution path: config set security.__proto__.toLocaleString <value> passed the prefix + existence guards (the latter via the in operator walking the prototype chain) and would have written into Object.prototype before validation. Fixed by:

  • getByPath now uses Object.hasOwn (own-properties only), so a prototype-walk key reads as absent and is rejected as unknown-key before setByPath runs;
  • setByPath additionally refuses __proto__/constructor/prototype segments (defense-in-depth).
    A regression test asserts the key is refused and Object.prototype is untouched.

Tests

src/commands/__tests__/config.test.ts (12) + 3 schema back-compat tests: list/get/set, settable-prefix guard, unknown-key + schema-validation rejection, scalar coercion (number/bool/false/enum/array), prototype-pollution refusal, remote-landing assertion (change reaches the bare remote), and diverged-history fail-closed. Full suite: 922 pass / 0 fail.

CI note

bun test exits non-zero on the per-file coverage floor; CI treats 0-fail as success.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added config command to view and modify vault configuration without editing files directly
    • Introduced security configuration settings for secret-handling policy (scan modes, value allowlists, base64 redaction control)
    • Config supports list, get, and set subcommands with schema validation
  • Documentation

    • Updated README and command reference with config command details
  • Tests

    • Added comprehensive test coverage for config operations

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@chrisleekr, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 46 minutes and 24 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4be0a635-837d-4350-8d0c-de1d6843dd02

📥 Commits

Reviewing files that changed from the base of the PR and between 3a510aa and 37067ff.

📒 Files selected for processing (3)
  • docs/commands.md
  • src/commands/__tests__/config.test.ts
  • src/commands/config.ts
📝 Walkthrough

Walkthrough

Adds a security block (secretScan, allowSecretValues, redactBase64Values) to AgentSyncConfigSchema with back-compat defaults, introduces a new config list/get/set CLI subcommand that reads and mutates vault configuration using git-backed reconciliation and schema validation, wires it into the root CLI, and updates documentation and tests.

Changes

agentsync config command and security schema

Layer / File(s) Summary
Security schema block and init defaults
src/config/schema.ts, src/config/__tests__/schema.test.ts, src/commands/init.ts, src/test-helpers/fixtures.ts
Adds an optional security section to AgentSyncConfigSchema with secretScan (enum, default standard), allowSecretValues (default []), and redactBase64Values (default true). init.ts gains a DEFAULT_SECURITY constant and writes it during vault initialization. Schema tests verify back-compat defaulting, partial-field filling, and invalid-value rejection. The fixture helper is updated to include the security object.
config command core implementation
src/commands/config.ts
Introduces performConfigList (flattens vault config to sorted dotted key/value pairs, excluding version and recipients.*), performConfigGet (safe dotted-key lookup), and performConfigSet (settable-prefix gating, remote reconciliation via GitClient, prototype-pollution-safe path mutation via setByPath, schema validation, writeConfig, and git add/commit/push). Exports ConfigEntry, ConfigGetResult, ConfigSetResult types and the configCommand Citty definition with list, get, and set subcommands.
CLI wiring and documentation
src/cli.ts, README.md, docs/commands.md
Imports and registers configCommand in the root CLI's subCommands map. Adds a config row to the README commands table and a full ## config reference section to docs/commands.md covering settable keys, security.* not-yet-enforced caveat, set validation and commit behavior, and non-settable key caveats.
config command tests and integration test updates
src/commands/__tests__/config.test.ts, src/commands/__tests__/integration.test.ts
Adds a Bun test suite with real git fixtures covering list filtering, get success/missing, set type coercion (bool, number, enum, JSON array), protected-key rejection (version, recipients.*, remote.url), unknown-key rejection, schema validation failure with no vault mutation, prototype-pollution guard, remote push verification, and diverged-history failed status. Two existing integration tests are updated to include the security block in writeConfig calls.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • chrisleekr/agentsync#12: The new performConfigSet implementation calls GitClient.reconcileWithRemote for divergence detection and fast-forward reconciliation, which is the same reconciliation API introduced and wired through commands in this PR.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding a new agentsync config command and a [security] schema section for vault configuration management.
Description check ✅ Passed The PR description comprehensively covers all template sections: Why, What, Security, Tests, and CI notes. It details the new command, schema additions, security fixes, and test coverage.
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread src/commands/config.ts Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/__tests__/config.test.ts`:
- Around line 65-72: The restore() function that cleans up environment variables
and temporary directories is currently called manually at the end of each test,
which means cleanup is skipped if any assertion fails before that line. Wrap the
restore() function call in an afterEach hook at the test suite level to
guarantee cleanup runs unconditionally after every test, then remove all
individual await restore() calls from the end of each test function (such as
those at the end of the test cases in the file).

In `@src/commands/config.ts`:
- Around line 171-179: The performConfigSet function writes and pushes
user-supplied configuration values without sanitizing them for secrets, which
could expose literal secrets in git history. Before calling writeConfig with
validated.data, import and apply the sanitizer from src/core/sanitizer.ts to
check for hard never-sync patterns in the validated.data object. If the
sanitizer detects secrets or blocked patterns, abort the operation and throw an
error with clear guidance to the user explaining what sensitive content was
detected and how to fix it. Only proceed with writeConfig, git.addAll,
git.commit, and git.push if the sanitization passes successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bdf3daca-0282-499c-91c1-7ca9313c9daf

📥 Commits

Reviewing files that changed from the base of the PR and between 462b28e and 3a510aa.

📒 Files selected for processing (10)
  • README.md
  • docs/commands.md
  • src/cli.ts
  • src/commands/__tests__/config.test.ts
  • src/commands/__tests__/integration.test.ts
  • src/commands/config.ts
  • src/commands/init.ts
  • src/config/__tests__/schema.test.ts
  • src/config/schema.ts
  • src/test-helpers/fixtures.ts

Comment thread src/commands/__tests__/config.test.ts
Comment thread src/commands/config.ts
…g values for secrets

- inline literal guards before each setByPath assignment (CodeQL barrier)
- refuse literal credentials in plaintext config values (allowlist exempt)
- afterEach teardown in config tests for guaranteed cleanup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011L7s33UCjpQkreXW7amAw2
Sign up for free to 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.

2 participants