Skip to content

docs: define the single-image single-stack isolation contract - #37

Merged
eXPerience83 merged 9 commits into
mainfrom
docs/single-stack-architecture
Jul 29, 2026
Merged

docs: define the single-image single-stack isolation contract#37
eXPerience83 merged 9 commits into
mainfrom
docs/single-stack-architecture

Conversation

@eXPerience83

Copy link
Copy Markdown
Owner

Summary

Document the accepted Remote Dev target architecture before changing the runtime:

  • one user-installed Remote Dev App or Compose stack;
  • one final image digest reused by the launcher and every agent service;
  • one primary browser entry point;
  • one isolated service per enabled coding agent;
  • private credentials, histories, GitHub state, SSH keys and workspaces per agent service;
  • no Docker socket, privileged child containers or agent secrets in the launcher;
  • Codex retained as the current reference implementation;
  • Antigravity planned as an explicit vendor-sourced optional service;
  • Claude preserved as a future path only.

Scope

Documentation and architectural decisions only. This PR does not implement the launcher, add services, change Compose, remove Bubblewrap or publish a new runtime image.

Changes

  • replace the earlier child-image architecture with the single-App/single-image/isolated-service contract;
  • record the superseding decisions in the decision log;
  • distinguish shared immutable tools from service-private state;
  • align the roadmap and README while clearly marking the current edge image as Codex-specific;
  • record the architecture and the latest merged upstream pins in the changelog.

Validation

Addresses #24.

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

Please verify the architecture contract for internal consistency, distinguish current behavior from planned behavior, flag contradictions with existing documentation, and check Markdown quality. Do not suggest runtime implementation changes in this documentation-only PR unless the documentation would otherwise promise unsupported behavior.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2015d7027

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/architecture.md Outdated
Comment thread docs/decisions.md
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== PR metadata and changed files ==='
git status --short
git diff --name-status HEAD^ HEAD
echo
echo '=== Diff (documentation changes) ==='
git diff --unified=80 HEAD^ HEAD -- '*.md' '*.mdx' '*.markdown' || true
echo
echo '=== Markdown/document inventory ==='
fd -HI -t f -e md -e mdx -e markdown . | sort
echo
echo '=== Contract-related references outside changed docs ==='
rg -n -i -C 3 \
  'child[- ]image|single[- ]image|single[- ]stack|launcher|bubblewrap|docker socket|privileged|codex|antigravity|claude|isolat(ed|ion)|agent service|remote dev' \
  -g '*.md' -g '*.mdx' -g '*.markdown' . || true
echo
echo '=== Markdown tooling/configuration ==='
fd -HI -t f '(^|/)(\.markdownlint.*|markdownlint.*|package\.json|\.remarkrc.*|remark\.config\..*)$' . -x sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {} \; || true
echo
echo '=== Markdown links in changed files ==='
git diff --name-only HEAD^ HEAD -- '*.md' '*.mdx' '*.markdown' \
  | while IFS= read -r file; do
      echo "--- $file"
      rg -n '\[[^]]+\]\([^)]+\)|<https?://[^>]+>|https?://[^[:space:])>]+' "$file" || true
    done

Length of output: 60618


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
echo "=== Merge base: $base ==="
echo "=== Full PR changed files ==="
git diff --name-status "$base"...HEAD
echo
echo "=== Full PR stats ==="
git diff --stat "$base"...HEAD
echo
echo "=== Architecture-document diff ==="
git diff --unified=30 "$base"...HEAD -- \
  README.md README.es.md PROJECT_STATUS.md CHANGELOG.md \
  docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md \
  docs/security.md docs/releases.md
echo
echo "=== Final focused documents with line numbers ==="
for file in README.md CHANGELOG.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md PROJECT_STATUS.md; do
  if [ -f "$file" ]; then
    echo "--- $file"
    nl -ba "$file"
  fi
done
echo
echo "=== Referenced issues and compatibility/image terminology ==="
rg -n -C 2 \
  '(issue|Issue) #(24|25|31|36)|codex-remote-dev|remote-dev-base|child image|child-image|one final image|same final image|current (edge|development image|Codex deployment)|not implemented|planned|future' \
  README.md README.es.md CHANGELOG.md PROJECT_STATUS.md docs || true
echo
echo "=== Markdown structural checks ==="
python3 - <<'PY'
from pathlib import Path
import re

files = [p for p in Path(".").rglob("*.md") if ".git" not in p.parts]
for p in sorted(files):
    text = p.read_text(encoding="utf-8")
    issues = []
    if not text.endswith("\n"):
        issues.append("missing final newline")
    fences = len(re.findall(r"(?m)^```", text))
    if fences % 2:
        issues.append(f"unbalanced fenced-code markers ({fences})")
    for n, line in enumerate(text.splitlines(), 1):
        if len(line) > 120 and not re.match(r"^\s*\|", line):
            issues.append(f"line {n} exceeds 120 columns ({len(line)})")
    if issues:
        print(f"{p}: " + "; ".join(issues))

print("Relative Markdown-link targets missing:")
for p in sorted(files):
    text = p.read_text(encoding="utf-8")
    for n, target in enumerate(re.findall(r"\[[^\]]*\]\(([^)\s]+)(?:\s+\"[^\"]*\")?\)", text), 1):
        if target.startswith(("#", "http://", "https://", "mailto:")):
            continue
        clean = target.split("#", 1)[0]
        if clean and not (p.parent / clean).exists():
            print(f"{p}: {target}")
PY

Length of output: 39670


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="fee981e46d0c157dca446c02bf5e0bb3f99f3674"

echo '=== Final modified documents with portable line numbers ==='
for file in CHANGELOG.md README.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md; do
  echo "--- $file"
  awk '{ printf "%6d\t%s\n", NR, $0 }' "$file"
done

echo
echo '=== Pin/source-of-truth comparison (base vs HEAD) ==='
for file in versions.env mise.lock Dockerfile; do
  if [ -f "$file" ]; then
    echo "--- $file"
    git diff --unified=3 "$base"...HEAD -- "$file" || true
    rg -n 'CODEX|MISE|UV|PYTHON|0\.146\.0|2026\.7\.16|0\.12\.0' "$file" || true
  fi
done

echo
echo '=== Tracking issue metadata ==='
for issue in 24 25 31 36; do
  echo "--- #$issue"
  gh issue view "$issue" --repo eXPerience83/remote-dev-containers \
    --json number,title,state,url,body \
    --jq '"#\(.number) [\(.state)] \(.title)\n\(.url)\n\(.body[0:500])"' \
    || echo "Unable to read issue #$issue"
done

echo
echo '=== Markdown structural and relative-link checks ==='
python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("CHANGELOG.md"), Path("README.md"), Path("docs/architecture.md"),
    Path("docs/decisions.md"), Path("docs/roadmap.md"), Path("docs/tool-matrix.md")
]
for p in files:
    text = p.read_text(encoding="utf-8")
    errors = []
    fence_count = len(re.findall(r"(?m)^[ \t]*```", text))
    if fence_count % 2:
        errors.append(f"unbalanced fenced code blocks: {fence_count}")
    headings = [m.group(1) for m in re.finditer(r"(?m)^(#{1,6})\s+\S", text)]
    jumps = [(i, len(headings[i - 1]), len(h)) for i, h in enumerate(headings[1:], 1)
             if len(h) > len(headings[i - 1]) + 1]
    if jumps:
        errors.append(f"heading-level jumps: {jumps}")
    for index, line in enumerate(text.splitlines(), 1):
        if line.rstrip() != line:
            errors.append(f"trailing whitespace at line {index}")
    print(f"{p}: " + ("OK" if not errors else "; ".join(errors)))

print("Missing relative link targets:")
missing = False
for p in files:
    for match in re.finditer(r"\[[^\]]*\]\(([^)\s]+)", p.read_text(encoding="utf-8")):
        target = match.group(1)
        if target.startswith(("https://", "http://", "mailto:", "#")):
            continue
        path = target.split("#", 1)[0]
        if path and not (p.parent / path).exists():
            missing = True
            print(f"{p}: {target}")
if not missing:
    print("none")
PY

echo
echo '=== Ambiguous present-tense target claims ==='
rg -n -i -C 1 \
  '\b(is|are|uses|use|receives|receive|runs|run|contains|contain|must|will)\b' \
  README.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md \
  | rg -i -C 2 'launcher|antigravity|claude|agent service|final image|stack|target|current|planned|future' || true

Length of output: 52941


@eXPerience83 Full review complete — no actionable findings.

The documentation is internally consistent across the README, architecture contract, decision log, roadmap, tool matrix, and changelog:

  • The current edge deployment is consistently described as the Codex-specific reference implementation.
  • The launcher, role-neutral image, isolated services, Antigravity integration, and Claude path are clearly marked as target/planned work tracked by #24, #25, #31, and #36.
  • The single-digest/single-stack contract, service-private state boundaries, launcher restrictions, and no-Docker-socket/privileged-child-container constraints agree throughout.
  • The changelog pin statements match versions.env.
  • Markdown checks passed for the changed files: balanced fences, heading structure, trailing whitespace, and relative links.
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@eXPerience83, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 65a55346-7c15-46be-961b-8f41e9337318

📥 Commits

Reviewing files that changed from the base of the PR and between a2015d7 and d48d109.

📒 Files selected for processing (3)
  • PROJECT_STATUS.md
  • README.md
  • docs/architecture.md

Walkthrough

The PR replaces the previous architecture documentation with a Remote Dev contract covering a shared immutable image, isolated launcher and agent services, security boundaries, migration requirements, validation assertions, and an updated implementation roadmap.

Changes

Remote Dev architecture

Layer / File(s) Summary
Target topology and shared image contract
README.md, docs/architecture.md, docs/decisions.md, CHANGELOG.md
Documents the accepted single-image, single-stack model with a launcher, fixed service roles, and one shared final image digest.
Persistence, security, and agent distribution
docs/architecture.md, docs/decisions.md, docs/tool-matrix.md, README.md, CHANGELOG.md
Defines isolated workspaces and state, launcher restrictions, TrueNAS container boundaries, update behavior, and optional-agent installation rules.
Migration, validation, and delivery milestones
docs/architecture.md, docs/roadmap.md
Adds Codex migration requirements, deployment and isolation assertions, non-goals, and milestones for the launcher, optional agents, and stable release.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • #24 — The PR documents the single-image, isolated-service architecture described by this issue.
  • #25 — The PR formalizes the target architecture and launcher security boundaries for this issue.
  • #31 — The PR aligns the roadmap and architecture documentation with this issue’s implementation plan.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed El título resume bien el cambio principal: el contrato de aislamiento de una sola imagen y un solo stack.
Description check ✅ Passed La descripción cubre resumen, alcance, cambios y validación; aunque faltan secciones explícitas, el contenido esencial está presente.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/single-stack-architecture

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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