You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Transform Mocker from a "parser-only facade" into honest Docker-compatible tooling. The core principle: every flag either works or explicitly errors, every command either does what Docker does or tells you it can't, and the Apple runtime is the source of truth -- not local JSON.
Codex Review Summary (Rev 1 → Rev 2 changes)
T3 replaced: warnings → fail-fast enforcement for unsupported flags
New T16: fake-but-not-stub commands (create, rename, pause, unpause) must be honest
T6 rewritten: runtime-first reconciliation, not just stale pruning
New T17: hostname parser fix as prerequisite to T4
T12 moved from Tier 3 → Tier 1, no docs-only escape hatch
T8 expanded to all docs + translations, "unsupported" label not "experimental"
New T18: ProcessRunner abstraction for testability
T14/T15 deferred to post-v0.2.0
Risk Matrix
Risk Category
Count
Severity
Priority
Shell injection
2 vectors
CRITICAL
Tier 0
Fake commands (metadata-only)
4 commands
HIGH
Tier 1
Silent flag ignoring
150+ flags
HIGH
Tier 1
Shadow state divergence
3 managers
HIGH
Tier 1
Credential echo + write-only auth
1 file
HIGH
Tier 1
Unimplemented commands in docs
14 stubs
MEDIUM
Tier 2
Test coverage (4%)
All engine code
MEDIUM
Tier 2
Version inconsistency
4 files
LOW
Tier 3
Tier Map
Tier 0 (Critical Security -- no dependencies, parallel eligible)
ID
Task
Risk
Files
Status
T1
Fix shell injection in copyToContainer
high
ContainerEngine.swift
done
T2
Fix shell injection in compose hostname injection
high
ComposeOrchestrator.swift
done
Tier 1 (Honesty Layer -- depends on Tier 0)
ID
Task
Risk
Depends On
Files
Status
T3
Unsupported flag enforcement (warnings for unsupported flags)
Definition: Line ~344 uses sh -c "cat > \(path)" with unescaped user input for both path and content. Replace with array-based argument passing using stdin pipe. The path and content must never be interpolated into a shell string.
Test: Write a test with path ; rm -rf /tmp/test and content containing MOCKER_EOF to verify no injection.
Definition: Line ~170 interpolates service hostnames into sh -c "printf ... >> /etc/hosts". Replace with exec-based approach using proper argument array. Also change try? to try with error propagation.
Test: Compose file with service name '; cat /etc/passwd; echo ' must not execute.
Definition: Create a shared compatibility matrix (enum or struct) that declares which flags are supported by the Apple runtime. In each command's run(), check if any unsupported flags were explicitly set by the user. If so, print a clear error to stderr and exit with code 1: Error: --gpus is not supported by Apple Containerization runtime. This is fail-fast, not warn-and-continue. Cosmetic-only flags (like --label which is stored in metadata) can warn instead of fail.
Test: mocker run --gpus all alpine must exit 1 with error message. mocker run --name test alpine must succeed.
Rollback: git checkout on each modified command file
T4: Forward implementable flags to ContainerEngine
Definition: Audit which flags Apple's container run --help actually accepts. Forward all supported ones: --hostname, --network, --platform, etc. Update ContainerEngine.run() argument array construction. Only forward flags that the Apple CLI actually processes -- do not forward flags that will be silently ignored by the subprocess.
Test: mocker run --hostname test-host alpine hostname should return test-host.
Definition: Make Apple runtime the source of truth. list() and inspect() query container list --format json first, then merge with local metadata (labels, port mappings etc). resolve() must check runtime before falling back to local JSON. When stale containers are detected during reconciliation, also clean up orphaned port proxy processes via PortProxy. Runtime-created containers (not created by Mocker) should appear in mocker ps with a [external] marker.
Test: Remove a mocker container via Apple CLI directly, verify mocker ps reflects removal. Create a container via Apple CLI, verify it appears in mocker ps.
Definition: Volumes: verify _data/ directory exists on list() and inspect(). Remove ghost entries. Networks: since these are metadata-only, add [metadata-only] qualifier in output and document the limitation.
Test: Delete volume's _data/ directory, verify mocker volume ls no longer lists it.
Definition: Three fixes: (1) Replace readLine() with terminal raw mode for password input (or at minimum document the echo limitation clearly). (2) Set ~/.mocker/config.json to 0600 permissions after write. (3) Either wire credentials into ImageManager pull/push calls OR replace login/logout with explicit unsupported error: Error: registry authentication is not yet supported. No middle ground -- "Login Succeeded" followed by auth never being used is the worst outcome.
Test: mocker login must either work end-to-end or exit with unsupported error.
Definition: Commands that lie by succeeding silently: (1) create calls run (starts the container). Either implement real create-without-start or error. (2) rename only edits JSON. Either delegate to runtime or error. (3) pause/unpause only flip metadata state. Either delegate to runtime or error. (4) compose create (line ~1183) delegates to up which starts containers. (5) compose pause/compose unpause (lines ~1361, ~1403) have the same metadata-only problem. All must either work against the runtime or error explicitly.
Test: mocker create alpine must NOT start the container (or must error). mocker compose pause must actually pause (or error).
Definition: fetchContainerInfo stores cfg["hostname"] as the container name (line ~436). This means forwarding --hostname in T4 will corrupt container identity. Fix the parser to correctly distinguish hostname from container name in Apple CLI inspect JSON output.
Test: Create container with --hostname custom-host --name mycontainer, verify mocker inspect mycontainer shows correct name AND hostname.
Definition: 14+ commands throw "not yet supported". Update ALL documentation: COMMANDS.md marks them [unsupported] (not "experimental"). README feature claims distinguish "full CLI flag parsing" from "full CLI behavior". Add a "Compatibility Notes" section explaining the Apple runtime limitations. Expand to docs/ directory and Chinese translations. Fix overclaiming: "Full Docker CLI compatibility" → "Docker CLI compatible (with Apple runtime limitations)".
Test: Grep all .md files for "unsupported" tags, verify count >= 14. Grep for "100%" or "full.*compatibility" and verify remaining claims are qualified.
Rollback: git checkout on all modified doc files
T18: Add ProcessRunner abstraction for testability + fix pipe deadlock
Definition: Two parts. (1) Extract a ProcessRunner protocol with func run(args:) async throws -> (String, Int32). Inject into ContainerEngine and ImageManager. Default implementation uses real Process, test implementation captures args and returns mock output. (2) Fix the process pipe deadlock: the current pattern reads stdout/stderr only after process termination (ContainerEngine line ~476, ImageManager line ~42). When output exceeds macOS pipe buffer (~64KB), the subprocess blocks and never exits. The ProcessRunner default implementation must read pipes concurrently with process execution, not after termination.
Test: swift build succeeds. Existing functionality unchanged. A mock test with >64KB output must not hang.
Definition: Using the ProcessRunner mock: test argument array construction from ContainerConfig (verify correct flags passed for each config field), test reconciliation logic (stale detection, port proxy cleanup), test resolve() prefers runtime over JSON.
Definition: Test that unsupported flags cause exit code 1. Test that supported flags produce correct ContainerConfig values. (Version consistency testing is in T13, not here.)
Definition: Create a single MockerVersion.current constant. Reference it everywhere. Currently Version.swift, MockerCLI.swift, System.swift say "0.1.0" while Compose.swift says "0.1.9".
Test: mocker version and mocker compose version print identical version strings.
Rollback: git checkout on all 4 files
Execution Risks (from Codex)
Port proxy orphans: Reconciliation must clean up stale port proxies, not just JSON entries
Breaking change: Switching ignored flags to fail-fast will break existing user scripts -- needs explicit release notes and migration guide
Apple CLI drift: Flag support may change independently of SPM dependency -- "audit once" can rot
Naming collisions: Showing runtime-created containers in mocker ps may create merge/naming issues
Process deadlock: Addressed in T18 (ProcessRunner reads pipes concurrently)