Dynamic Review: package the engine and document safe operation
Maintainers usually reply within 1 day
A pull request for this has already been merged.
- #230 by @Schacki-Jr — merged
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- docker, github-actions, typescript
- Domain
- devops, documentation, infrastructure, security
Research direction
Start with the dependency issue #201 and design record #120, then read runner/Dockerfile, runner job_loop/settings, capability preflight, and the license and smoke-test files listed in the issue. Check TESTING.md and existing runner and deployment docs to understand implemented behavior before changing them. Done means the pinned offline runner, fail-closed capability behavior, documented limits and operational gates meet the acceptance criteria, with the final release checklist recording the required evidence and blockers.
Written by the indexing model from the issue text.
Description
Goal
Operators can install, configure and troubleshoot Dynamic Review with reproducible binaries, existing workspace secrets and explicit limits.
Scope
Package unmodified stock anomalyco/opencode v1.19.0, Git and required bundled runtime/helpers with release/source/checksum pins and notices from merged #85 write-up. Do not package bubblewrap, a fork, review-mode patch or engine policy plugin. No floating latest, runtime curl/npm install, model-catalog fetch or repo plugin/dependency discovery. Bun is embedded in the release; do not add a separate runtime without a verified need. Initial Linux amd64 glibc pin: upstream source 733b2c627e5aec39cb33cc22373bdce33053ef2c, asset opencode-linux-x64.tar.gz, archive SHA-256 7bb9e61ad6feacf2e89c10a6a2c1840e3de4220bb50ba1fc7110f31806076aec. Other architectures require their own artifacts/checksums; do not reuse this digest or generate a patched artifact.
Runner-container isolation uses a dedicated unprivileged OpenCode OS user separate from credential-bearing runner duties, verified export ownership/write denial, private per-job HOME/XDG/auth/config/cache/scratch, and actual network access only to the job's runner-owned model proxy. Describe how secrets and parent-process state are made unreadable and other-job/control/proxy endpoints inaccessible. No host home/repository data is baked into the image. Keep a simple fail-closed startup self-check of the actual engine user, read-only export mechanism and proxy-only network; per-job launch verifies concrete export/state. No bubblewrap/user-namespace checks, host sandbox profiles, sysctl/LSM/seccomp tuning that existed solely for bwrap, privileged/SYS_ADMIN fallback or deployment on this dev host. Document supported Docker/Coolify deployment targets instead.
Missing/failed prerequisites mean no opencode capability advertised, while PR-Agent-only workers still process Diff jobs. Document a slim PR-Agent-only option without requiring #130. A successful binary --version alone does not prove isolation or network. #197/#202 prove the effective boundary; #82 remains the additional hosted egress gate, not permission for unrestricted self-hosted agent egress.
Document unchanged operator-owned resource bounds from #193, deadline clamping, validation, cleanup/disk layout, secret-filter limitations and accepted nested AGENTS.md injection. The core marks repository content untrusted and the engine has no write/exec/general-network capability; no guarantee of model resistance. Preserve the spike's plugin-execution failure as research evidence and prove sanitized stock jobs do not import those payloads. Run bounded worst-case whole-job/cgroup memory and cleanup tests before selecting Dynamic concurrency; spike sampled RSS is not a capacity guarantee. No invented quality/prices/latency claims.
Reuse the current encrypted workspace BYOK service. Stay model/provider-agnostic, default deepseek-v4.1-flash, with operator-supplied compatible configuration; no pinned OpenRouter hosting provider or provider-specific routing code/options. Unsupported required tool calls/structured output fails with dynamic_model_features_unsupported, no silent fallback. No new LLM key env variable, per-project/shared secret, native-provider credential flow or provider UI. Only placeholder .env.example files may be read/edited for non-secret limit variables. Never read/create another .env* file.
Rollout records completed #85 research, #197 external-boundary/accounting proof, #199 lossless-state gate, stock response-codec compatibility and #82 hosted gate. Only automatic review, /review and Review now exist; #203 owns related cleanup/history, not an unresolved decision or added dependency. Future repository execution still requires #130 plus #82.
Acceptance criteria
- Image has reproducible stock pins and offline --version/self-check; source/asset checksums match the unmodified release. No repository plugin/config execution or dependency installation. No bubblewrap/userns/patch/host-profile prerequisite.
- Existing /licenses includes exact OpenCode/Codex/Google/PR-Agent provenance/required notices; binary dependencies are audited by make check-licenses or a documented equivalent integrated into it, not hidden from the check.
- Actual stock OpenCode job under the dedicated unprivileged uid proves sanitized export, effective write/exec denial, unreadable credentials/parent secret state, inaccessible other-job data/control endpoints, proxy-only network and process-group/temp cleanup. No root/bwrap diagnostic substitutes for the actual deployed boundary.
- PR-Agent-only runner never advertises opencode; Dynamic jobs remain waiting for capable capacity, with documented diagnosis.
- Document model, skill editing/reset, workspace credentials, limits, errors, no automatic fallback, switching/cancel semantics and operational rollout/gates.
- Validate invalid/zero/negative/oversized limit config before claiming; hard maxima cannot be widened by project or PR text. Distinguish context window from cumulative consumed tokens.
- README, runner/README, review-settings/runner-api/fakes docs and TESTING.md describe implemented behavior only; add a short architecture decision record.
- Release checklist records merged #85 evidence (not a blocker), external stock-engine limits/network/accounting/codec proof, #82 hosted gate and remaining #199 state/capacity/quality questions. Command policy is resolved; coordinate #203 cleanup. No unsafe capability advertised while required boundary proof is missing.
Files / modules
runner/Dockerfile and ignore files, pinned binary manifest/install helper and checksum/license metadata; runner job_loop/settings and capability preflight; .env.example placeholders only when necessary; compose.yml / compose.coolify.yml examples only where configuration is required; docker/smoke/runner.sh; app/src/ci image/compose/license guards; README.md, runner/README.md, docs/decisions and deployment docs; NOTICE, THIRD_PARTY_LICENSES.md, TESTING.md and fakes docs.
Test cases
| ID | kind | level | case | expected |
|---|---|---|---|---|
| #202-T01 | happy | image smoke | Built runner image checks unmodified pin offline under dedicated unprivileged engine user | Exact release/source/artifact/checksum and licenses; effective user/read-only/proxy boundary; no runtime downloads/bwrap/patch |
| #202-T02 | security | image smoke | Stock Dynamic job with hostile repo plugin/config and model requests write/exec/credential read/direct external or other-job network | Discovery payload stripped and sentinel never executes; unsafe operations denied; no secrets or surviving helper/process/job temp directory |
| #202-T03 | regression | image smoke | PR-Agent-only option with existing Diff job | Diff works; opencode not advertised; no unsupported claim |
| #202-T04 | error | unit | Missing tooling and invalid limits/model config | Actionable stable preflight/config code; no unsafe capability or unbounded job |
| #202-T05 | happy | unit | Parse defaults and lower overrides with existing worker timeout | Epic limits match code/docs; minimum applicable deadline wins |
| #202-T06 | security | integration | License/provenance and image tracked-secret scans | Required notices present; no key/token/env/checkout data in image |
| #202-T07 | happy | manual | Follow Docker/Coolify guide/checklist on documented deployment target (not current dev host) | Container/dedicated-user/read-only/proxy checks pass without userns/kernel/profile tuning; generic model config/current BYOK; #85 completed evidence and #82 hosted gate recorded |
| #202-T08 | regression | unit | Existing CI/Docker/compose configuration guards | New non-secret knobs documented in .env.example; no PR_AGENT_COMMAND override in production |
| #202-T09 | security | image smoke | Startup self-check with missing/wrong engine user, writable export mechanism or unrestricted network | Fail closed; no opencode advertised/claimed; actionable stable isolation error; Diff-only capacity remains valid |
| #202-T10 | edge | image smoke | Bounded worst-case job reaches export/model-content envelope and documented Dynamic slot limit; injected OOM/kill | Whole-job/cgroup peaks measured, concurrency recommendation recorded; failure preserves prior state and reaps owned processes/temp files |
Out of scope
#82 firewall implementation, #130 push target/container scheduler, real-model benchmark execution, a new LLM provider/account UI, OpenCode fork/patch/plugin development, bubblewrap/userns/host-profile work and increasing unmeasured budgets.
Dependencies
Depends on #201.
Part of #193. Design record: #120.
Test-first; test IDs belong in comments above tests, never titles. No real model/network calls; follow TESTING.md and keep existing tests. One PR into development; make verify must be green.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 1
- Avg merge
- 1h 18m
- Merged PRs (30d)
- 186
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ExpidetGames/code-reviewer
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ExpidetGames/code-reviewer#308 ·
Maintainers usually reply within 1 day
-
type: docs
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#94 ·
Maintainers usually reply within 1 day
-
area: app post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 12/100
ExpidetGames/code-reviewer#339 ·
Maintainers usually reply within 1 day
-
area: runner post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 18/100
ExpidetGames/code-reviewer#338 ·
Maintainers usually reply within 1 day
-
area: runner post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 12/100
ExpidetGames/code-reviewer#337 ·
Maintainers usually reply within 1 day
All issues in ExpidetGames/code-reviewer
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
melgarafael/DeskcommCRM#3000 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
callstackincubator/simlock#639 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
aws/agentcore-cli#2606 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 7 days
-
ai-driven-qa bug Cosmetic
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 1 day