Skip to content

Phase 3: Container extraction - #5

Closed
james-in-a-box[bot] wants to merge 7 commits into
mainfrom
jib/phase-3-container
Closed

Phase 3: Container extraction#5
james-in-a-box[bot] wants to merge 7 commits into
mainfrom
jib/phase-3-container

Conversation

@james-in-a-box

@james-in-a-box james-in-a-box Bot commented Feb 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase 3 of the egg extraction: extract container Dockerfiles and scripts.

Changes

Gateway container (container/gateway/):

  • Dockerfile with Squid proxy and Python environment
  • entrypoint.sh for startup
  • squid.conf (restrictive) and squid-allow-all.conf (permissive)
  • allowed_domains.txt for domain allowlist

Sandbox container (container/sandbox/):

  • Dockerfile with development tools
  • entrypoint.py for container initialization
  • scripts/git - Git wrapper routing through gateway
  • scripts/gh - GitHub CLI wrapper routing through gateway
  • bin/git-credential-github-token - Credential helper

Parameterization

Original (james-in-a-box) Extracted (egg)
/home/jib /home/sandbox
jib-gateway egg-gateway
JIB_* env vars EGG_* env vars
jib-isolated network egg-isolated network

Validation Plan

# 1. Checkout the branch (after merging PR #4)
git fetch origin
git checkout jib/phase-3-container

# 2. Verify container directory structure
ls -la container/gateway/
# Expected: Dockerfile, entrypoint.sh, squid.conf, squid-allow-all.conf, allowed_domains.txt

ls -la container/sandbox/
# Expected: Dockerfile, entrypoint.py

ls -la container/sandbox/scripts/
# Expected: git, gh (executable scripts)

ls -la container/sandbox/bin/
# Expected: git-credential-github-token

# 3. Check for jib references that should be egg
grep -rn "jib-gateway" container/ || echo "No jib-gateway refs (good)"
grep -rn "/home/jib" container/ || echo "No /home/jib refs (good)"
grep -rn "JIB_" container/ || echo "No JIB_ env vars (good)"
# Expected: No matches

# 4. Verify egg references exist
grep -rn "egg-gateway" container/sandbox/scripts/git | head -3
grep -rn "EGG_SESSION_TOKEN" container/sandbox/scripts/git | head -3
# Expected: Should find egg-gateway and EGG_SESSION_TOKEN references

# 5. Verify scripts are executable concepts (check shebang)
head -1 container/sandbox/scripts/git
head -1 container/sandbox/scripts/gh
# Expected: #!/bin/bash or similar

# 6. Verify Dockerfiles have correct base images
head -5 container/gateway/Dockerfile
head -5 container/sandbox/Dockerfile
# Expected: FROM python:3.11-slim or similar

# 7. Run linting (entrypoint.py should pass)
./dev native lint
# Expected: All checks passed

# 8. Run tests
./dev native test
# Expected: 4 tests pass

Authored-by: jib

Implement Phase 1 of the egg extraction plan:

- Create repository structure with gateway/, sandbox/, cli/, shared/, tests/
- Add pyproject.toml with uv for dependency management
- Add GitHub Actions workflows (lint.yml, test.yml)
- Add ./dev wrapper script for CI parity (runs act locally)
- Add pre-commit configuration
- Add Dependabot configuration
- Write README.md with architecture overview
- Write CONTRIBUTING.md with development guidelines
- Add egg.yaml.example and secrets.yaml.example
- Create module structure with __init__.py files
- Add initial unit tests for module imports
- Add docs/testing.md and docs/architecture.md

This establishes the infrastructure before extracting gateway code in Phase 2.

Authored-by: jib
Extract and create documentation for the egg repository:

- docs/security.md: Core security model and threat mitigations
- docs/adr/git-isolation-architecture.md: Git worktree isolation ADR
- docs/adr/credential-injection.md: Credential injection ADR
- docs/configuration.md: Configuration reference
- docs/setup.md: Setup guide
- docs/api.md: Gateway API reference
- docs/troubleshooting.md: Common issues and solutions

Security documentation extracted from james-in-a-box ADRs:
- ADR-Gateway-Credential-Injection.md
- ADR-Git-Isolation-Architecture.md
- ADR-Anthropic-API-Credential-Injection.md

All docs regenerated for egg (no james-specific references).

Authored-by: jib
Add core shared modules:
- shared/egg_config/loader.py: YAML config loading with env var expansion
- shared/egg_config/validators.py: Config validation utilities
- shared/egg_logging/logger.py: Structured JSON/console logging

Add first gateway module:
- gateway/policy.py: Policy engine for branch ownership and access control
  - Parameterized for egg (configurable bot_name, branch_prefix)
  - Removed james-in-a-box specific references
  - Uses EGG_TRUSTED_USERS instead of GATEWAY_TRUSTED_USERS

Remaining Phase 2 tasks:
- Port session_manager, git_client, github_client, worktree_manager
- Port remaining supporting modules
- Port gateway.py Flask app
- Port test files

Authored-by: jib
Port gateway sidecar modules from james-in-a-box:
- git_client.py: Git CLI wrapper with path/arg validation
- github_client.py: gh CLI wrapper with token management
- session_manager.py: Thread-safe session storage with disk persistence
- policy.py: Branch ownership and PR policy enforcement
- rate_limiter.py: Sliding window rate limiting
- worktree_manager.py: Git worktree lifecycle management
- token_refresher.py: GitHub App token refresh
- repo_parser.py: URL/path parsing for repo identification
- repo_visibility.py: GitHub API visibility queries with caching
- private_repo_policy.py: Per-session private/public mode enforcement
- fork_policy.py: Fork operation restrictions
- error_messages.py: User-friendly error messages
- config_validator.py: Startup configuration validation
- proxy_monitor.py: Squid proxy traffic monitoring
- repo_config.py: Per-repo authentication mode configuration
- gateway.py: Main Flask REST API server

Also adds:
- scripts/parse-git-mounts.py for repository mount parsing
- pyproject.toml hatch build config for packages
This adds the sandbox and gateway container definitions:

Sandbox container (container/sandbox/):
- Dockerfile: Ubuntu 22.04 base with development tools, Python 3.11
- entrypoint.py: Container initialization and user setup
- scripts/git: Git wrapper routing through gateway sidecar
- scripts/gh: GitHub CLI wrapper routing through gateway
- bin/git-credential-github-token: Git credential helper

Gateway container (container/gateway/):
- Dockerfile: Python 3.11 slim base with Squid proxy
- entrypoint.sh: Starts Squid proxy and gateway API server
- squid.conf: Restrictive config for private mode (api.anthropic.com only)
- squid-allow-all.conf: Permissive config for public mode
- allowed_domains.txt: Domain allowlist for private mode

Key parameterization changes from james-in-a-box:
- /home/jib -> /home/sandbox
- jib-gateway -> egg-gateway
- jib user -> sandbox user
- JIB_* env vars -> EGG_* env vars
- /opt/jib-runtime -> /opt/egg-runtime

Authored-by: jib
@jwbron
jwbron changed the base branch from main to jib/phase-2-gateway February 2, 2026 22:06
@james-in-a-box james-in-a-box Bot changed the title Add Phase 3 container files Phase 3: Container extraction Feb 2, 2026
@jwbron
jwbron force-pushed the jib/phase-2-gateway branch from df4e5a4 to 3fcfb7d Compare February 2, 2026 23:44
@jwbron
jwbron changed the base branch from jib/phase-2-gateway to main February 3, 2026 07:13
@james-in-a-box

james-in-a-box Bot commented Feb 3, 2026

Copy link
Copy Markdown
Contributor Author

Review Finding: Superseded by PR #48

This PR has been analyzed against PR #48 (comprehensive implementation). All functionality from this PR is included in PR #48 with improvements.

Comparison

Component PR #5 PR #48 Status
Gateway Dockerfile ✅ Enhanced (git config, CA cert generation) Superseded
Gateway entrypoint.sh ✅ Enhanced Superseded
squid.conf ✅ Enhanced (MITM/cert config) Superseded
squid-allow-all.conf ✅ Same core logic Superseded
allowed_domains.txt ✅ Improved comments Superseded
Sandbox Dockerfile ✅ Enhanced (beads, Claude Code, docker-setup.py) Superseded
Sandbox entrypoint.py ✅ Rewritten with more features Superseded
git/gh wrapper scripts ✅ Present Superseded
git-credential-github-token ❌ Not needed Superseded by design (gateway handles tokens)

Recommendation

Safe to close. PR #48 includes all container infrastructure from this PR with the following improvements:

  • CA certificate generation scripts
  • DH parameter generation at build time
  • Beads task tracker installation
  • Claude Code CLI installation
  • docker-setup.py for configurable package installation
  • Enhanced Squid SSL certificate handling
  • Security fixes (shell injection, UID/GID validation)

— Authored by jib

james-in-a-box Bot pushed a commit that referenced this pull request Feb 6, 2026
Gap #4 (cmd[2:2] fragility): Add LIFECYCLE_FLAGS_INDEX constant to make
the implicit contract explicit. Callers now reference the module constant
instead of hardcoding the magic number. Added a test that verifies the
constant value, so changes to the builder's structure will fail tests.

Gap #5 (container_ip): run_claude_structured() now allocates a static IP
for test containers via _allocate_test_container_ip(). This matches
production where sessions are bound to specific container IPs for request
verification.

Gap #3 (public mode E2E): Created issue #168 to track adding E2E test
coverage for public mode container launches.

Authored-by: egg
jwbron added a commit that referenced this pull request Feb 6, 2026
* Extract shared build_sandbox_docker_cmd() for container launches

Container-launch command construction was duplicated across three call
sites (run_claude, exec_in_new_container, E2E conftest), causing
divergence bugs like missing --add-host and wrong env var names.
The test harness was also missing PRIVATE_MODE, DNS lockdown, proxy
config, RUNTIME_UID/GID, CONTAINER_ID, and --security-opt.

This extracts a single build_sandbox_docker_cmd() into a new
shared/egg_container module that all three sites now call, with 26
unit tests covering private/public mode, optional params, and the
caller insertion conventions.

* Fix ruff format issues

* Address review feedback: add ANTHROPIC_AUTH_METHOD and document coupling

Addresses two gaps from the audit review:

1. Tests now set ANTHROPIC_AUTH_METHOD=oauth to match production behavior.
   Production callers always set this env var (api_key or oauth), but the
   test was only passing ANTHROPIC_OAUTH_TOKEN. This ensures sandbox
   startup code branches the same way in tests as in production.

2. Added docstring to run_claude_structured() documenting the network
   config coupling. The test constructs ContainerNetworkConfig manually
   from EggStack values rather than calling _get_container_network_config().
   If that function changes, the test must be updated to match.

Authored-by: egg

* Address review gaps #4 and #5, create issue for #3

Gap #4 (cmd[2:2] fragility): Add LIFECYCLE_FLAGS_INDEX constant to make
the implicit contract explicit. Callers now reference the module constant
instead of hardcoding the magic number. Added a test that verifies the
constant value, so changes to the builder's structure will fail tests.

Gap #5 (container_ip): run_claude_structured() now allocates a static IP
for test containers via _allocate_test_container_ip(). This matches
production where sessions are bound to specific container IPs for request
verification.

Gap #3 (public mode E2E): Created issue #168 to track adding E2E test
coverage for public mode container launches.

Authored-by: egg

---------

Co-authored-by: egg <egg@example.com>
Co-authored-by: jwbron <8340608+jwbron@users.noreply.github.com>
james-in-a-box Bot pushed a commit that referenced this pull request Feb 7, 2026
Fix critical issues from review:
- Task ID convention mismatch: Parser now generates task-{phase}-{number}
  format matching CLI expectations (Issue #3)
- Integer parsing vulnerability: Added parse_task_id() and parse_phase_id()
  helpers with proper validation and error handling (Issue #1)
- URL parameter injection: Use urllib.parse.urlencode for query params (Issue #2)
- Placeholder task numbering: Use task_number=1 instead of 0 (Issue #5)
- Silent failure in shell script: gh_api_safe now sets GH_API_FAILED flag
  and returns empty JSON for graceful fallback (Issue #6)

Additional improvements:
- Updated Task model pattern to accept task-P-N format
- Added comprehensive test coverage for error paths
- Added edge case tests for plan parser
- All 73 tests pass, ruff linter clean

Authored-by: egg
jwbron added a commit that referenced this pull request Feb 7, 2026
* Implement Phase 3: Agent CLI and prompt integration

Add the agent-facing components for the SDLC pipeline:

- Contract CLI (egg-contract) for agents to interact with contract state:
  - show: Display current contract state
  - add-commit: Link commits to tasks
  - update-notes: Add implementation notes
  - mark-task/mark-phase: Update status (reviewer role)
  - add-decision: Create HITL decision points

- Agent rules file (contract.md) with CLI usage guidance

- Document templates for refine and plan phases:
  - analysis.md: Problem analysis template
  - plan.md: Implementation plan template with task ID format

- SDLC prompt builder that provides phase-specific context and
  instructions to the agent

- Plan parser for extracting tasks from plan documents:
  - Parses [TASK-X-Y] patterns from markdown
  - Supports YAML front matter for structured task definitions
  - Generates placeholder tasks for empty phases
  - Produces warnings for parse issues

- Unit tests for plan parser and contract CLI

Issue: #133

Authored-by: egg

* Fix bash syntax error in build-sdlc-prompt.sh

Change the inner heredoc delimiter in the PR format example from 'EOF'
to 'BODY' to avoid conflicting with the outer heredoc delimiter. The
'EOF' on line 363 was being interpreted as the end of the outer heredoc
(starting at line 322), causing a syntax error on the closing ')'.

Authored-by: egg

* Fix lint and type errors in Phase 3 contracts code

- Fix import sorting in shared/egg_contracts/__init__.py (I001)
- Fix import sorting in tests/sandbox/test_contract_cli.py (I001)
- Fix unused variable in tests/sandbox/test_contract_cli.py (F841)
- Fix import sorting and remove unused import in tests/shared/egg_contracts/test_plan_parser.py (I001, F401)
- Fix mypy type annotation in shared/egg_contracts/plan_parser.py
- Fix mypy no-any-return errors in sandbox/egg_lib/contract_cli.py
- Apply ruff formatting fixes

Authored-by: egg

* Address code review feedback for Phase 3 implementation

Fix critical issues from review:
- Task ID convention mismatch: Parser now generates task-{phase}-{number}
  format matching CLI expectations (Issue #3)
- Integer parsing vulnerability: Added parse_task_id() and parse_phase_id()
  helpers with proper validation and error handling (Issue #1)
- URL parameter injection: Use urllib.parse.urlencode for query params (Issue #2)
- Placeholder task numbering: Use task_number=1 instead of 0 (Issue #5)
- Silent failure in shell script: gh_api_safe now sets GH_API_FAILED flag
  and returns empty JSON for graceful fallback (Issue #6)

Additional improvements:
- Updated Task model pattern to accept task-P-N format
- Added comprehensive test coverage for error paths
- Added edge case tests for plan parser
- All 73 tests pass, ruff linter clean

Authored-by: egg

* Remove unused GH_API_FAILED variable from build-sdlc-prompt.sh

The GH_API_FAILED variable was declared and set but never read,
triggering shellcheck SC2034 warning. The variable has been removed
as the functionality was never implemented.

Authored-by: egg

* Address remaining PR review feedback

- Fix add-decision RBAC: Add decisions.* to FIELD_OWNERSHIP with
  IMPLEMENTER role, allowing implementers to create decisions while
  only humans can resolve them.

- Fix array append in validator: Handle appending to arrays when
  idx == len(array) by appending instead of raising IndexError.
  Also handle the case in apply_mutation where old_value doesn't
  exist yet for append operations.

- Document race condition in add-decision: Added comments explaining
  the TOCTOU race condition between reading decision count and
  submitting mutation. Gateway should handle conflicts.

- Fix mark-task/mark-phase role documentation: Updated docstrings
  and help text to clarify these operations require REVIEWER role.

- Add commit SHA validation: New validate_commit_sha() function
  validates 7-40 character hex strings for git SHAs.

- Fix short question ellipsis: Only append "..." if question is
  longer than 50 characters.

- Add comprehensive tests for new functionality including commit
  SHA validation and array append operations.

Authored-by: egg

* Fix ruff format issue in contract_cli.py

Collapse multi-line ValueError string to single line to satisfy
ruff format requirements.

Authored-by: egg

* Address low-severity review feedback

- Add integration tests verifying plan parser task IDs are compatible
  with the CLI's parse_task_id() function
- Add RETURN trap in gh_api_safe() to clean up temp files on interruption
- Refactor MockGatewayHandler to use a factory function that creates
  handler classes with isolated responses, ensuring thread safety when
  running tests in parallel
- Generate unique HEREDOC delimiter using random suffix to prevent
  injection if issue body contains the delimiter string

Authored-by: egg

---------

Co-authored-by: jwbron <8340608+jwbron@users.noreply.github.com>
Co-authored-by: james-in-a-box[bot] <246424927+james-in-a-box[bot]@users.noreply.github.com>
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.

1 participant