Experiment formal browser delegated registration source plan 01 - kmosoti/FabricO11y GitHub Wiki

Delegated browser ownership registration: prospective source preflight01

This is prospective; no command has run. Root is sole serial executor; source stays held until actual registration red is published. Review is not executed evidence.

{
  "status": "NOT RUN; exact Pip/Wren pre-flight pending",
  "created_utc": "2026-10-13T06:18:37.736641+00:00",
  "source_head": "90cdf680d23769acb8fc20fda9cf15818d6549a2",
  "source_tree": "96c2e0b9d3350719f4ba1dd1c5e09a38ce6bb76c",
  "source_status": "clean",
  "coordination_scope": "C-084",
  "outer_command": [
    "python3",
    "-B",
    "/run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-browser-delegated-registration-01.py",
    "browser-delegated-registration-red-01",
    "1073741824",
    "env",
    "PYTHONPATH=tools/ui",
    "python3",
    "-B",
    "-m",
    "unittest",
    "-v",
    "test_role_matrix.BrowserFixtureCleanupTests",
    "test_role_matrix.DelegatedBrowserOwnershipTests"
  ],
  "inside_launcher_command": [
    "env",
    "PYTHONPATH=tools/ui",
    "python3",
    "-B",
    "-m",
    "unittest",
    "-v",
    "test_role_matrix.BrowserFixtureCleanupTests",
    "test_role_matrix.DelegatedBrowserOwnershipTests"
  ],
  "resource_command": [
    "python3",
    "-B",
    "tools/resource_group.py",
    "--",
    "env",
    "PYTHONPATH=tools/ui",
    "python3",
    "-B",
    "-m",
    "unittest",
    "-v",
    "test_role_matrix.BrowserFixtureCleanupTests",
    "test_role_matrix.DelegatedBrowserOwnershipTests"
  ],
  "expected_registration_result": "13 methods:one empty positive,eight assertion failures (five original cleanup,two real process setsid/zombie,one missing ownership API),four explicit dependent skips;exit1",
  "storage": {
    "root": "/run/media/kmosoti/data/FabricO11y",
    "fresh_census": "complete namespace census before invocation; fail closed",
    "reserve_bytes": 1073741824,
    "admission_threshold_bytes": 95000000000,
    "ceiling_bytes": 100000000000,
    "output_json": "/run/media/kmosoti/data/FabricO11y/results/service-opening-candidate/browser-delegated-registration-red-01.json",
    "output_log": "/run/media/kmosoti/data/FabricO11y/results/service-opening-candidate/browser-delegated-registration-red-01.log",
    "raw_resource_receipts": "/run/media/kmosoti/data/FabricO11y/results/service-opening-candidate/resource-containment"
  },
  "limits": {
    "outer_seconds": 1800,
    "memory_high_bytes": 17179869184,
    "memory_max_bytes": 21474836480,
    "swap_max_bytes": 0,
    "serial": "no other project workload/container/VM",
    "delegate": false
  },
  "cleanup": "confirmed complete outer cgroup stop; fixture independent pidfd/reaping for browser; inspect all owned process identities and actual preservation/temporary postconditions; retain failures and original files without reconstruction",
  "guards": "Production/browser/helper/oracles unchanged; cgroup placement/population/kill interfaces modeled; process identities,zombies,independent cleanup are real. All old finally assertions retained. No kernel containment/native/browser/compile claim. Synthetic45s lifespan;15/5/2/global240 unchanged. Binder-time observation does not establish later child reaping; later native admission needs an independently established strategy.",
  "pins": {
    "results/candidate-build-fresh-8fb6f413179b-01/run-step-browser-delegated-registration-01.py": "317a7a9f1ca3013ada706a3d569d1f63985a4caf4de00bbad0f423cb29a9d81c",
    "scratch/console-access-acceptance/tools/ui/test_role_matrix.py": "f54944f27ca76bb9d342c9c72f5415d0827c5024af69e6defdaccb006308260d",
    "scratch/console-access-acceptance/docs/experiments/formal/console-session-clock-protocol.md": "9d5af92f4be624bb45adf9a6c5efa23b068472fea2a208f89e2076f416b6d8c1"
  }
}

results/candidate-build-fresh-8fb6f413179b-01/run-step-browser-delegated-registration-01.py

SHA256 317a7a9f1ca3013ada706a3d569d1f63985a4caf4de00bbad0f423cb29a9d81c, 7040 bytes.

import datetime, hashlib, json, os, re, signal, subprocess, sys, time
from pathlib import Path
ROOT = Path('/run/media/kmosoti/data/FabricO11y')
REPO = ROOT / 'scratch/console-access-acceptance'
OUT = ROOT / 'results/service-opening-candidate'
STORE = ROOT / 'scratch/service-opening-census'
FROZEN = '90cdf680d23769acb8fc20fda9cf15818d6549a2'
def require(value, reason):
    if not value:
        raise ValueError(reason)
label, reserve_text, *command = sys.argv[1:]
reserve = int(reserve_text)
delegated = command[:1] == ['--delegate']
if delegated: command = command[1:]
require(re.fullmatch(r'[a-z0-9-]{1,80}', label) and reserve > 0 and command, 'ordinary workload admission guard')
record_path = OUT / (label + '.json')
require(not record_path.exists(), 'unique run label required')
def census():
    # Rootless container files can belong to subordinate UIDs. Inspect all of
    # them in the same user namespace; never skip unreadable directories.
    require(not STORE.is_symlink(), 'ordinary workload admission guard')
    require((STORE / '.owned-census-store').read_text() == 'service-opening-census-v1\n', 'ordinary workload admission guard')
    args = ['podman', '--root', str(STORE/'graph'), '--runroot', str(STORE/'run'),
            '--tmpdir', str(STORE/'tmp'), '--storage-driver', 'vfs',
            'unshare', 'python3', '-B', str(OUT/'census.py')]
    env = dict(os.environ, TMPDIR=str(STORE/'tmp'), TMP=str(STORE/'tmp'), TEMP=str(STORE/'tmp'))
    result = subprocess.run(args, env=env, text=True, capture_output=True, timeout=25)
    if result.returncode:
        raise RuntimeError(f'strict namespace census failed ({result.returncode}): {result.stderr}')
    observed = json.loads(result.stdout)
    require(observed['uid'] == 0 and observed['gid'] == 0, 'ordinary workload admission guard')
    require(type(observed['data_bytes']) is int and observed['data_bytes'] >= 0, 'ordinary workload admission guard')
    return observed
def git(*args):
    return subprocess.check_output(['git', *args], cwd=REPO, text=True).strip()
require(git('rev-parse', 'HEAD') == FROZEN and not git('status', '--porcelain'), 'clean frozen source required')
require(not subprocess.check_output(['systemctl', '--user', 'list-units', 'fabric-work-*', '--state=running', '--plain', '--no-legend'], text=True).strip(), 'another project workload is active')
initial = census()
used = initial['data_bytes']
record = {'label': label, 'command': command, 'delegated': delegated, 'frozen': None, 'scope': 'harness controls only; no candidate acceptance evidence', 'harness_revision': FROZEN, 'source_status_before': git('status', '--porcelain'), 'storage_root': str(ROOT), 'admission_bytes': used, 'admission_observation': initial, 'reserved_bytes': reserve, 'observations': [], 'started_utc': datetime.datetime.now(datetime.timezone.utc).isoformat()}
if used + reserve > 95_000_000_000:
    record.update(state='not_run', reason='95 GB storage admission threshold')
    record_path.write_text(json.dumps(record, indent=2)+'\n')
    raise SystemExit('storage admission denied; project command not launched')
receipts = REPO / 'target/resource-containment/runs'
before = set(receipts.glob('*.json'))
env = dict(os.environ, FABRIC_STORAGE_ROOT=str(ROOT), CARGO_HOME=str(ROOT/'toolchain-cache/cargo'), RUSTUP_HOME=str(ROOT/'toolchain-cache/rustup'), CARGO_BUILD_JOBS='2')
env['PATH'] = str(ROOT/'tools/candidate-dpkg/bin') + ':' + env['PATH']
log_path = OUT / (label + '.log')
record.update(state='running', log=str(log_path))
record_path.write_text(json.dumps(record, indent=2)+'\n')
def find_unit():
    with log_path.open() as stream:
        prefix = stream.read(65536)
    match = re.search(r'Running as unit: (fabric-work-[0-9a-f]+)\.service', prefix)
    return match.group(1) if match else None
def stop_owned(process):
    unit = find_unit()
    if unit:
        stopped = subprocess.run(['systemctl', '--user', 'stop', unit],
                                 text=True, capture_output=True, timeout=25)
        record['stop'] = {'unit': unit, 'exit': stopped.returncode, 'stderr': stopped.stderr}
        if stopped.returncode:
            # Interrupt the launcher too; its finally block independently
            # confirms that this exact service has no surviving descendants.
            process.send_signal(signal.SIGINT)
    else:
        process.send_signal(signal.SIGINT)
        record['stop'] = {'unit': None, 'launcher_interrupted': True}
with log_path.open('wb') as log:
    launcher = ['python3', '-B', 'tools/resource_group.py', *(['--delegate'] if delegated else []), '--', *command]
    process = subprocess.Popen(launcher, cwd=REPO, env=env, stdout=log, stderr=subprocess.STDOUT)
    next_census = time.monotonic() + 30
    try:
        while process.poll() is None:
            time.sleep(1)
            if time.monotonic() >= next_census:
                observed = census()
                record['observations'].append({'unix':time.time(), **observed})
                record_path.write_text(json.dumps(record, indent=2)+'\n')
                if observed['data_bytes'] >= 95_000_000_000:
                    record['interruption'] = '95 GB threshold reached'
                    break
                next_census = time.monotonic() + 30
    except BaseException as error:
        record['interruption'] = f'{type(error).__name__}: {error}'
    finally:
        if record.get('interruption') and process.poll() is None:
            try:
                stop_owned(process)
            except BaseException as error:
                record['stop_error'] = f'{type(error).__name__}: {error}'
                process.send_signal(signal.SIGINT)
        status = process.wait()
record['launcher_exit'] = status
if record.get('interruption'): status = 2
with log_path.open('rb') as stream:
    log_digest = hashlib.file_digest(stream, 'sha256').hexdigest()
record.update(state='interrupted' if record.get('interruption') else 'completed', exit=status, source_status_after=git('status', '--porcelain'), finished_utc=datetime.datetime.now(datetime.timezone.utc).isoformat(), log_sha256=log_digest, resource_receipts=[])
archive = OUT/'resource-containment'; archive.mkdir(exist_ok=True)
for p in sorted(set(receipts.glob('*.json')) - before):
    value=json.loads(p.read_text())
    if value['command'] != command: continue
    q=archive/p.name; q.write_bytes(p.read_bytes())
    record['resource_receipts'].append({'path':str(q),'sha256':hashlib.sha256(q.read_bytes()).hexdigest(),'exit':value['exit'],'stop_confirmed':value['stop_confirmed'],'retained_failure_evidence':value['retained_failure_evidence']})
if not record['resource_receipts'] or any(not r['stop_confirmed'] or r['exit'] != status for r in record['resource_receipts']):
    record['receipt_error'] = 'missing or inconsistent outer resource receipt'
    status = 2
    record['exit'] = status
record_path.write_text(json.dumps(record, indent=2)+'\n')
print(json.dumps(record, indent=2))
if status: print(log_path.read_text()[-8000:])
raise SystemExit(status)

scratch/console-access-acceptance/tools/ui/test_role_matrix.py

SHA256 f54944f27ca76bb9d342c9c72f5415d0827c5024af69e6defdaccb006308260d, 57715 bytes.

"""ADR-derived route coverage; origin: issue45/C-027 and the missing legacy rows."""
import ast
import copy
from contextlib import contextmanager, ExitStack
import ctypes
import hashlib
import json
import os
from pathlib import Path
import re
import shutil
import signal
import socket
import stat
import subprocess
import sys
import tempfile
import threading
import time
from types import SimpleNamespace
import unittest
from unittest.mock import patch

import live_browser_check as browser

ROOT = Path(__file__).resolve().parents[2]
FIXTURE = ROOT / 'docs/experiments/formal/fixtures/console-route-roles.json'


def registered_routes(source):
    routes = set()
    for match in re.finditer(r'\.route\(\s*"([^"]+)"\s*,', source):
        depth, end = 1, match.end()
        while depth:
            depth += (source[end] == '(') - (source[end] == ')')
            end += 1
        for method in re.findall(r'\b(get|post|put|patch|delete|head|options)\s*\(', source[match.end():end]):
            routes.add((method.upper(), match.group(1)))
    return routes


def witnessed_calls(request, check):
    if hasattr(browser, 'run_role_matrix'):
        browser.run_role_matrix(request, check)
        return
    # Execute ONLY the retained selected-matrix AST against synthetic transports.
    # No main(), browser, sockets, subprocesses or native authority are invoked.
    main = next(node for node in ast.parse(Path(browser.__file__).read_text()).body
                if isinstance(node, ast.FunctionDef) and node.name == 'main')
    statements = next(node.body for node in ast.walk(main) if isinstance(node, ast.Try)
                      and any(isinstance(n, ast.Assign) and any(isinstance(t, ast.Name) and t.id == 'owner_routes'
                                                               for t in n.targets) for n in node.body))
    begin = next(i for i, node in enumerate(statements) if isinstance(node, ast.Assign)
                 and any(isinstance(t, ast.Name) and t.id == 'owner_routes' for t in node.targets))
    end = next(i for i in range(begin + 1, len(statements)) if isinstance(statements[i], ast.Assign)
               and any(isinstance(t, ast.Name) and t.id == 'read' for t in statements[i].targets))
    namespace = {'credential': 'reader', 'spindle_token': 'spindle', 'check': check,
                 'bearer_api': lambda role, path, method='GET', body=None: request(role or 'anonymous', method, path, body),
                 'api': lambda path, method='GET', body=None: request('owner', method, path, body),
                 'expect': lambda answer, status, message, label: check(browser.semantic_rejection(answer, status, message), label)}
    exec(compile(ast.Module(body=statements[begin:end], type_ignores=[]), '<retained-matrix>', 'exec'), namespace)


class RoleMatrixTests(unittest.TestCase):
    def setUp(self):
        self.fixture = json.loads(FIXTURE.read_text())
        self.expected = {(role, method, path): outcome
                         for method, _, path, _, outcomes in self.fixture['rows']
                         for role, outcome in zip(self.fixture['roles'], outcomes)}

    def request(self, role, method, path, body=None):
        # The retained fixture targeted browser-edge; the successor owns matrix.
        path = path.replace('/v1/console/nodes/browser-edge/', '/v1/console/nodes/matrix/')
        status, error = self.expected.get((role, method, path), (200, None))
        field = self.fixture['refusal_fields'].get(path, 'error')
        return status, {field: error} if error else {}

    def test_fixture_covers_both_registered_routers_and_all_control_actions(self):
        rows = self.fixture['rows']
        self.assertEqual(self.fixture['roles'], ['anonymous', 'spindle', 'reader', 'owner'])
        self.assertEqual(len(rows), 36)
        self.assertEqual(len(self.expected), 144)
        registered = set().union(*(registered_routes((ROOT / 'crates/fabric-server/src' / name).read_text())
                                  for name in ('console.rs', 'http.rs')))
        self.assertEqual({(row[0], row[1]) for row in rows}, registered)
        for prefix in ('/v1/console', '/v1/admin'):
            self.assertEqual({row[2].rsplit('/', 1)[1] for row in rows
                              if row[1] == prefix + '/nodes/{name}/{action}'}, {'pause', 'resume', 'revoke'})

    def test_live_matrix_calls_all_credentials_on_every_route_and_legacy_action(self):
        calls = []

        def request(role, method, path, body):
            calls.append((role, method, path))
            return self.request(role, method, path, body)

        witnessed_calls(request, self.assertTrue)
        self.assertEqual(set(calls), set(self.expected),
                         'live role matrix missing cells: ' + repr(sorted(set(self.expected) - set(calls))))
        self.assertEqual(len(calls), 144, 'each registered role-route cell must run exactly once')

    def test_reader_admission_mutation_is_rejected_by_the_live_checker(self):
        def request(role, method, path, body):
            if (role, method, path) == ('reader', 'GET', '/v1/console/audit'):
                return 200, {'events': []}
            return self.request(role, method, path, body)

        with self.assertRaisesRegex(AssertionError, 'reader.*GET /v1/console/audit'):
            witnessed_calls(request, self.assertTrue)

    def test_independent_outcomes_never_accept_admission_refusal_or_role_crossover(self):
        for role, path, expected in [
            ('spindle', '/v1/console/status', [401, 'sign in required']),
            ('reader', '/v1/console/audit', [403, 'role not permitted']),
            ('owner', '/v1/admin/nodes', [401, 'use a console credential']),
        ]:
            self.assertEqual(self.expected[(role, 'GET', path)], expected)
            self.assertFalse(browser.semantic_rejection((429, {'error': expected[1]}), *expected))
            self.assertFalse(browser.semantic_rejection((200, {'error': expected[1]}), *expected))
            self.assertFalse(browser.semantic_rejection((expected[0], {'error': 'wrong refusal'}), *expected))
        missing = copy.deepcopy(self.fixture['rows'])
        missing.remove(next(row for row in missing if row[0:3] ==
                            ['POST', '/v1/admin/nodes/{name}/{action}', '/v1/admin/nodes/matrix/resume']))
        self.assertEqual(len({(r[0], r[1]) for r in missing}), len({(r[0], r[1]) for r in self.fixture['rows']}))
        self.assertNotEqual({(r[0], r[2]) for r in missing}, {(r[0], r[2]) for r in self.fixture['rows']})

    def test_transports_refuse_expired_or_storage_limited_dispatch_and_progressing_body(self):
        # Origin: Miso's independent review of0de4b46; no main/network/process.
        source = ast.parse(Path(browser.__file__).read_text())
        main = next(n for n in source.body if isinstance(n, ast.FunctionDef) and n.name == 'main')
        functions = [n for n in source.body if isinstance(n, ast.FunctionDef) and n.name != 'main']
        functions += [n for n in main.body if isinstance(n, ast.FunctionDef) and n.name in ('call', 'bearer_api')]
        for transport in ('call', 'bearer_api'):
            for case in ('expired', 'storage', 'paced_expiry', 'timeout', 'progressing'):
                if transport == 'call' and case == 'paced_expiry':continue
                with self.subTest(transport=transport, case=case):
                    now, opened, reads = [2.0 if case == 'expired' else 0.0], [], []
                    class Response:
                        status = 200
                        fp = SimpleNamespace(raw=SimpleNamespace(_sock=SimpleNamespace(settimeout=lambda _: None)))
                        def __enter__(self):return self
                        def __exit__(self, *_):pass
                        def read(self, size=None):
                            reads.append('whole')
                            if case == 'progressing':now[0] = 2.0
                            return b'{"value":{"ready":true}}'
                        def read1(self, size):
                            reads.append('chunk')
                            if case == 'progressing':now[0] = 2.0
                            return b'{"value":{"ready":true}}' if len(reads) == 1 else b''
                    def open_response(request, **kwargs):
                        opened.append(kwargs['timeout'])
                        return Response()
                    namespace = dict(vars(browser))
                    namespace.update(time=SimpleNamespace(monotonic=lambda:now[0], monotonic_ns=lambda:int(now[0]*1e9)),
                                     deadline=1.0, storage_violation=SimpleNamespace(is_set=lambda:case == 'storage'),
                                     endpoint='http://localhost:1', origin='https://localhost:1', receipt={},
                                     args=SimpleNamespace(inject_role_defect=False), tls_opener=SimpleNamespace(open=open_response),
                                     pace_api=lambda:now.__setitem__(0, 2.0 if case == 'paced_expiry' else now[0]),
                                     cadence=SimpleNamespace(clock=lambda:now[0], last=None),
                                     urllib=SimpleNamespace(request=SimpleNamespace(Request=browser.urllib.request.Request, urlopen=open_response),
                                                            error=browser.urllib.error))
                    exec(compile(ast.Module(body=functions, type_ignores=[]), '<transport-boundary>', 'exec'), namespace)
                    invoke = (lambda:namespace['call']('GET', '/status')) if transport == 'call' else (lambda:namespace['bearer_api'](None, '/v1/console/nodes'))
                    if case == 'timeout':
                        invoke()
                        self.assertEqual(len(opened), 1)
                        self.assertGreater(opened[0], 0)
                        self.assertLessEqual(opened[0], 1.0, 'socket timeout exceeds remaining inner deadline')
                    else:
                        with self.assertRaisesRegex(RuntimeError, 'deadline|storage|512 MiB'):
                            invoke()
                        if case == 'progressing':self.assertEqual(reads, ['chunk'], 'wall bound must stop a progressively readable body')
                        else:self.assertEqual(opened, [], 'expired/storage-limited dispatch reached network')

    def test_actual_slow_headers_and_chunk_metadata_cannot_outlive_inner_io_bounds(self):
        # Origin: CPython read1 still reads chunk metadata/header lines internally.
        source = ast.parse(Path(browser.__file__).read_text())
        main = next(n for n in source.body if isinstance(n, ast.FunctionDef) and n.name == 'main')
        functions = [n for n in source.body if isinstance(n, ast.FunctionDef) and n.name != 'main']
        functions += [n for n in main.body if isinstance(n, ast.FunctionDef) and n.name == 'call']
        for case in ('headers', 'chunk_metadata', 'storage'):
            with self.subTest(case=case):
                storage, stop, errors = threading.Event(), threading.Event(), []
                with socket.socket() as listener:
                    listener.bind(('127.0.0.1', 0));listener.listen(1);listener.settimeout(2)
                    def peer():
                        try:
                            connection, _ = listener.accept()
                            with connection:
                                connection.settimeout(1);request=b''
                                while b'\r\n\r\n' not in request:request+=connection.recv(4096)
                                body=b'{"value":{"ready":true}}'
                                prefix=(b'HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n'+f'{len(body):x};note='.encode()
                                        if case == 'chunk_metadata' else b'HTTP/1.1 200 OK\r\nX-Progress: ')
                                connection.sendall(prefix);began=time.monotonic()
                                while time.monotonic()-began<.6 and not stop.is_set():
                                    if case == 'storage' and time.monotonic()-began>=.12:storage.set()
                                    connection.sendall(b'x');stop.wait(.01)
                                suffix=(b'\r\n'+body+b'\r\n0\r\n\r\n' if case == 'chunk_metadata'
                                        else b'\r\nContent-Length: '+str(len(body)).encode()+b'\r\n\r\n'+body)
                                if not stop.is_set():connection.sendall(suffix)
                        except (BrokenPipeError, ConnectionResetError):pass
                        except Exception as error:errors.append(error)
                    worker=threading.Thread(target=peer, daemon=True);worker.start()
                    namespace=dict(vars(browser));began=time.monotonic()
                    namespace.update(endpoint=f'http://127.0.0.1:{listener.getsockname()[1]}',
                                     deadline=began+(2 if case == 'storage' else .12),storage_violation=storage)
                    exec(compile(ast.Module(body=functions, type_ignores=[]), '<actual-io-boundary>', 'exec'), namespace)
                    previous_handler=browser.signal.getsignal(browser.signal.SIGALRM)
                    previous_timer=browser.signal.getitimer(browser.signal.ITIMER_REAL)
                    try:
                        with self.assertRaisesRegex(RuntimeError, 'storage|512 MiB' if case == 'storage' else 'deadline'):
                            namespace['call']('GET', '/status')
                        elapsed=time.monotonic()-began
                    finally:
                        stop.set();worker.join(1)
                    self.assertFalse(worker.is_alive(), 'synthetic peer did not stop')
                    self.assertEqual(errors, [], 'synthetic peer failed before exercising the bound')
                    self.assertEqual(browser.signal.getsignal(browser.signal.SIGALRM), previous_handler)
                    self.assertEqual(browser.signal.getitimer(browser.signal.ITIMER_REAL), previous_timer)
                    self.assertLessEqual(elapsed, .35, 'continuous metadata progress evaded the absolute I/O bound')

    def test_actual_browser_dispatch_gap_survives_delayed_pace_continuation(self):
        # Origin: Miso's 5ms continuation counterexample; execute actual injected JS.
        source=ast.parse(Path(browser.__file__).read_text())
        scripts=[n.args[0].value for n in ast.walk(source) if isinstance(n, ast.Call)
                 and isinstance(n.func, ast.Name) and n.func.id == 'js' and n.args
                 and isinstance(n.args[0], ast.Constant) and isinstance(n.args[0].value, str)
                 and 'window.fixturePaceQueue=Promise.resolve()' in n.args[0].value]
        self.assertEqual(len(scripts), 1, 'one actual fetch scheduler must supply the control')
        runner=browser.DATA/'tools/bun-1.4.0/bun'
        if not runner.is_file():runner=Path(browser.shutil.which('bun') or str(runner))
        self.assertTrue(runner.is_file(), 'Bun is required for the actual JavaScript control')
        script='const setup='+json.dumps(scripts[0])+r''';
          let now=0,delayed=false;const actual=[];
          const window={fetch:async(url)=>{actual.push({path:url,started_ms:now});return {status:200,headers:{get:()=>null}}}};
          new Function('window','performance','setTimeout','location','return function(){'+setup+'}')(
            window,{now:()=>now},(resolve,delay)=>{now+=delay;resolve()},{href:'https://fixture.invalid/console/'})(550);
          const pace=window.fixturePace;
          window.fixturePace=async(...args)=>{const value=await pace(...args);if(!delayed){delayed=true;now+=5}return value};
          await window.fetch('/v1/console/auth/login/start');await window.fetch('/v1/console/auth/login/finish');
          window.fixtureUnpacedBurst=true;
          await Promise.all(Array.from({length:16},()=>window.fetch('/v1/console/auth/login/start')));
          console.log(JSON.stringify({actual,recorded:window.fixtureApiHeaders,truncated:window.fixtureApiHeadersTruncated}));
        '''
        result=subprocess.run([str(runner),'--eval',script],capture_output=True,text=True,timeout=5)
        self.assertEqual(result.returncode,0,result.stderr)
        witness=json.loads(result.stdout);actual=witness['actual'];recorded=witness['recorded']
        self.assertEqual(len(actual),18,'two paced requests and the unchanged16-request unpaced control')
        self.assertEqual([r['started_ms'] for r in actual],[r['started_ms'] for r in recorded], 'receipt stamps actual fetch dispatch')
        self.assertEqual([r['status'] for r in recorded],[200]*18)
        self.assertEqual([r['paced'] for r in recorded],[True,True]+[False]*16)
        self.assertEqual(len({r['started_ms'] for r in actual[2:]}),1,'registered burst remains unpaced')
        self.assertFalse(witness['truncated'])
        self.assertGreaterEqual(actual[1]['started_ms']-actual[0]['started_ms'],550,
                                '5ms pace-continuation delay shrank actual dispatch gap: '+repr(actual[:2]))


def owned_browser_identity(pid):
    process = Path('/proc') / str(pid)
    fields = (process / 'stat').read_text().rsplit(')', 1)[1].split()
    if process.stat().st_uid != os.getuid() or int(fields[19]) <= 0:
        raise AssertionError('unowned browser control process')
    return int(fields[19]), int(fields[2])


@contextmanager
def browser_cleanup_fixture(modes, blocked_sampler=False, cgroup_fault=None):
    # Every process is real but synthetic, with a finite 45-second lifespan.
    sys.path.insert(0, str(ROOT / 'tools'))
    from resource_group import require_limits
    require_limits()
    libc, previous = ctypes.CDLL(None, use_errno=True), ctypes.c_int()
    if libc.prctl(37, ctypes.byref(previous), 0, 0, 0) or libc.prctl(36, 1, 0, 0, 0):
        raise RuntimeError('browser process controls require Linux subreaper')
    directory = parent_path = None
    groups, identities, process_logs, group_descriptors, registry_pidfds = [], [], [], [], []
    sampler = None
    mocks = None
    body_failure = None
    restore_attempted = False
    stop_samples, release_sampler = threading.Event(), threading.Event()
    try:
        directory = Path(tempfile.mkdtemp(dir=os.environ['FABRIC_SCRATCH_ROOT'], prefix='browser-cleanup-control-'))
        work, out = directory / 'work', directory / 'out'
        work.mkdir()
        out.mkdir()
        parent_path = directory / 'fabric-work-browser-control.service'
        parent_path.mkdir()
        (parent_path / 'supervisor').mkdir()
        for name, value in {'cgroup.controllers': 'memory cpu pids io',
                            'cgroup.subtree_control': 'memory cpu pids io',
                            'memory.max': '4000000000', 'memory.high': '3500000000',
                            'memory.swap.max': '0', 'cpu.max': '200000 100000',
                            'pids.max': '512'}.items():
            (parent_path / name).write_text(value)

        def held_directory(path):
            descriptor = os.open(path, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW | os.O_CLOEXEC)
            observed = os.fstat(descriptor)
            group_descriptors.append((descriptor, observed.st_dev, observed.st_ino))
            return {'path': path, 'fd': descriptor, 'dev': observed.st_dev, 'ino': observed.st_ino}

        parent = held_directory(parent_path)
        parent['deadline_monotonic_ns'] = time.monotonic_ns() + 240_000_000_000
        script = directory / 'owned-process.py'
        script.write_text('''import os, select, signal, sys, time
from pathlib import Path
directory, work, mode = Path(sys.argv[1]), Path(sys.argv[2]), sys.argv[3]
expires = time.monotonic() + 45
def atomic(name, text):
    pending = directory / (name + '.pending')
    with pending.open('x') as stream:
        stream.write(text); stream.flush(); os.fsync(stream.fileno())
    pending.replace(directory / name)
if mode == 'timeout': signal.signal(signal.SIGTERM, signal.SIG_IGN)
gate_read, gate_write = os.pipe()
child = os.fork()
if child == 0:
    os.close(gate_write)
    if not select.select([gate_read], [], [], 5)[0] or os.read(gate_read, 1) != b'1': os._exit(1)
    os.close(gate_read)
    signal.signal(signal.SIGTERM, signal.SIG_IGN)
    if mode == 'setsid': os.setsid()
    held = (work / ('held-' + directory.name)).open('xb')
    held.write(b'literal browser private fixture'); held.flush()
    atomic('ready', 'ready')
    time.sleep(max(0, expires - time.monotonic()))
    os._exit(0)
os.close(gate_read)
try:
    process = Path('/proc') / str(child)
    fields = (process / 'stat').read_text().rsplit(')', 1)[1].split()
    if process.stat().st_uid != os.getuid() or int(fields[19]) <= 0 or int(fields[1]) != os.getpid() or int(fields[2]) != os.getpid():
        raise RuntimeError('fork child is outside owned private group')
    atomic('child.pid', f'{child} {fields[19]}')
    os.write(gate_write, b'1')
finally:
    os.close(gate_write)
deadline = time.monotonic() + 5
while not (directory / 'ready').exists():
    if time.monotonic() >= deadline: raise RuntimeError('child readiness deadline')
    time.sleep(.01)
while not (directory / 'admitted').exists():
    if time.monotonic() >= deadline: raise RuntimeError('controller admission deadline')
    time.sleep(.01)
if mode not in ('exited', 'setsid'): time.sleep(max(0, expires - time.monotonic()))
''')
        original_read, original_write, original_fd_write = Path.read_text, Path.write_text, os.write
        kill_attempts = []
        fault = {'value': cgroup_fault}

        def members(item):
            living = []
            for pid, start in ((item['process'].pid, item['start']),
                               (item.get('child'), item.get('child_start'))):
                if pid is None:
                    continue
                try:
                    fields = original_read(Path('/proc') / str(pid) / 'stat').rsplit(')', 1)[1].split()
                except FileNotFoundError:
                    continue
                if int(fields[19]) != start:
                    raise AssertionError('mock cgroup member identity changed')
                if fields[0] not in ('Z', 'X'):
                    living.append(pid)
            return living

        def cgroup_read(path, *args, **kwargs):
            for item in groups:
                group_path = item['group']['path']
                if path == group_path / 'cgroup.procs':
                    return ''.join(str(pid) + '\n' for pid in members(item))
                if path == group_path / 'cgroup.events':
                    populated = bool(members(item)) or fault['value'] == 'stuck-population'
                    return 'populated ' + str(int(populated)) + '\nfrozen 0\n'
                if any(path == Path('/proc') / str(pid) / 'cgroup'
                       for pid in (item['process'].pid, item.get('child')) if pid is not None):
                    placement = parent_path / 'supervisor' if fault['value'] == 'outside-placement' else group_path
                    return '0::/' + str(placement.relative_to(directory)) + '\n'
            return original_read(path, *args, **kwargs)

        def cgroup_kill(item, value):
            if value not in ('1', b'1'):
                raise AssertionError('mock kill accepts only the registered kill value')
            kill_attempts.append(item['process'].pid)
            if fault['value'] == 'first-stop-refused' and item is groups[-1]:
                raise PermissionError('literal owned group stop failure')
            living = members(item)
            for pid, start, descriptor in identities:
                if pid in living:
                    try:
                        signal.pidfd_send_signal(descriptor, signal.SIGKILL)
                    except ProcessLookupError:
                        pass
            return 1

        def cgroup_write(path, value, *args, **kwargs):
            for item in groups:
                if path == item['group']['path'] / 'cgroup.kill':
                    return cgroup_kill(item, value)
            return original_write(path, value, *args, **kwargs)

        def cgroup_fd_write(descriptor, value):
            observed = os.fstat(descriptor)
            for item in groups:
                if (observed.st_dev, observed.st_ino) == item['kill_identity']:
                    return cgroup_kill(item, value)
            return original_fd_write(descriptor, value)

        mocks = ExitStack()
        mocks.enter_context(patch.object(Path, 'read_text', cgroup_read))
        mocks.enter_context(patch.object(Path, 'write_text', cgroup_write))
        mocks.enter_context(patch.object(os, 'write', cgroup_fd_write))
        if hasattr(browser, 'cgroups'):
            mocks.enter_context(patch.object(browser.cgroups, 'ROOT', directory))
            mocks.enter_context(patch.object(browser.cgroups, 'current', return_value=parent_path / 'supervisor'))
        for index, mode in enumerate(modes):
            group_dir = directory / ('group-' + str(index))
            group_dir.mkdir()
            group_path = parent_path / ('group-' + str(index))
            group_path.mkdir()
            for name in ('cgroup.procs', 'cgroup.events', 'cgroup.kill'):
                (group_path / name).write_text('')
            for name in ('memory.max', 'memory.high', 'memory.swap.max', 'cpu.max', 'pids.max'):
                (group_path / name).write_text((parent_path / name).read_text())
            kill_identity = (group_path / 'cgroup.kill').stat()
            group = held_directory(group_path)
            group['exclusive'] = True
            log = (group_dir / 'process.log').open('xb')
            process_logs.append(log)
            process = subprocess.Popen([sys.executable, '-B', str(script), str(group_dir), str(work), mode],
                                       start_new_session=True, stdout=log, stderr=log)
            groups.append({'process': process, 'directory': group_dir, 'group': group,
                           'kill_identity': (kill_identity.st_dev, kill_identity.st_ino)})
            start, pgid = owned_browser_identity(process.pid)
            descriptor = os.pidfd_open(process.pid)
            identities.append((process.pid, start, descriptor))
            groups[-1]['start'] = start
            registry_pidfd = os.dup(descriptor)
            registry_pidfds.append((registry_pidfd, process.pid))
            group.update(process=process, pid=process.pid, start_ticks=start, pidfd=registry_pidfd)
            if owned_browser_identity(process.pid) != (start, process.pid) or pgid != process.pid:
                raise AssertionError('owned leader identity changed')
            deadline = time.monotonic() + 5
            while not (group_dir / 'ready').exists():
                if time.monotonic() >= deadline:
                    raise AssertionError('owned child did not publish readiness')
                time.sleep(.01)
            marker = group_dir / 'child.pid'
            info = marker.lstat()
            if not stat.S_ISREG(info.st_mode) or info.st_uid != os.getuid() or info.st_nlink != 1 or info.st_size > 128:
                raise AssertionError('invalid child identity marker')
            child, child_start = map(int, marker.read_text().split())
            expected_pgid = child if mode == 'setsid' else process.pid
            if child <= 1 or child_start <= 0 or owned_browser_identity(child) != (child_start, expected_pgid):
                raise AssertionError('unbound owned child identity')
            child_descriptor = os.pidfd_open(child)
            identities.append((child, child_start, child_descriptor))
            if owned_browser_identity(child) != (child_start, expected_pgid):
                raise AssertionError('child identity changed during pidfd binding')
            groups[-1].update(child=child, child_start=child_start, child_pidfd=child_descriptor)
            binding = {'parent': parent, 'group': group}
            if callable(getattr(browser, 'bind_browser_group', None)):
                binding = browser.bind_browser_group(parent, group, process)
                for member in binding['group'].get('members', []):
                    descriptor = member['pidfd']
                    if descriptor in {identity[2] for identity in identities}:
                        raise AssertionError('registry cannot consume independent guardian pidfd')
                    if descriptor not in {entry[0] for entry in registry_pidfds}:
                        registry_pidfds.append((descriptor, member['pid']))
            groups[-1]['binding'] = binding
            (group_dir / 'admitted').write_text('owned by controller')
            if mode in ('exited', 'setsid'):
                process.wait(timeout=5)
        sampler = threading.Thread(target=lambda: release_sampler.wait(4) if blocked_sampler else stop_samples.wait(4))
        sampler.start()
        namespace = dict(vars(browser))
        namespace.update(session=None, processes=[('group-' + str(i), item['process']) for i, item in enumerate(groups)],
                         receipt={'exit': 0}, stop_samples=stop_samples, sampler=sampler,
                         out=out, samples=[], logs=[], work=work,
                         group_parent=parent, owned_groups=[item['binding'] for item in groups],
                         cgroup_kill_attempts=kill_attempts, cgroup_fault=fault)
        yield namespace, groups
    except BaseException as error:
        body_failure = {'type': type(error).__name__, 'message': str(error)[:1024]}
        raise
    finally:
        try:
            if mocks is not None:
                mocks.close()
            errors = []
            stop_evidence, group_evidence, file_evidence = [], [], []
            cleanup_began_monotonic_ns = time.monotonic_ns()
            sampler_alive_before_cleanup = sampler is not None and sampler.is_alive()
            stop_samples.set()
            release_sampler.set()
            if sampler is not None:
                try:
                    sampler.join(timeout=5)
                    if sampler.is_alive():
                        errors.append('sampler did not stop')
                except RuntimeError as error:
                    errors.append(str(error))
            for pid, start, descriptor in identities:
                observed = {'pid': pid, 'expected_start_ticks': start,
                            'began_monotonic_ns': time.monotonic_ns(),
                            'pidfd_kill_attempted': False, 'stop_confirmed': False}
                stop_evidence.append(observed)
                try:
                    try:
                        current, pgid = owned_browser_identity(pid)
                    except FileNotFoundError:
                        observed.update(stop_confirmed=True, outcome='already absent')
                        continue
                    observed.update(observed_start_ticks=current, pgid=pgid)
                    if current != start:
                        raise AssertionError('refuse cleanup of reused PID')
                    fields = (Path('/proc') / str(pid) / 'stat').read_text().rsplit(')', 1)[1].split()
                    if int(fields[19]) != start:
                        raise AssertionError('process identity changed before state observation')
                    observed['state_before_signal'] = fields[0]
                    try:
                        observed['pidfd_kill_attempted'] = True
                        signal.pidfd_send_signal(descriptor, signal.SIGKILL)
                    except ProcessLookupError:
                        pass
                    deadline = time.monotonic() + 5
                    while True:
                        try:
                            reaped, status = os.waitpid(pid, os.WNOHANG)
                        except ChildProcessError:
                            reaped = 0
                        if reaped == pid:
                            observed.update(stop_confirmed=True, outcome='reaped by control', wait_status=status)
                            break
                        try:
                            current, _ = owned_browser_identity(pid)
                        except FileNotFoundError:
                            observed.update(stop_confirmed=True, outcome='confirmed absent')
                            break
                        if current != start or time.monotonic() >= deadline:
                            raise AssertionError('owned process identity/cleanup not confirmed')
                        time.sleep(.01)
                except (OSError, ValueError, IndexError, AssertionError) as error:
                    errors.append(str(error))
                    observed['error'] = str(error)[:512]
                finally:
                    observed['ended_monotonic_ns'] = time.monotonic_ns()
                    try:
                        os.close(descriptor)
                    except OSError as error:
                        errors.append(str(error))
            for item in groups:
                observed = {'pgid': item['process'].pid, 'confirmed_zero_population': False,
                            'before_monotonic_ns': time.monotonic_ns()}
                group_evidence.append(observed)
                try:
                    os.killpg(item['process'].pid, 0)
                except ProcessLookupError:
                    observed['confirmed_zero_population'] = True
                    continue
                except OSError as error:
                    errors.append(str(error))
                    observed['error'] = str(error)[:512]
                else:
                    errors.append('owned group is still populated')
                finally:
                    observed['after_monotonic_ns'] = time.monotonic_ns()
            for log in process_logs:
                try:
                    log.close()
                except OSError as error:
                    errors.append(str(error))
            for descriptor, device, inode in group_descriptors:
                try:
                    observed = os.fstat(descriptor)
                    if (observed.st_dev, observed.st_ino) != (device, inode):
                        raise AssertionError('refuse closing reused control directory descriptor')
                    os.close(descriptor)
                except OSError as error:
                    if error.errno != 9:
                        errors.append(str(error))
                except AssertionError as error:
                    errors.append(str(error))
            for descriptor, pid in registry_pidfds:
                try:
                    fields = (Path('/proc/self/fdinfo') / str(descriptor)).read_text().splitlines()
                    bound_pid = int(next(line.split(':', 1)[1] for line in fields if line.startswith('Pid:')))
                    if bound_pid not in (pid, -1):
                        raise AssertionError('refuse closing reused registry pidfd')
                    os.close(descriptor)
                except FileNotFoundError:
                    pass
                except (OSError, ValueError, StopIteration, AssertionError) as error:
                    errors.append(str(error))
            restore_attempted = True
            subreaper_restored = libc.prctl(36, previous.value, 0, 0, 0) == 0
            if not subreaper_restored:
                errors.append('restore previous test subreaper setting')
            if directory is not None:
                witnesses = [(directory / 'owned-process.py', 8192)]
                if parent_path is not None:
                    witnesses.extend((parent_path / name, 128) for name in
                                     ('cgroup.controllers', 'cgroup.subtree_control', 'memory.max',
                                      'memory.high', 'memory.swap.max', 'cpu.max', 'pids.max'))
                for item in groups:
                    witnesses.extend((item['directory'] / name, cap)
                                     for name, cap in (('child.pid', 128), ('ready', 128), ('admitted', 128), ('process.log', 8192)))
                for path, cap in witnesses:
                    record = {'path': str(path.relative_to(directory))}
                    file_evidence.append(record)
                    try:
                        descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_CLOEXEC)
                        try:
                            before = os.fstat(descriptor)
                            if not stat.S_ISREG(before.st_mode) or before.st_uid != os.getuid() or before.st_nlink != 1 or before.st_size > cap:
                                raise AssertionError('invalid bounded evidence file')
                            raw = os.read(descriptor, cap + 1)
                            after = os.fstat(descriptor)
                            identity = lambda value: {key: getattr(value, 'st_' + key) for key in
                                                       ('dev', 'ino', 'mode', 'uid', 'nlink', 'size', 'mtime_ns', 'ctime_ns')}
                            if len(raw) != before.st_size or identity(before) != identity(after):
                                raise AssertionError('evidence file changed during observation')
                            record.update(identity=identity(before), sha256=hashlib.sha256(raw).hexdigest())
                            if path.name == 'child.pid':
                                child, child_start = map(int, raw.split())
                                record.update(pid=child, start_ticks=child_start)
                                record['pidfd_bound'] = any((pid, start) == (child, child_start)
                                                           for pid, start, _ in identities)
                                if not record['pidfd_bound']:
                                    raise AssertionError('marker lacks independently bound pidfd identity')
                        finally:
                            os.close(descriptor)
                    except (OSError, ValueError, AssertionError) as error:
                        record['error'] = str(error)[:512]
                        errors.append('evidence ' + record['path'] + ': ' + str(error)[:512])
                retained = body_failure is not None or bool(errors)
                evidence = {'body_failure': body_failure, 'scratch_retained': retained,
                            'cleanup_began_monotonic_ns': cleanup_began_monotonic_ns,
                            'processes': stop_evidence, 'groups': group_evidence, 'files': file_evidence,
                            'sampler_alive_before_cleanup': sampler_alive_before_cleanup,
                            'sampler_stopped': sampler is None or not sampler.is_alive(),
                            'subreaper_restored': subreaper_restored,
                            'work_exists_after_control': (directory / 'work').exists(),
                            'cgroup_observations_are_mocked': True,
                            'mock_cgroup_kill_attempts': kill_attempts if mocks is not None else [],
                            'mock_cgroup_fault': fault['value'] if mocks is not None else None,
                            'cleanup_errors': errors, 'recorded_monotonic_ns': time.monotonic_ns()}
                try:
                    raw = json.dumps(evidence, indent=2) + '\n'
                    if len(raw.encode()) > 32768:
                        raise AssertionError('control cleanup evidence exceeds 32KiB')
                    with (directory / 'cleanup-evidence.json').open('x') as stream:
                        stream.write(raw)
                        stream.flush()
                        os.fsync(stream.fileno())
                except (OSError, ValueError, AssertionError) as error:
                    errors.append('cleanup evidence: ' + str(error)[:512])
                    retained = True
                if retained:
                    print('browser control evidence retained: ' + str(directory), file=sys.stderr)
            if errors:
                raise AssertionError('control scratch retained at ' + str(directory) + ': ' + '; '.join(errors))
            if directory is not None and body_failure is None:
                shutil.rmtree(directory)
        finally:
            if not restore_attempted and libc.prctl(36, previous.value, 0, 0, 0):
                raise RuntimeError('restore previous test subreaper setting')


def actual_browser_finally(namespace):
    # Execute the actual main finally; no browser/server or main setup is invoked.
    source = ast.parse(Path(browser.__file__).read_text())
    main = next(node for node in source.body if isinstance(node, ast.FunctionDef) and node.name == 'main')
    finalizers = [node.finalbody for node in main.body if isinstance(node, ast.Try) and node.finalbody]
    if len(finalizers) != 1:
        raise AssertionError('one actual browser main finalizer must supply the control')
    exec(compile(ast.Module(body=finalizers[0], type_ignores=[]), browser.__file__, 'exec'), namespace)


class BrowserFixtureCleanupTests(unittest.TestCase):
    def assert_zero_population(self, groups):
        for item in groups:
            self.assertFalse((Path('/proc') / str(item['child'])).exists(), 'actual finalizer left an unreaped owned child')
            with self.assertRaises(ProcessLookupError, msg='actual finalizer did not confirm zero private-group population'):
                os.killpg(item['process'].pid, 0)

    def test_actual_finally_normal_empty_fixture_has_confirmed_cleanup(self):
        with browser_cleanup_fixture([]) as (namespace, groups):
            actual_browser_finally(namespace)
            self.assertFalse(namespace['sampler'].is_alive())
            self.assertFalse(namespace['work'].exists())
            self.assertTrue((namespace['out'] / 'browser.json').is_file())
            self.assertTrue((namespace['out'] / 'resource-samples.json').is_file())

    def test_actual_finally_stops_child_when_leader_already_exited(self):
        with browser_cleanup_fixture(['exited']) as (namespace, groups):
            self.assertEqual(groups[0]['process'].returncode, 0)
            actual_browser_finally(namespace)
            self.assert_zero_population(groups)

    def test_actual_finally_stops_term_resistant_child_after_leader_termination(self):
        with browser_cleanup_fixture(['normal']) as (namespace, groups):
            actual_browser_finally(namespace)
            self.assert_zero_population(groups)

    def test_actual_finally_timeout_escalation_stops_whole_group(self):
        with browser_cleanup_fixture(['timeout']) as (namespace, groups):
            process = groups[0]['process']
            original_wait, requested = process.wait, []

            def shortened_wait(timeout=None):
                requested.append(timeout)
                return original_wait(timeout=min(timeout, .2) if timeout is not None else None)

            # TEST ONLY real wait shortening; production 15s/5s limits stay fixed.
            with patch.object(process, 'wait', side_effect=shortened_wait):
                actual_browser_finally(namespace)
            self.assertIn(15, requested, 'the actual production TERM wait supplied the timeout path')
            self.assert_zero_population(groups)

    def test_actual_finally_attempts_all_groups_and_retains_scratch_after_failed_stop(self):
        with browser_cleanup_fixture(['normal', 'normal'], cgroup_fault='first-stop-refused') as (namespace, groups):
            attempted, real_killpg = [], os.killpg
            real_pidfd_signal = signal.pidfd_send_signal
            failed = groups[-1]['process'].pid

            def fail_one_group(pgid, sig):
                if sig:
                    attempted.append(pgid)
                if pgid == failed and sig:
                    raise PermissionError('literal owned group stop failure')
                return real_killpg(pgid, sig)

            def fail_one_pidfd(descriptor, sig, *args, **kwargs):
                fields = (Path('/proc/self/fdinfo') / str(descriptor)).read_text().splitlines()
                pid = int(next(line.split(':', 1)[1] for line in fields if line.startswith('Pid:')))
                item = next((item for item in groups if pid in (item['process'].pid, item['child'])), None)
                if item is None:
                    raise AssertionError('cleanup tried signaling an unbound control pidfd')
                if sig:
                    attempted.append(item['process'].pid)
                if item['process'].pid == failed and sig:
                    raise PermissionError('literal owned group stop failure')
                return real_pidfd_signal(descriptor, sig, *args, **kwargs)

            with patch.object(browser.os, 'killpg', side_effect=fail_one_group), \
                    patch.object(signal, 'pidfd_send_signal', side_effect=fail_one_pidfd):
                try:
                    actual_browser_finally(namespace)
                except (OSError, RuntimeError):
                    pass
            self.assertEqual(set(attempted + namespace['cgroup_kill_attempts']), {item['process'].pid for item in groups},
                             'a first stop error must not suppress other owned group attempts')
            self.assertTrue(namespace['work'].is_dir(), 'unconfirmed stop must retain private fixture scratch')
            self.assertTrue((Path('/proc') / str(groups[-1]['child'])).exists(), 'injected refusal must reach a real living group')
            self.assertNotIn('process groups stopped', namespace['receipt'].get('cleanup', ''), 'do not claim cleanup on refusal')

    def test_actual_finally_preserves_scratch_until_bounded_sampler_is_stopped(self):
        with browser_cleanup_fixture([], blocked_sampler=True) as (namespace, groups):
            started = time.monotonic()
            try:
                actual_browser_finally(namespace)
            except RuntimeError:
                pass
            self.assertTrue(namespace['stop_samples'].is_set(), 'actual finalizer must reach sampler stop')
            self.assertLess(time.monotonic() - started, 3, 'sampler refusal must remain bounded')
            self.assertTrue(namespace['sampler'].is_alive(), 'literal sampler must still be alive at refusal')
            self.assertTrue(namespace['work'].is_dir(), 'scratch must not be removed while sampler lives')
            self.assertNotIn('process groups stopped', namespace['receipt'].get('cleanup', ''), 'unconfirmed sampler stop is not cleanup')


class DelegatedBrowserOwnershipTests(unittest.TestCase):
    # C-084 source mocks are not evidence of kernel delegation or subtree kill.
    assert_zero_population = BrowserFixtureCleanupTests.assert_zero_population

    def assert_authority_retained(self, namespace, groups):
        for record in (namespace['group_parent'], groups[0]['group']):
            observed = os.fstat(record['fd'])
            self.assertEqual((observed.st_dev, observed.st_ino), (record['dev'], record['ino']))
        group = groups[0]['group']
        info = (Path('/proc/self/fdinfo') / str(group['pidfd'])).read_text().splitlines()
        self.assertEqual(int(next(line.split(':', 1)[1] for line in info if line.startswith('Pid:'))), group['pid'])

    def require_mechanism(self):
        if not all(callable(getattr(browser, name, None)) for name in
                   ('bind_browser_group', 'stop_browser_groups')) or not hasattr(browser, 'cgroups'):
            self.skipTest('dependent cgroup control: owned binder/stopper mechanism is unavailable')

    def test_owned_group_binding_and_stop_mechanisms_are_available(self):
        for name in ('bind_browser_group', 'stop_browser_groups'):
            self.assertTrue(callable(getattr(browser, name, None)), 'missing owned browser cgroup mechanism: ' + name)
        self.assertTrue(hasattr(browser, 'cgroups'), 'missing existing delegated cgroup plumbing')
        with browser_cleanup_fixture(['normal']) as (namespace, groups):
            item = groups[0]
            binding = item['binding']
            self.assertIsNot(binding['parent'], namespace['group_parent'], 'retain a defensive parent record')
            self.assertIsNot(binding['group'], item['group'], 'retain a defensive launch record')
            self.assertIs(binding['group']['process'], item['process'])
            for field in ('pid', 'start_ticks', 'pidfd', 'path', 'fd', 'dev', 'ino', 'exclusive'):
                self.assertEqual(binding['group'][field], item['group'][field])
            member = next((row for row in binding['group'].get('members', []) if row['pid'] == item['child']), None)
            self.assertIsNotNone(member, 'retain the actual source-fixture child identity before it becomes a zombie')
            self.assertEqual(member['start_ticks'], item['child_start'])
            info = (Path('/proc/self/fdinfo') / str(member['pidfd'])).read_text().splitlines()
            self.assertEqual(int(next(line.split(':', 1)[1] for line in info if line.startswith('Pid:'))), item['child'])

    def test_binding_refuses_literal_capability_and_placement_defects(self):
        self.require_mechanism()
        cases = (('missing-delegation', 'delegation'), ('missing-group', 'identity'),
                 ('missing-kill', 'capability'), ('outside-placement', 'placement'),
                 ('nonexclusive-group', 'ownership'), ('supervisor-as-parent', 'parent'),
                 ('expired-global-deadline', 'deadline'))
        for defect, diagnostic in cases:
            with self.subTest(defect=defect), browser_cleanup_fixture(['normal']) as (namespace, groups):
                parent, group = dict(namespace['group_parent']), dict(groups[0]['group'])
                moved, extra_fd = None, None
                try:
                    if defect == 'missing-delegation':
                        (parent['path'] / 'cgroup.subtree_control').write_text('')
                    elif defect == 'missing-group':
                        moved = group['path'].with_name('moved-group')
                        group['path'].rename(moved)
                    elif defect == 'missing-kill':
                        (group['path'] / 'cgroup.kill').unlink()
                    elif defect == 'outside-placement':
                        namespace['cgroup_fault']['value'] = defect
                    elif defect == 'nonexclusive-group':
                        group['exclusive'] = False
                    elif defect == 'expired-global-deadline':
                        parent['deadline_monotonic_ns'] = time.monotonic_ns() - 1
                    else:
                        path = parent['path'] / 'supervisor'
                        extra_fd = os.open(path, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC)
                        observed = os.fstat(extra_fd)
                        parent.update(path=path, fd=extra_fd, dev=observed.st_dev, ino=observed.st_ino)
                    with patch.object(signal, 'pidfd_send_signal', side_effect=AssertionError('binding must never signal')):
                        with self.assertRaisesRegex(RuntimeError, '^browser-group-' + diagnostic + '$'):
                            browser.bind_browser_group(parent, group, groups[0]['process'])
                    self.assertFalse(namespace['cgroup_kill_attempts'], 'refuse before kill-file writes')
                    self.assertTrue((Path('/proc') / str(groups[0]['child'])).exists())
                    self.assert_authority_retained(namespace, groups)
                finally:
                    if moved is not None:
                        moved.rename(group['path'])
                    if extra_fd is not None:
                        os.close(extra_fd)

    def test_binding_refuses_literal_process_descriptor_and_directory_identity_defects(self):
        self.require_mechanism()
        for defect in ('wrong-process', 'wrong-pid', 'wrong-start', 'wrong-pidfd',
                       'wrong-parent-inode', 'wrong-group-inode', 'unbound-group-fd'):
            with self.subTest(defect=defect), browser_cleanup_fixture(['normal']) as (namespace, groups):
                parent, group = dict(namespace['group_parent']), dict(groups[0]['group'])
                process = groups[0]['process']
                if defect == 'wrong-process':
                    process = SimpleNamespace(pid=process.pid)
                elif defect == 'wrong-pid':
                    group['pid'] = groups[0]['child']
                elif defect == 'wrong-start':
                    group['start_ticks'] += 1
                elif defect == 'wrong-pidfd':
                    group['pidfd'] = groups[0]['child_pidfd']
                elif defect == 'wrong-parent-inode':
                    parent['ino'] += 1
                elif defect == 'wrong-group-inode':
                    group['ino'] += 1
                else:
                    group['fd'] = parent['fd']
                with patch.object(signal, 'pidfd_send_signal', side_effect=AssertionError('binding must never signal')):
                    with self.assertRaisesRegex(RuntimeError, '^browser-group-identity$'):
                        browser.bind_browser_group(parent, group, process)
                self.assertFalse(namespace['cgroup_kill_attempts'])
                self.assertTrue((Path('/proc') / str(groups[0]['child'])).exists())
                self.assert_authority_retained(namespace, groups)

    def test_actual_finally_stops_setsid_child_after_its_leader_exited(self):
        with browser_cleanup_fixture(['setsid']) as (namespace, groups):
            item = groups[0]
            self.assertEqual(item['process'].returncode, 0)
            self.assertEqual(owned_browser_identity(item['child'])[1], item['child'])
            actual_browser_finally(namespace)
            self.assert_zero_population(groups)
            with self.assertRaises(ProcessLookupError):
                os.killpg(item['child'], 0)

    def test_actual_finally_reaps_adopted_zombie_even_when_mock_kernel_population_is_zero(self):
        with browser_cleanup_fixture(['exited']) as (namespace, groups):
            item = groups[0]
            signal.pidfd_send_signal(item['child_pidfd'], signal.SIGKILL)
            deadline = time.monotonic() + 2
            while True:
                fields = (Path('/proc') / str(item['child']) / 'stat').read_text().rsplit(')', 1)[1].split()
                self.assertEqual(int(fields[19]), item['child_start'])
                if fields[0] == 'Z':
                    break
                self.assertLess(time.monotonic(), deadline, 'literal adopted child must become a zombie')
                time.sleep(.01)
            self.assertEqual((item['group']['path'] / 'cgroup.events').read_text(), 'populated 0\nfrozen 0\n')
            self.assertEqual((item['group']['path'] / 'cgroup.procs').read_text(), '')
            actual_browser_finally(namespace)
            self.assert_zero_population(groups)

    def test_actual_finally_stuck_population_is_bounded_and_retains_scratch(self):
        self.require_mechanism()
        with browser_cleanup_fixture(['exited']) as (namespace, groups):
            namespace['cgroup_fault']['value'] = 'stuck-population'
            started = time.monotonic()
            with self.assertRaisesRegex(RuntimeError, '^browser-group-stop$'):
                actual_browser_finally(namespace)
            self.assertLess(time.monotonic() - started, 23, 'unchanged 15/5/2-second stop bounds')
            self.assertTrue(namespace['work'].is_dir())
            self.assertNotIn('process groups stopped', namespace['receipt'].get('cleanup', ''))
            self.assert_zero_population(groups)

    def test_stop_refuses_replaced_registry_identity_before_any_signal(self):
        self.require_mechanism()
        for defect in ('replaced-directory', 'replaced-parent', 'wrong-process', 'wrong-pidfd'):
            with self.subTest(defect=defect), browser_cleanup_fixture(['normal']) as (namespace, groups):
                binding = groups[0]['binding']
                copied = {'parent': dict(binding['parent']), 'group': dict(binding['group'])}
                group, moved, replaced = copied['group'], None, None
                try:
                    if defect in ('replaced-directory', 'replaced-parent'):
                        replaced = group['path'] if defect == 'replaced-directory' else copied['parent']['path']
                        moved = replaced.with_name('old-owned-' + replaced.name)
                        replaced.rename(moved)
                        replaced.mkdir()
                    elif defect == 'wrong-process':
                        group['process'] = SimpleNamespace(pid=group['pid'])
                    else:
                        group['pidfd'] = groups[0]['child_pidfd']
                    with patch.object(signal, 'pidfd_send_signal', side_effect=AssertionError('unbound stop must never signal')):
                        with self.assertRaisesRegex(RuntimeError, '^browser-group-stop$'):
                            browser.stop_browser_groups(namespace['group_parent'], [copied])
                    self.assertFalse(namespace['cgroup_kill_attempts'])
                    self.assertTrue((Path('/proc') / str(groups[0]['child'])).exists())
                    self.assert_authority_retained(namespace, groups)
                finally:
                    if moved is not None:
                        replaced.rmdir()
                        moved.rename(replaced)


if __name__ == '__main__':
    unittest.main()

scratch/console-access-acceptance/docs/experiments/formal/console-session-clock-protocol.md

SHA256 9d5af92f4be624bb45adf9a6c5efa23b068472fea2a208f89e2076f416b6d8c1, 32106 bytes.

# Disposable controlled-time session checks

Status: prospective; **not run**. Issue #45's C2/ACCESS-1 requires packaged
idle and absolute session expiry. The existing native explicit-now test proves
its scoped adapter semantics; it does not establish packaged browser behavior.
This successor supplements the [console protocol](console-access-protocol.md)
without replacing its real reader TTL, signed rejection, recovery or other cells.
It is controlled-time expiry, not thirty-minute/eight-hour elapsed endurance.
It supplies no performance, outage, soak, delivery or package-build evidence.

The owner authorized this finite process-local fixture within existing deadlines.
Candidate artifact F is `8fb6f413179b094288316e25845c137440ba23fa`; actual fresh
#40/package payload identities, fresh #41, clean exact merged harness, independent
controls and reviewed admission are prerequisites for acceptance. Historical
ELF imports do not establish the new ELF's binding. No host clock mutation,
privilege, product flag or binary patch is allowed.

## Hook and control boundary

The sole interposed API is `clock_gettime(clockid_t, struct timespec *)` in a
fixture-only `.so`. Successful CLOCK_REALTIME reads in its original admitted
server PID add a validated nonnegative whole-second offset with overflow checks;
tv_nsec and underlying error behavior remain unchanged. All other clock IDs,
including MONOTONIC/RAW, are untouched. Do not hook time/gettimeofday/sleep/timer
APIs or silently broaden interception when the actual binary bypasses this path.
Resolve the underlying call using RTLD_NEXT with explicit initialization/error
handling. Invalid initialization or control permanently fails the fixture; an
ordinary-time fallback must never be credited as synthetic expiry.

The pinned [Rust SystemTime implementation](https://raw.githubusercontent.com/rust-lang/rust/b940084d7/library/std/src/sys/time/unix.rs)
selects CLOCK_REALTIME, and its
[Unix timespec path](https://raw.githubusercontent.com/rust-lang/rust/b940084d7/library/std/src/sys/pal/unix/time.rs)
calls libc clock_gettime. That source supports a hypothesis, not proof of the
new packaged ELF's import or running call path. Root must inspect that exact
ELF's interpreter/dynamic symbols before choosing interception. The
[loader's `--preload` option](https://man7.org/linux/man-pages/man8/ld.so.8.html)
applies to one executable rather than child execs, but direct
loader invocation keeps the loader as `/proc/PID/exe`, violating this protocol's
exact target-executable identity. The owner therefore selected the scoped
target-only LD_PRELOAD fallback before implementation. Set it only in the one
target exec's environment; the constructor clears LD_PRELOAD and the control
configuration before main, restores CLOEXEC and records actual fork/exec
isolation. Preserve the exact target ELF identity requirement. Never preload the
launcher, compiler, controller, grader, browser, driver, companion or normal
acceptance workloads. This selection is registered separately because it changes
the fixture's inheritance boundary; it is not runtime evidence that isolation
works.

Use a private anonymous AF_UNIX/SOCK_SEQPACKET socketpair, NONBLOCK+CLOEXEC,
with exactly one controller. Pass only the target endpoint to the server exec.
Before main/threading/fork, validate its type, consume mandatory initial offset0,
restore CLOEXEC, clear control/preload configuration from runtime environ and
record original PID/start identity. The packet is exactly24 bytes: eight bytes
`FCLKv1\0\0`, little-endian u64 sequence, little-endian u64 offset seconds.
Sequence starts0 and increases by1, offsets start0 and never decrease, maximum
offset28860, maximum64 packets. EAGAIN retains validated state; EOF, wrong type,
bad/closed FD, truncation/oversize, version/sequence/cap/decrease/overflow or
controller death permanently fails. Bound drains, retries, synchronization and
ledger work. A foreign fork PID returns unshifted time without reading control
or locking inherited synchronization; child exec must inherit neither helper
mapping, control configuration nor control FD.

## Independent evidence and literal oracle

`session_clock_oracle.py` imports no controller/shim transition logic. Its first
controls freeze the six offsets0,1,1799,1800,28799,28800 across clock IDs0/1/4.
Each probe row has exactly pid,sequence,offset_s,clock_id,raw_ns,returned_ns,
syscall_before_ns,syscall_after_ns. The raw call must lie in independently
captured matching raw-SYS_clock_gettime brackets, at most1s wide. Returned time
is raw+offset only for REALTIME and exactly raw otherwise, preserving nsec.
Missing rows, another PID, shifted monotonic, forged ordinary realtime, modified
nsec or mismatched sequence are named rejections. Wide/late clock observations
are inconclusive, not product failures or successes.

Compile a pinned Rust SystemTime/Instant probe and independent raw syscall
witness only after registration. A real500ms sleep has ordered raw monotonic
start-before/start-after/end-before/end-after brackets, total at most1s; Instant
elapsed must lie between the independent lower/upper elapsed bounds. Actual
compiler/toolchain, source/helper/probe/loader/libc hashes/build IDs and argv are
receipt inputs. A Rust probe alone does not establish the packaged server's
binding: the exact server PID must emit matching REALTIME calls during each
serialized request, bound to controller raw/monotonic request windows. Missing,
ambiguous, truncated or another-PID call evidence blocks acceptance.

Bind target executable and exactly one target helper mapping to independently
frozen hashes plus PID/start ticks/cgroup/dev/inode. Confirm target control type
and CLOEXEC. Independently observe controller/browser/driver/companion PIDs,
ordinary host-clock brackets and absence of helper maps/control keys/control FD.
At positive target offset1, a fork probe returns raw time without advancing
control sequence; after exec it has no helper, keys or FD. `/proc/PID/environ`
describes initial exec environment and cannot alone prove constructor unsetenv;
runtime/child observations must establish isolation. Forged maps, unpreloaded
target, helper/environment/FD escape and fork consumption are mandatory native
negative controls, not satisfied by fabricated pure-oracle records.

## Exact session boundaries

Use genuine resident/UV WebAuthn-issued memory sessions, never forged tokens or
edits to server state. Store only public session hashes and actual issuance,
expiry, baseline last-success and associated server-read timing. Pace every
dispatch through the unchanged550ms shared pacer;429 never substitutes for401
`sign in required`. Disable polling before the final session observations.

Use independent no-prior-cookie login contexts A/B so issuing A does not retire
B. A returns200 at its own baseline last-success+1799; untouched B returns exact
401 at its baseline+1800, with absolute expiry still later. A's successful read
refreshes A and cannot be reused as B's at-boundary oracle. Record different
actual baselines and choose request order accordingly; do not assume equal
issuance seconds.

In a separate disposable state, keep the same genuinely issued C token alive
at issuance+1000k for k1..28, then require200 at issuance+28799 and exact401 at
issuance+28800. Every preceding gap is below1800 and immutable public absolute
expiry equals issuance+28800, so idle expiry/reauthentication cannot explain the
final refusal. No token replacement, reissue/revoke or owner step-up is allowed.
The oracle requires all32 literal observations: A/B plus C's28 keepalives and
two boundary reads; actual token hashes, prior-seen progression, statuses,
refusal messages and server-call seconds must match independently bound inputs.
Wrong baseline/token, missing keepalive, changed boundary, expired200,
429/403/transport error and wrong error text are named checker defects.

Calculate forward-only offset from independent kernel observations and confirm
applied sequence. For adjacent target seconds keep offset unchanged and wait
in real time; never move backward to repair an overshoot. Late/ambiguous reads
remain inconclusive and require a new fixture. After actual server401, explicit
Check session must lock the real browser and clear protected memory while browser
Date remains ordinary. A client Date-only timer cannot prove server expiry.

## Containment, antirollback and completion

Preserve inner240s, existing expired-cursor1200s, outer1800s, browser4GB cap,
CPU200%,tasks512,no swap and512MiB fixture ceiling. Bound the clock ledger at
1MiB and fail on truncation. Clock manipulation applies only to disposable
expiry fixtures; all real reader, performance, outage and soak gates remain
ordinary-clock. Actual host rollback must be detected, not clamped. Forward
steps naturally age300s owner freshness/challenges; do ordinary setup first,
extend no policy and ensure TLS validity covers both ordinary and shifted time.
TLS/challenge/process errors never stand in for semantic expiry.

The future access watermark/telemetry and credentials make this state unsuitable
for reuse. Stop all descendants/listeners, archive raw public failures/hashes and
verify stop, then remove only owned fixture credentials, profiles, private keys,
future state, sockets and probe/helper build outputs. Never reset watermark or
recover/restart this state in ordinary time; preserve immutable package inputs.

Root first runs this exact prospective-control command on the registration:

```sh
python3 -B tools/resource_group.py -- python3 -B -m unittest discover -s tools/ui -p test_session_clock.py -v

The initial named availability assertion checks the declared Python controller, C shim and Rust probe source paths. Its expected red is missing fixture mechanism, not a product defect or behavioral rejection. No broken fallback is invented. After that captured red, implement separately and rerun unchanged literal controls. Availability-green is not interception or expiry evidence: compiled actual-ELF/loaded-PID/raw-clock/frame/child-isolation controls, including native unpreloaded rejection, remain mandatory before browser admission. All these native and packaged controls are not run at registration. Freeze their actual paths/hashes/argv in a subsequent preflight; missing tooling remains an actionable prerequisite within scope rather than an invented passing result.

Lifecycle and frozen-image regressions

Static review of mechanism c8fbf41 found three defects before native admission. The separate prospective controls retain the clock oracle and every existing expected outcome. They run only inside the default resource group, using small owned disk fixtures and restoring the test process's previous subreaper setting.

  1. A leader exits after a same-PGID child installs SIGTERM ignore. Closing the fixture must force-stop and reap that owned group, even when leader wait has already completed. Test cleanup independently kills/reaps the child on red.
  2. A literal fake compiler writes public stderr and a partial object, then forks a TERM-resistant child. A private clock trace leaves 0.75s of the unchanged 240s deadline. TimeoutExpired must remain visible; descendants must stop and both captured output and partial build evidence must be archived before removing the owned build directory. No real compiler is run by this control.
  3. Real owned executable/helper files change after their original literal hashes and device/inode witnesses are frozen. Mocked /proc metadata agrees with the changed paths; the checker must still refuse against expected frozen fields: executable_sha256/executable_identity and helper_sha256/helper_identity. The exact refusals are isolation-target-frozen and isolation-helper-frozen. Where the legacy checker lacks that witness parameter, the test invokes its unchanged path and records actual acceptance as the named assertion failure.

These fixtures are harness-defect controls, not packaged expiry or compiler qualification. Root records their actual red before a separate production fix.

An additional identity control replaces each frozen executable/helper path with an identical-byte file on a new inode. It separately forges the loaded helper mapping's device and inode while retaining the original file. Original hashes alone cannot admit either replacement: executable replacement must refuse with isolation-target-frozen; helper replacement or mismatched mapped device/inode must refuse with isolation-helper-frozen. Existing literal controls and the clock oracle stay fixed. The fake compiler and accelerated test-only monotonic trace above are neither a real 240-second run nor real compiler-binding acceptance.

Two serial state fixtures and browser cleanup registration

Prospective scope acknowledged by C-069 before implementation. Controls and packaged browser acceptance are not run on this registration. The older single-PID check_sessions controls remain byte-identical compatibility checks. They cannot admit the packaged adapter: the original literal order followed by C's absolute boundary exceeds the offset ceiling in one process. Use two freshly created serial states while retaining all 32 observations, statuses, error strings and wall-second bounds.

The actual registration result at b1e7e83 records four missing-checker assertions and five actual-finalizer counterexamples; independent cleanup completed. The AB/C oracle is now implemented separately using the unchanged session-semantic validator and observed rows. Its source checks are recorded separately. Finalizer ownership needs the prospective amendment below; native timing and browser acceptance remain pending.

The new independent interface is check_session_fixtures(rows, sessions, fixtures) -> None; rejection raises a named ValueError. It must not mutate any input or rewrite observed PIDs to feed the legacy single-PID checker. Fixtures have exactly the keys AB and C; the fixed session mapping is A/B to AB and C to C. A/B share AB's positive integer server PID; C's positive integer PID differs. Boolean and floating values are not integer identities or timestamps. There is no implicit mapping, single-PID fallback, extra fixture or unbound row.

Each fixture record carries the following independently collected inputs:

Fields Required binding
candidate_commit, package_sha256, executable_sha256, helper_sha256 Full source commit and lower-case SHA-256 identities, identical across AB/C, separately admitted against immutable package/source inputs
process_binding Actual session_clock.process_binding receipt: PID, positive start ticks, nonempty cgroup, matching executable/helper hashes, libc path/hash and nonempty helper mappings; original dev/inode/hash/maps checks remain mandatory native admission
state_before Canonical absolute state path, device/inode, created_monotonic_ns, observed_monotonic_ns, initial_entries=[], copy_source=None, descriptor_held=True
state_after Same canonical path/device/inode and a later observed_monotonic_ns inside that fixture's live interval
run_started_monotonic_ns, deadline_monotonic_ns Identical across both fixtures; deadline is exactly run start plus 240,000,000,000 ns
started_monotonic_ns, stopped_monotonic_ns Actual start and completed stop observations inside the one global deadline
owned_groups Nonempty, duplicate-free inventory of launched private {pgid, start_ticks} identities, including the bound server
stop_observations Exactly one matching identity per launched group with actual observed_monotonic_ns, integer population=0 and boolean confirmed=True, after its requests and no later than completed stop

AB and C state paths must differ, and their (device, inode) pairs must differ. The actual adapter exclusively creates each directory without reusing a name, holds its protected descriptor, observes empty contents before server start and keeps the original identity through the later observation. It performs no state copying. Creation precedes the empty observation, which precedes server start. Metadata assertions alone do not prove that no copying occurred; actual adapter ordering and protected descriptor observations are prerequisites. Literal checker receipts do not constitute filesystem or native process evidence.

All AB owned groups must be confirmed empty before C starts. AB completed stop strictly precedes C start. A prior stop boolean, leader exit, omitted group, duplicate observation, wrong start identity or still-populated group cannot satisfy this ordering. The final outer resource-group stop receipt is additional evidence and cannot replace either fixture's stop observation.

Every row retains the original fields and adds actual unshifted request_before_monotonic_ns, server_call_monotonic_ns and request_after_monotonic_ns. The matching fixture contains the entire request window; the server call lies inside it. Dispatches preserve the unchanged 550ms minimum gap over the whole sequence, including the AB/C transition. Do not reset the pacer or global deadline for C. Setup, both serial fixtures and their stops must fit the same inner 240 seconds. Any overrun is a preserved failure, not permission to extend time. Outer 1800 seconds, browser 4GB, CPU200%, tasks512, no swap, 512MiB fixtures, 1MiB ledger, 64 frames and offset at most 28860 remain unchanged. Each controller starts a fresh forward-only sequence at zero and independently passes the existing frame/native isolation checks.

Native timing prerequisite: server_call_monotonic_ns must be a direct unshifted clock witness from the same REALTIME shim invocation, bound to its PID/TID and applied sequence. The current native ledger lacks that witness. Controller receive time and wall-time subtraction cannot reconstruct it. Register and independently control the actual adapter before browser admission, preserving the original clock-return/prototype semantics, at most 256 bytes per record and 1MiB total. If an exact witness cannot fit, a directly witnessed monotonic bracket needs a separately registered shape before implementation. The synthetic exact timestamps below establish neither interception nor native time attribution. Genuine resident/UV-issued sessions, trusted production URL, request-to-shim joins, secret-safe archives and all prior native controls remain separate admission prerequisites; #41 must complete before browser acceptance.

SessionFixtureBindingTests supplies one valid independent literal receipt pair, verifies no input mutation and rejects exact-key/image/process mismatch, reused PID, crossed/unbound row, aliased/copied/nonempty/replaced state, missing or duplicate stop evidence, nonzero population, overlap, deadline reset/overrun, out-of-window reads and a 549,999,999ns gap within a state and across the state boundary. Original missing keepalive, idle/absolute seconds, last-seen progress, 401 sign in required and 429/expired-200 rejections remain fixed. Fixture diagnostics are session-fixture-keys, -images, -pid, -process, -state, -fresh, -deadline, -order, -stop, -row, -window and -pacing. Each suffix uses the full session-fixture- prefix. Original semantic diagnostics remain unchanged. The initial named callable assertion is expected to report missing explicit two-state session fixture checker. Until that mechanism exists, an assertion at this point is availability evidence, not a demonstrated malformed-receipt rejection.

BrowserFixtureCleanupTests executes only the actual live_browser_check.main finally AST with synthetic owned processes. No browser, package, server or main setup is launched. A parent records its fork child's PID/start identity atomically before releasing a gate for risky child setup. The fixtures have private process groups and finite 45-second lifespans; a test-only Linux subreaper and pidfds permit independent cleanup without signaling reused PIDs. The prior subreaper setting is restored. Scratch is removed only after all owned process identities/groups and the sampler are confirmed stopped; missing identity or unconfirmed cleanup retains the control directory. A setup or test body exception also retains it after independent pidfd stop/reap, even when that cleanup succeeds. Before any successful-directory removal, the control writes an exclusive bounded 32KiB cleanup-evidence.json: actual identity/stop/reap outcomes, bracketed group-zero observations, sampler/subreaper outcomes, bounded marker/script/log identities and SHA-256 hashes, and the original exception type/message. Failed directories retain those raw files and the generated literal child script; stderr identifies the directory for root archival. The finalizer under test may already have erased its own work subtree; record that fact without inventing replacement evidence. Successful controls alone remove confirmed-clean scratch.

The literal controls require cleanup after leader exit, force-stop of a TERM-resistant child after leader termination, timeout escalation, and attempts for every owned group after one real group's stop is deliberately refused. A stop refusal retains scratch and cannot claim stopped groups. A real bounded sampler that remains alive after the unchanged two-second join likewise retains scratch and cannot claim cleanup. An empty-process positive control must finish the actual finalizer, stop its sampler and publish both public JSON receipts. The timeout control explicitly shortens only its real Popen.wait calls to at most 0.2 seconds; production 15-second TERM and five-second KILL waits remain fixed. This is a descendant-cleanup control, not elapsed native timeout evidence. The five negative cleanup methods may demonstrate existing cleanup defects only when root actually runs them and confirms setup reached the finalizer.

Root runs the ten new methods through the launcher after publishing the exact source pins, capped driver and a fresh full reservation/census:

python3 -B tools/resource_group.py -- env PYTHONPATH=tools/ui python3 -B -m unittest -v test_session_clock.SessionFixtureBindingTests test_role_matrix.BrowserFixtureCleanupTests

After preserving the actual red, implement the admitted correction separately and rerun these unchanged controls plus both complete existing test files. This source-check command does not authorize real browser acceptance. Actual package/helper/process/maps, state/timing and owned-group receipt bindings need their own frozen native preflight; passing fabricated metadata never supplies that evidence.

Delegated browser launch ownership amendment

Prospective scope is C-084, acknowledged in X-140. This supersedes the proposed PIDFD process-group signaling mechanism. It changes cleanup authority to exclusively created delegated cgroup subtrees, retaining the five original failed-stop outcomes, empty positive, exact child reaping and all prior session/clock/status controls. Registration is not run. Production finalizer, native clock helper and packaged adapter remain unchanged here.

Reuse tools/bench/labs/completion/cgroups.py and enter_group.py, with the outer launcher's --delegate. Before delegation, hold the fresh owned service directory descriptor and verify its aggregate 4GB/3.5GB high, CPU200%, tasks512 and no-swap limits. delegate() moves the controller into supervisor; that directory is not the owned service ancestor and its direct limits do not replace the retained parent aggregate cap. Hold the parent identity throughout every launch and cleanup. Exclusively create each subgroup beneath that parent, set/read its explicit limits no larger than the parent, and hold its directory descriptor before launch. enter_group.py verifies placement before executing the target; descendants inherit it across setsid. Refuse missing delegation, subgroup, kill capability or actual placement. No numeric PID/PGID signal fallback is admitted.

Two narrow functions constitute the prospective source interface:

Interface Owned inputs and required behavior
bind_browser_group(parent, group, proc) Validate held parent/subgroup identities, exclusive creation provenance, exact Popen object, original PID/start ticks, held matching pidfd and actual placement; return defensive value copies as {'parent': parent_record, 'group': group_record} without signaling
stop_browser_groups(parent, bindings) Revalidate the retained registry and directory identities before signaling; attempt every owned group despite another failure; retain separate kernel-empty and child-reaped observations; aggregate failure as RuntimeError('browser-group-stop')

The parent record is {path, fd, dev, ino, deadline_monotonic_ns}. The group record is {path, fd, dev, ino, exclusive, process, pid, start_ticks, pidfd}. Paths are canonical owned directories; fd is the held no-follow directory descriptor and dev/ino are its original identity. The group records the exact launch process, positive original pid/start_ticks, and separately held matching pidfd. The launcher owns these descriptors through stop/archive; the independent test guardian holds different pidfds. The returned records must not alias mutable input dictionaries. The returned group additionally retains members, independently witnessed {pid, start_ticks, pidfd} records from the live admitted subtree; the source fixture requires its actual child to be bound before it becomes a zombie. The exclusive=True observation records an actual successful no-reuse mkdir in the owned launch path. Metadata alone does not prove creation provenance or pre-exec placement: native source ordering and actual kernel observations remain prerequisites. These functions do not accept arbitrary user-selected cgroups as cleanup authority.

Binding refusals are exact RuntimeError diagnostics: browser-group-delegation, -identity, -capability, -placement, -ownership, -parent and -deadline, each with the full browser-group- prefix. A refusal occurs before any signal or kill-file write. Replaced parent/subgroup paths, mismatching held descriptors, forged Popen/PID/start/pidfd and stale registry records cannot authorize stop. An unbound group stays untouched while the other registered groups still receive their independent stop attempts.

Use only PIDFD-bound TERM for currently witnessed members of the owned subtree, with the unchanged 15-second grace. Then the retained subgroup's cgroup.kill receives 1 if live members remain, followed by at most five seconds to observe cgroup.events populated 0. The kernel contract includes descendant subgroups and handles concurrent forks/migrations. It also excludes zombies from cgroup.procs; populated 0 alone is not child reaping. Keep the owned test/runtime subreaper setting through all launches and restore its previous value after cleanup. Reap exact adopted identities (for example, PIDFD-bound waitid), and separately confirm their /proc identities are absent. Record both facts before removing any private scratch. Stop the sampler with the unchanged two-second join; unconfirmed sampler/group/reaping retains scratch and cannot publish a successful cleanup claim. Archive bounded diagnostics before a close failure. All stop attempts continue after another group's refusal.

A binder-time snapshot does not establish ownership of later runtime forks or guarantee their zombie reaping. The source fixture has one independently known child already live at binding; it cannot establish native completeness. Before production/native admission, register a truthful retained descendant collection and exact reaping strategy that covers later forks and setsid, without arbitrary foreign PIDs or broad waitpid(-1). A modeled zero population never substitutes for that missing ownership evidence.

The single deadline_monotonic_ns is run start plus 240,000,000,000ns. Both serial states, delegation/setup, dispatch and stop share it; no reset at C. Local 15/5/2 bounds never extend that deadline. Any overrun is a preserved failure; bounded identity-safe failure cleanup still occurs under outer1800. Original 550ms global pacing and every frame/offset/ledger bound remain fixed.

The existing BrowserFixtureCleanupTests retain all six methods/outcomes. Their failed-stop injection now covers the old killpg, owned PIDFD signals and the modeled subgroup kill write, with the same requirement that one real group remains living while all other groups are attempted. The old timeout continues to shorten only real Popen.wait to 0.2s and require the requested production15s path. DelegatedBrowserOwnershipTests adds seven methods:

  • one explicitly named binder/stopper availability assertion;
  • seven literal delegation/group/kill/placement/creation/parent/deadline defects;
  • seven original process/descriptor/directory identity defects;
  • an actual setsid TERM-resistant child after its leader exits;
  • an actual adopted zombie when modeled population is zero;
  • bounded stuck population with scratch retention and exact child reaping;
  • four stale-registry defects, including replaced parent and subgroup paths.

Until both functions and existing cgroup plumbing exist, the two defect tables, stuck-population and stale-registry methods are explicit dependent skips. They do not report rejected input when their implementation is absent. The two new real-process methods still execute the actual old finally. Prospective unchanged production counts are 13 methods: one empty positive, five old and two new cleanup failures, one named availability failure, and four dependent skips. These are predictions, not recorded outcomes. After a separate admitted repair, all13 must execute with no skips/failures.

The source fixture exclusively creates ordinary scratch directories and held directory FDs, models cgroup controller/cap/event/procs/placement reads, and intercepts only exact owned kill-file writes (path or FD) into signals through its own retained pidfds. Its process/zombie/reaping observations are real; its cgroup placement/population/subtree-kill observations are source mocks. This cannot demonstrate kernel delegation, real pre-exec placement, concurrent subtree kill or actual aggregate enforcement. A later admitted delegated kernel cell must independently establish those facts with the exact source, parent limits, owned subgroup identities and raw stop/reap observations. Original retained failure directories are not edited or removed. New failures retain generated scripts/atomic markers/logs and the bounded independent cleanup evidence after all owned processes are stopped/reaped; successful fixtures alone remove confirmed-clean scratch.

Root's prospective source-only command (fresh census/full1GiB reservation, default16/20GiB/no-swap/outer1800, exact frozen driver/source preflight):

python3 -B tools/resource_group.py -- env PYTHONPATH=tools/ui python3 -B -m unittest -v test_role_matrix.BrowserFixtureCleanupTests test_role_matrix.DelegatedBrowserOwnershipTests

This cell does not use --delegate: all its cgroup interfaces are source mocks, while its real synthetic descendants remain under the enforced outer service. The future actual kernel/browser cell requires --delegate and separate scope.