fix: Phase 3h script_service + server_service

F3h-01 script_service._build_kill_command: shlex.quote(log_path) wraps the
       path in single-quotes; embedding that inside "..." produced a filename
       with literal single-quote chars that cat/kill could not find.
       Fix: use the shlex-quoted string directly without extra double-quotes.

F3h-02 script_service._substitute_db_vars: non-atomic string replacement
       allowed nested substitution when a credential value contained another
       $DB_* pattern. Fix: replace with null-byte sentinels first, then
       substitute actual values in a second pass.

server_service.push_to_servers: add comment documenting that audit_repo and
       retry_repo are None (internal compat shim — not used by routes).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name
2026-05-23 15:50:44 +08:00
parent c3c3bae370
commit 86bb32f87e
2 changed files with 31 additions and 12 deletions
@@ -100,11 +100,15 @@ class ServerService:
from server.application.services.sync_service import SyncService
# Build a SyncService sharing our existing repos + the extra ones it needs
# NOTE: audit_repo and retry_repo are None here — this method is a compatibility
# shim for internal callers only. Do NOT call sync_service.batch_push() methods
# that invoke self.audit_repo or self.retry_repo, or they will raise AttributeError.
# API routes should use SyncService directly via Depends(get_sync_service).
sync_service = SyncService(
server_repo=self.server_repo,
sync_log_repo=self.sync_log_repo,
audit_repo=None, # audit handled by caller if needed
retry_repo=None, # retry handled by caller if needed
audit_repo=None,
retry_repo=None,
)
return await sync_service.batch_push(
server_ids=server_ids,