Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5746f22
feat(management): stage one-use recovery epoch persistence (#2824)
kitamura-tetsuo Nov 12, 2026
faab920
fix(management): poison epoch after conflicting reserved binding
kitamura-tetsuo Nov 12, 2026
5accde9
feat(management): compose original provenance and current recovery ep…
kitamura-tetsuo Nov 12, 2026
355143f
test(management): exercise native recovery refusals and publication b…
kitamura-tetsuo Nov 12, 2026
8849652
test(management): require complete native recovery acceptance scenarios
kitamura-tetsuo Nov 12, 2026
69b6eed
test(management): close native recovery oracle gaps
kitamura-tetsuo Nov 12, 2026
de0c156
fix(management): preserve strict recovery fixture profiles
kitamura-tetsuo Nov 12, 2026
9d6df50
test(management): verify the consumed epoch before dispatch
kitamura-tetsuo Nov 12, 2026
bab6281
fix(management): release completed SQLite observations
kitamura-tetsuo Nov 12, 2026
080bd7c
fix(management): finalize native fixture producers before recovery
kitamura-tetsuo Nov 12, 2026
b767f2b
fix(management): retain the complete original database profile
kitamura-tetsuo Nov 12, 2026
7e86de9
fix(workspace): keep patch capture from refreshing the caller index
kitamura-tetsuo Nov 12, 2026
25d8e19
fix(management): preserve original authenticated readback stores
kitamura-tetsuo Nov 12, 2026
fd141ff
test: retain real scheduling in concurrent owner cancellation
kitamura-tetsuo Nov 12, 2026
4dbab24
fix(management): retain bounded refusal cause diagnostics
kitamura-tetsuo Nov 12, 2026
b97d168
fix(test): stabilize native recovery Docker route catalog
kitamura-tetsuo Nov 12, 2026
65b1cc2
fix(test): observe fresh readiness after authenticated readback
kitamura-tetsuo Nov 12, 2026
db3e3d7
fix(management): separate recovery approval from unrelated cgroups
kitamura-tetsuo Nov 12, 2026
f56a851
fix(management): bind retained masked watcher sources
kitamura-tetsuo Nov 12, 2026
87c41a7
fix(test): retain causal containment refusal diagnostics
kitamura-tetsuo Nov 12, 2026
fd062ab
fix(test): start readiness budget after verified child launch
kitamura-tetsuo Nov 12, 2026
fb1fc14
fix(test): inhibit scheduled cleanup before native recovery
kitamura-tetsuo Nov 12, 2026
d9d8e9d
fix: preserve evidence across management observation races
kitamura-tetsuo Nov 12, 2026
65c2ac8
Stabilize recovery VM housekeeping before route approval
kitamura-tetsuo Nov 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions .github/workflows/management-recovery-epoch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
name: Management Recovery Epoch Acceptance

'on':
pull_request:

permissions:
contents: read
actions: read

concurrency:
group: ${{ github.workflow }}-pr-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
acceptance-plan:
name: Select the complete native recovery acceptance matrix
runs-on: ubuntu-24.04
timeout-minutes: 10
outputs:
scenarios: ${{ steps.scenarios.outputs.scenarios }}
steps:
- name: Checkout exact reviewed source
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Setup Python
uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "0.7.22"
- name: Install locked test dependencies
run: uv sync --locked --dev --extra test
- name: Select every independent production scenario
id: scenarios
run: |
.venv/bin/python -B - <<'PY'
import json
import os
from scripts.test_management_recovery_epoch_host import ACCEPTANCE_SCENARIOS, required_cases

assert len(ACCEPTANCE_SCENARIOS) == len(set(ACCEPTANCE_SCENARIOS))
assert all(required_cases(scenario) for scenario in ACCEPTANCE_SCENARIOS)
with open(os.environ["GITHUB_OUTPUT"], "a") as stream:
stream.write("scenarios=" + json.dumps(ACCEPTANCE_SCENARIOS) + "\n")
PY
recovery-epoch:
name: Recovery epoch (${{ matrix.scenario }}) in isolated VM
needs: acceptance-plan
runs-on: ubuntu-24.04
timeout-minutes: 150
strategy:
fail-fast: false
max-parallel: 4
matrix:
scenario: ${{ fromJSON(needs.acceptance-plan.outputs.scenarios) }}
env:
UV_LOCKED: "1"
PYTHONDONTWRITEBYTECODE: "1"
RECOVERY_FIXTURE: /var/tmp/ac-recovery-vm-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.scenario }}
APPROVED_AUTHORIZATION_ID: ci-recovery-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.scenario }}
RECOVERY_SCENARIO: ${{ matrix.scenario }}
steps:
- name: Checkout exact reviewed source
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "0.7.22"
- name: Install locked test dependencies
run: uv sync --locked --dev --extra test
- name: Inspect the actual guest acceleration device
run: |
set -euo pipefail
if test -c /dev/kvm; then
stat --format='KVM device: %n mode=%a uid=%u gid=%g' /dev/kvm
else
echo 'No KVM device: the fresh QEMU guest will use bounded software CPU emulation.'
fi
- name: Build and verify exact installed management image
run: uv run python scripts/prepare_management_test_image.py
- name: Prepare the approved fresh recovery VM
env:
FIXTURE_READ_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
umask 077
token_file="$RUNNER_TEMP/recovery-source-read-token"
trap 'rm -f "$token_file"' EXIT
printf '%s' "$FIXTURE_READ_TOKEN" > "$token_file"
docker pull caddy:2
manager_id="$(docker image inspect --format '{{.Id}}' "$AUTOCODER_FRESH_TEST_BASE_IMAGE")"
caddy_id="$(docker image inspect --format '{{.Id}}' caddy:2)"
bash scripts/recovery_vm/prepare.sh "$RECOVERY_FIXTURE" "$APPROVED_AUTHORIZATION_ID" "$manager_id" "$caddy_id" "$token_file" "$RECOVERY_SCENARIO"
- name: Build bounded QEMU runner
run: docker compose --env-file "$RECOVERY_FIXTURE/compose.env" build
- name: Run actual original producers, containment and one-shot issuer
timeout-minutes: 125
run: |
set -euo pipefail
docker compose --env-file "$RECOVERY_FIXTURE/compose.env" run --rm fixture
- name: Remove the ephemeral read credential
if: always()
run: |
rm -f "$RUNNER_TEMP/recovery-source-read-token"
rm -f "$RECOVERY_FIXTURE/input/source-token"
- name: Retain bounded native acceptance diagnostics
if: always()
uses: actions/upload-artifact@v7
with:
name: management-recovery-epoch-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.scenario }}
path: /var/tmp/ac-recovery-vm-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.scenario }}/output/
if-no-files-found: error
retention-days: 7
verifier-omission-control:
name: Detect omitted post-consumption verification in isolated VM
needs: acceptance-plan
runs-on: ubuntu-24.04
timeout-minutes: 150
env:
UV_LOCKED: "1"
PYTHONDONTWRITEBYTECODE: "1"
RECOVERY_FIXTURE: /var/tmp/ac-recovery-vm-${{ github.run_id }}-${{ github.run_attempt }}-verifier-omission-control
APPROVED_AUTHORIZATION_ID: ci-recovery-${{ github.run_id }}-${{ github.run_attempt }}-verifier-omission-control
RECOVERY_SCENARIO: post-receipt-ready-mutation
steps:
- name: Checkout exact reviewed source
uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "0.7.22"
- name: Install locked test dependencies
run: uv sync --locked --dev --extra test
- name: Inspect the actual guest acceleration device
run: |
set -euo pipefail
if test -c /dev/kvm; then
stat --format='KVM device: %n mode=%a uid=%u gid=%g' /dev/kvm
else
echo 'No KVM device: the fresh QEMU guest will use bounded software CPU emulation.'
fi
- name: Build and verify exact installed management image
run: uv run python scripts/prepare_management_test_image.py
- name: Prepare the approved fresh recovery VM
env:
FIXTURE_READ_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
umask 077
token_file="$RUNNER_TEMP/recovery-source-read-token"
trap 'rm -f "$token_file"' EXIT
printf '%s' "$FIXTURE_READ_TOKEN" > "$token_file"
docker pull caddy:2
manager_id="$(docker image inspect --format '{{.Id}}' "$AUTOCODER_FRESH_TEST_BASE_IMAGE")"
caddy_id="$(docker image inspect --format '{{.Id}}' caddy:2)"
bash scripts/recovery_vm/prepare.sh "$RECOVERY_FIXTURE" "$APPROVED_AUTHORIZATION_ID" "$manager_id" "$caddy_id" "$token_file" "$RECOVERY_SCENARIO" omit-post-consumption-verifier
- name: Build bounded QEMU runner
run: docker compose --env-file "$RECOVERY_FIXTURE/compose.env" build
- name: Detect the exact omitted verifier with the unchanged native oracle
timeout-minutes: 125
run: |
set -euo pipefail
docker compose --env-file "$RECOVERY_FIXTURE/compose.env" run --rm fixture
- name: Remove the ephemeral read credential
if: always()
run: |
rm -f "$RUNNER_TEMP/recovery-source-read-token"
rm -f "$RECOVERY_FIXTURE/input/source-token"
- name: Retain the distinct mutation-control evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: management-recovery-epoch-${{ github.run_id }}-${{ github.run_attempt }}-verifier-omission-control
path: /var/tmp/ac-recovery-vm-${{ github.run_id }}-${{ github.run_attempt }}-verifier-omission-control/output/
if-no-files-found: error
retention-days: 7
acceptance:
name: Management Recovery Epoch Acceptance
needs: [acceptance-plan, recovery-epoch, verifier-omission-control]
if: always()
runs-on: ubuntu-24.04
timeout-minutes: 2
steps:
- name: Require every native scenario to succeed
env:
PLAN_RESULT: ${{ needs.acceptance-plan.result }}
ACCEPTANCE_RESULT: ${{ needs.recovery-epoch.result }}
MUTATION_CONTROL_RESULT: ${{ needs.verifier-omission-control.result }}
run: |
test "$PLAN_RESULT" = success
test "$ACCEPTANCE_RESULT" = success
test "$MUTATION_CONTROL_RESULT" = success
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ RUN groupadd --gid 65532 auto-coder-worker && useradd --uid 65532 --gid 65532 --
COPY --from=python-environment /opt/auto-coder/.venv /opt/auto-coder/.venv
ENV PATH="/opt/auto-coder/.venv/bin:/home/node/.opencode/bin:${PATH}"
# Embed the trusted build input so the installed artifact reports it without Docker/Git/network access.
RUN python -m auto_coder.build_provenance embed
RUN python -B -m auto_coder.build_provenance embed
COPY --from=build /usr/local/bin/opencode /usr/local/bin/opencode
COPY --from=build /usr/local/bin/codex /usr/local/bin/codex
WORKDIR /workspace
Expand Down
11 changes: 11 additions & 0 deletions docs/client-features/management-current-containment-observation.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,17 @@ fresh reads. A process running a scheduler outside its normal service also
refuses. This initial profile conservatively refuses unrelated masked services
that retain work as well.

A process or thread may disappear while the complete procfs inventory is read.
Only disappearance independently confirmed by a fresh PID/TID inventory, or a
changed complete inventory, permits a retry. At most three attempts are made;
each discards the incomplete pair and reads two new complete matching
source/controller/cgroup/task snapshots. Earlier protected source, controller,
boot and mask bindings remain refusal anchors across attempts. A still-listed
process or thread with missing evidence, an empty live task inventory, permission
or malformed-data errors, changed protected facts, and any positively observed
inhibited task or scheduler still refuse immediately. No task is skipped to
complete a positive observation, and persistent inventory churn remains unavailable.

A detected remaining task has a typed refusal at the route boundary. Its public
diagnostic contains fixed text and a bounded validated controller-scope identifier
so an independent consumer can distinguish the canonical and differently named
Expand Down
4 changes: 4 additions & 0 deletions docs/client-features/management-fresh-initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ container profiles with the expected mounts are accepted. The evidence file is
created once in the new owner-only guard directory. Access errors are refusal,
including inability to inspect an old process namespace.

Supervisor-ledger observations close their read-only SQLite connections after
each read, including refusals. They retain no database handle beyond that check;
the owner fences and namespace descriptors have their separate required lifetimes.

The host commands accept only explicit, private files and exact container IDs:

```sh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ its current fences; it must separately decide whether that explicitly bounded
coverage supplies the history its own contract requires. Neither enrollment
nor a matching evidence object supplies recovery or launch authority.

The separate `ordinary-original-genesis-v1` profile described in
[Original ordinary deployment genesis and retained lineage](management-original-genesis.md)
adds an affirmative original root-creation and ordinary first-launch baseline.
It uses `ordinary-original-history-v1` authority and the independent
`derive_lineage`/`verify_lineage` API. It does not change this prospective-only
profile's pre-enrollment gap or convert any earlier deployment.

## Original producer and lifetime

An operator must separately provision a new canonical mode-0700 history directory
Expand Down
Loading
Loading