Skip to content

Follow-up: bin/agent-coord duplicates three policy/validation code paths that must stay in sync #178

Description

@justin808

Surfaced by review of #105 (head 70bc6b6). Three independent reviewer findings describe the same shape: bin/agent-coord hand-rolls the same logic in more than one place, so a future fix has to be applied twice or thrice to stay correct. None of these are defects today — they are divergence risks in a file whose whole purpose is a security boundary, which is exactly where silent drift is most expensive.

Deliberately excluded from #105: that PR is already a ~2400-line security-sensitive change tripping the autonomous-merge changed-lines-limit, and pure refactors of pre-existing code would widen the blast radius of a diff that needs careful human review. Filed here so the cleanup is not lost.

1. validate_resolved_directory_chain! duplicates validate_secure_directory_chain!s component walk

#105 (comment)

Both split an expanded path into components, walk from /, and call validate_secure_directory_component! per component with the same leaf computation. The only real difference is that validate_secure_directory_chain! also handles symlink resolution/creation and calls into validate_resolved_directory_chain! after resolving. Since the latter is only ever invoked from inside the former, the walk-and-check loop could be one shared helper parameterized by "handle symlinks or not", instead of two near-identical ~15-line copies. A future change to how leaf is computed would need applying twice — precisely the TOCTOU-prone divergence this code is hardened against elsewhere.

2. validate_config_api_url! duplicates HttpStore#parse_base_urls URL policy

#105 (comment)

Both implement: scheme must be http/https with a non-empty host; no query or fragment; plain http rejected unless the hostname is in LOOPBACK_HOSTS. validate_config_api_url! even reaches into HttpStore::LOOPBACK_HOSTS to share the constant, but reimplements the surrounding logic and uses a different error type (Error vs OperationalError). If the loopback/https policy changes in one place — say a new trusted loopback alias — nothing signals that the other needs the same update, so agent-coord config set --api-url could accept a URL the HTTP backend later rejects at request time, or vice versa.

Note this already bit once: #105 needed a separate "Fix IPv6 loopback URL validation" commit (25121dc8) touching both sides.

3. Three reimplementations of the same cli > process_env > user_config precedence chain

#105 (comment)

effective_config_value, the effective_backend_env_value / process_selects_backend? / backend_env_source group, and effective_policy each resolve the same tiered precedence differently. effective_config_value treats an empty string as unset via .to_s.empty?; effective_backend_env_value returns raw values including empty strings, forcing callers like resolve_backend_env to separately normalize (env_api = nil if env_api == ""); effective_policy folds a fourth policy_file tier inline rather than composing. A precedence or empty-string change made in one is not guaranteed to be mirrored in the other two.

The empty-string inconsistency here is not hypothetical — it is the root of the --state-root "" and config show --backend "" reports also raised against #105.

Proposed fix

Factor each cluster into one shared implementation. Best done as a standalone refactor PR with no behavior change, so the diff is reviewable as pure restructuring and the existing suite acts as the regression net.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Priority: first group for useful backlog reduction and concrete product quality work.agent-claimedAgent lane claim mirror (hint, not a lock)complexity:simplifyRemoves code, duplicated rules, states or maintenance obligations. Not a merge-readiness verdict.triage:simplify-nextFocused simplification after overlapping work is resolved; reduce code and obligations.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions