From 49223e172c114fe16870dde75fe7f734bce67579 Mon Sep 17 00:00:00 2001 From: Peter van Tol Date: Tue, 29 Sep 2026 14:38:56 +0200 Subject: [PATCH 1/5] Add native macOS non-root EP wheel qualification evidence --- .../ENGINEERING_PLATFORM_ROADMAP.md | 15 + .../EP_SERVER_DEPLOYMENT_AND_DISCOVERY.md | 5 + .../EP_SERVER_MACOS_NONROOT_2_3_105.md | 82 ++++ .../EP_SERVER_SYSTEM_MULTI_INSTANCE_V1.md | 6 + .../ep_nonroot_lifecycle_macos_r27.py | 253 +++++++++++++ tools/qualification/ep_nonroot_macos_r27.py | 352 ++++++++++++++++++ 6 files changed, 713 insertions(+) create mode 100644 docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md create mode 100644 tools/qualification/ep_nonroot_lifecycle_macos_r27.py create mode 100644 tools/qualification/ep_nonroot_macos_r27.py diff --git a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md index ff13c08d..8b623afb 100644 --- a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md +++ b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md @@ -20,6 +20,21 @@ partial-deletion SIGKILL recovery and all 15 EP lifecycle crash cells. This EP-owned subset is `PROCESS_CRASH_QUALIFIED`; the note creates no new node, does not change broader OI-2 status or claim installer/reboot acceptance. +## EP Server native macOS non-root runtime — 2026-09-29 + +The released 2.3.105 wheel has [bounded native foreground evidence](../engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md) +under a separate UID 20000 on macOS arm64/Python 3.14.7. Its real Server/API +readback bound the expected instance and published wheel digest; authenticated +disposable consumer scope, wrong-identity rejection, filesystem denial, +same-UID A/B separation, a synthetic cross-UID denial, missing-provider +UNAVAILABLE state and normal restart passed. This narrows the missing +runtime/readiness portion of OI-2 and OI-5 without changing their parent +statuses. System service registration, reboot and live provider login remain +outside this native qualification. The EP-owned preserve/restore continuation +is still under diagnosis after a non-root runtime-slot installation failure. +No machine-readable DAG in this repository contains OI-2 or OI-5 IDs; no new +DAG node or parallel backlog is created. + ## Release and operational installation lifecycle V1 — active coordinated plan Repository evidence recorded on 2026-09-09 reads `origin/main` as diff --git a/docs/engineering/EP_SERVER_DEPLOYMENT_AND_DISCOVERY.md b/docs/engineering/EP_SERVER_DEPLOYMENT_AND_DISCOVERY.md index 131c25f9..e8f611e1 100644 --- a/docs/engineering/EP_SERVER_DEPLOYMENT_AND_DISCOVERY.md +++ b/docs/engineering/EP_SERVER_DEPLOYMENT_AND_DISCOVERY.md @@ -24,3 +24,8 @@ invokes the EP-owned provisioner. It does not construct a plist, runtime, provider context, migration or cleanup plan. A real fresh-Mac cold boot and provider-login fan-out remain joint installer acceptance; source qualification does not claim that live-host result. + +The [2.3.105 native macOS non-root evidence](EP_SERVER_MACOS_NONROOT_2_3_105.md) +qualifies a supervised foreground Server and its real API under a separate +test UID. It does not imply this deployment target's LaunchDaemon, cold boot, +provider login or joint installer acceptance. diff --git a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md new file mode 100644 index 00000000..09d0c74c --- /dev/null +++ b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md @@ -0,0 +1,82 @@ +# EP Server 2.3.105 macOS non-root qualification + +This is the bounded EP-owned evidence for LANE_2 registration revision 27, +assignment `L2-EP-NONROOT-RUNTIME-CONFORMANCE-V1-20260929`. The authoritative +operator record is [Forge #142](https://github.com/pcvantol/forge/issues/142). +The existing OI-2 lifecycle and OI-5 service/readiness nodes remain the owning +roadmap subset. None of the repository's machine-readable DAG files defines +those node IDs, so this qualification adds no parallel DAG or invented node. + +## Exact released artifact + +| Field | Readback | +| --- | --- | +| Release | `engineering-platform-v2.3.105`, `RELEASE_COMPLETE` | +| Release source | `ad44263f6ec87ea018cda11f053fa12521ae9d79` | +| Published wheel SHA-256 | `22dd1e49c263b55dc9eee396810a09fc43509984fe685f3c00d26289d55e8adc` | +| Release receipt SHA-256 | `0b3ebeaef44c1af7808e4bdccf88bedf555e3a94e4ba5b30e1f26fab04eda1fb` | +| Interpreter | macOS arm64, Python 3.14.7; wheel requires `>=3.14,<3.15` | +| Actual Server store schema | 72 from the released source, installed module and live API | + +The registration's `EP_STORAGE_SCHEMA=68` does not match the released Server +store schema 72. The wheel and release receipt digests match exactly; the +schema discrepancy is retained as a registration correction, not applied to +the published bytes or live response. + +## Native foreground matrix + +The locally admitted disposable account had EUID/EGID 20000, no administrator +or remote-login group, SecureToken disabled and no APFS/FileVault cryptographic +membership. A real process under that UID loaded `engineering_platform` +from a noneditable venv outside the checkout. The process inventory showed +the macOS Python 3.14.7 app executable, and the real loopback HTTP response +reported its own instance ID, version 2.3.105 and observed exact wheel digest. +The test used a scrubbed environment with explicit HOME and PATH; macOS's +`__CF_USER_TEXT_ENCODING` injection was the only allowed extra variable. + +| Case | Result and boundary | +| --- | --- | +| Product initialization and A/B | Distinct disposable identities and simultaneous real HTTP servers; logical instance separation under the same UID | +| Expected identity and release | Real HTTP 200, same expected instance, version and observed wheel digest | +| Wrong expected instance | `EP_SERVER_INSTANCE_ID_MISMATCH` and nonzero exit | +| Scoped API | A product-created disposable consumer received authenticated v1.1 identity/readback; absent bearer returned 401 and wrong project scope 403. The token stayed local and was never printed in evidence | +| Filesystem | Test UID could not write the installed package; a non-writable own data parent was rejected without global permission repair | +| Cross-UID | A synthetic 0600 file owned by another already available UID was unreadable by the test UID; this is not a second EP instance | +| Provider absence | Codex and GitHub reported `UNAVAILABLE`, with no overall provider READY | +| Normal restart | Same instance, release and scoped API identity after exact-child stop/start; provider status remained `UNAVAILABLE` | +| Cleanup | Exact child stopped; independent process and listener readback found no own server | + +These are real Server/process/API observations. They do not establish a +LaunchDaemon, physical reboot, live provider login, service-account installer, +production instance or full installer acceptance. The user environment was +not borrowed. No production credential, Keychain or other lane resource was +read or changed. + +## Reproduction + +`tools/qualification/ep_nonroot_macos_r27.py` takes explicit absolute paths +for the account's private test home, downloaded wheel, installed noneditable +venv and a synthetic 0600 other-UID fixture. Run it with that venv's Python +`-I` after an operator-approved, local role drop and `env -i` with only +`HOME`, `PATH`, `LANG`, `LC_ALL`, `TMPDIR` and +`PYTHONDONTWRITEBYTECODE`. Pass `--account`, `--expected-uid`, `--home`, +`--wheel`, `--venv` and `--synthetic-sibling-fixture`. The harness itself +must never run as root, use a checkout import as EP authority or bypass +`Requires-Python`. It creates only disposable data in the specified home and +supervises its exact Server children. + +`tools/qualification/ep_nonroot_lifecycle_macos_r27.py` uses the same +published wheel and an instance-owned product root. It writes a service plist +only inside its disposable launch stand-in directory, never in macOS system +service directories. The provider executables deliberately fail and their +synthetic records serve only to exercise preserve/restore state transitions; +they do not qualify a provider login. The controller starts a real initial +foreground Server and the product's own live health verifier checks it. + +## Lifecycle boundary + +The first native lifecycle attempt under UID 20000 stopped during the +product-owned immutable runtime-slot installation, before preserve/restore. +The underlying package installer error is under diagnosis in the same +assignment; preserve/restore is not claimed PASS from the interactive-UID +development dry-run. diff --git a/docs/engineering/EP_SERVER_SYSTEM_MULTI_INSTANCE_V1.md b/docs/engineering/EP_SERVER_SYSTEM_MULTI_INSTANCE_V1.md index 2d90c2f0..9bca6b58 100644 --- a/docs/engineering/EP_SERVER_SYSTEM_MULTI_INSTANCE_V1.md +++ b/docs/engineering/EP_SERVER_SYSTEM_MULTI_INSTANCE_V1.md @@ -356,3 +356,9 @@ foreign-operation/instance, provider-demotion and restore-after-purge controls remained enforced by the reusable harness. This qualifies the EP-owned process-crash subset with a filesystem-only service adapter. It does not qualify a physical reboot, power loss, production service or installer. + +The separate [macOS non-root 2.3.105 qualification](EP_SERVER_MACOS_NONROOT_2_3_105.md) +records a real foreground Server/API under UID 20000, scoped disposable +authentication, filesystem and provider-negative cases, and normal restart. +Its EP-owned preserve/restore continuation retains a distinct service-adapter +boundary and is not inferred from the process-crash results above. diff --git a/tools/qualification/ep_nonroot_lifecycle_macos_r27.py b/tools/qualification/ep_nonroot_lifecycle_macos_r27.py new file mode 100644 index 00000000..e1db39d5 --- /dev/null +++ b/tools/qualification/ep_nonroot_lifecycle_macos_r27.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python3 +"""R27 EP preserve/restore on disposable roots with a local service adapter.""" +import hashlib +import argparse +import json +import os +from pathlib import Path +import plistlib +import pwd +import socket +import subprocess +import sys +import tempfile +import time +import urllib.error +import urllib.request + +from engineering_platform import system_instance_provisioner as provisioner +from engineering_platform import system_installation_topology as topology +from engineering_platform import system_provider_context as providers +from engineering_platform import system_server_service as services + +ACCOUNT = "" +HOME = Path("/") +WHEEL = Path("/") +EXPECTED_UID = -1 +DIGEST = "sha256:22dd1e49c263b55dc9eee396810a09fc43509984fe685f3c00d26289d55e8adc" +REVISION = "ad44263f6ec87ea018cda11f053fa12521ae9d79" + +def configure(): + global ACCOUNT, HOME, WHEEL, EXPECTED_UID + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--account", required=True) + parser.add_argument("--expected-uid", type=int, required=True) + parser.add_argument("--home", type=Path, required=True) + parser.add_argument("--wheel", type=Path, required=True) + args = parser.parse_args() + ACCOUNT, EXPECTED_UID = args.account, args.expected_uid + HOME, WHEEL = args.home, args.wheel + require(EXPECTED_UID > 0 and HOME.is_absolute() and WHEEL.is_absolute(), + "Explicit absolute qualification inputs required") + +def require(value, error): + if not value: + raise RuntimeError(error) + +def port(): + with socket.socket() as sock: + sock.bind(("127.0.0.1", 0)) + return sock.getsockname()[1] + +class Controller: + def __init__(self, launch_root): + self.launch_root = launch_root + self.interpreters = {} + self.children = {} + self.started_pid = None + + def register(self, instance, interpreter): + paths = services.instance_default_paths(instance, self.launch_root) + paths.launch_daemons_dir.mkdir(parents=True, exist_ok=True) + definition = services.instance_service_definition(instance, interpreter=interpreter) + paths.plist_path.write_bytes(plistlib.dumps(services.instance_plist_payload(paths, definition))) + self.interpreters[instance.instance_id] = interpreter + return {"result": "REGISTERED", "label": instance.service_label} + + def quiesce(self, instance): + child = self.children.pop(instance.instance_id, None) + if child is not None and child.poll() is None: + child.terminate() + try: + child.wait(timeout=12) + except subprocess.TimeoutExpired: + child.kill() + child.wait(timeout=5) + return {"result": "QUIESCED"} + + def start(self, instance): + interpreter = self.interpreters[instance.instance_id] + env = { + "HOME": str(HOME), + "PATH": "/usr/bin:/bin:/usr/sbin:/sbin", + "LANG": "C", "LC_ALL": "C", + "TMPDIR": str(HOME), + "PYTHONDONTWRITEBYTECODE": "1", + **providers.server_environment(instance), + } + log = open(instance.root / "supervised-server.log", "ab", buffering=0) + child = subprocess.Popen( + [str(interpreter), "-I", "-m", "engineering_platform.server", "serve", + "--data-root", str(instance.data_root), "--expected-instance-id", instance.instance_id], + cwd=HOME, env=env, stdin=subprocess.DEVNULL, stdout=log, + stderr=subprocess.STDOUT, start_new_session=True, + ) + log.close() + self.children[instance.instance_id] = child + self.started_pid = child.pid + bind_port = json.loads((instance.data_root / "server.json").read_text())["bind_port"] + deadline = time.monotonic() + 20 + while time.monotonic() < deadline: + if child.poll() is not None: + raise RuntimeError(f"Adapter foreground server exited: {child.returncode}") + try: + with urllib.request.urlopen( + f"http://127.0.0.1:{bind_port}/health", timeout=2 + ) as response: + report = json.load(response) + if report.get("instance_id") == instance.instance_id: + return {"result": "RUNNING"} + except (OSError, ValueError, urllib.error.HTTPError): + pass + time.sleep(0.2) + raise RuntimeError("Adapter foreground server did not answer") + + def loaded(self, instance): + child = self.children.get(instance.instance_id) + return child is not None and child.poll() is None + + def remove(self, instance): + self.quiesce(instance) + paths = services.instance_default_paths(instance, self.launch_root) + paths.plist_path.unlink(missing_ok=True) + return {"result": "REMOVED"} + +def main(): + uid, gid = os.geteuid(), os.getegid() + account = pwd.getpwnam(ACCOUNT) + require(uid == EXPECTED_UID and uid == account.pw_uid and gid == account.pw_gid, + "Wrong lifecycle process identity") + require(HOME.resolve() == Path(account.pw_dir).resolve() + and HOME.stat().st_uid == uid + and HOME.stat().st_mode & 0o077 == 0, + "Test home is not private and owned by the exact process identity") + require(sys.version_info[:2] == (3, 14), "Wrong Python version") + require(hashlib.sha256(WHEEL.read_bytes()).hexdigest() == DIGEST[7:], + "Wrong published wheel digest") + work = Path(tempfile.mkdtemp(prefix="ep-r27-lifecycle-", dir=HOME)) + product_root = work / "product" + launch_root = work / "launch-standin-only" + launch_root.mkdir() + controller = Controller(launch_root) + engine = provisioner.SystemInstanceProvisioner( + product_root, controller=controller, launch_daemons_dir=launch_root, + account_lookup=pwd.getpwnam, + ) + instance_id = "ep-r27-native-instance-001" + instance = topology.system_instance_topology( + engine.product, instance_id=instance_id, display_label="EP R27 native lifecycle", + service_account=ACCOUNT, + ) + try: + # Synthetically recorded provider receipts are needed only to exercise + # the lifecycle state machine. The executables deliberately fail. + for context in providers.provider_contexts(instance): + context.executable.parent.mkdir(parents=True, exist_ok=True) + context.executable.write_text("#!/bin/sh\nexit 67\n") + context.executable.chmod(0o755) + engine.provider_register( + instance_id=instance.instance_id, display_label=instance.display_label, + service_account=ACCOUNT, provider=context.provider, + executable_sha256=providers.executable_digest(context.executable), + version="synthetic-lifecycle-only", + auth_reference=f"r27-synthetic:{context.provider}:{instance_id}", + auth_bootstrap_receipt=f"r27-synthetic-receipt:{context.provider}:{instance_id}", + ) + release = provisioner.ReleaseRequest("2.3.105", WHEEL, DIGEST, REVISION) + original_run = provisioner.subprocess.run + failed_child = [] + def observed_run(*args, **kwargs): + outcome = original_run(*args, **kwargs) + if outcome.returncode: + failed_child.append({ + "command_kind": "pip-install" if "pip" in str(args[0]) else "other", + "returncode": outcome.returncode, + "stderr_tail": (outcome.stderr or "")[-1000:], + "stdout_tail": (outcome.stdout or "")[-500:], + }) + return outcome + provisioner.subprocess.run = observed_run + try: + creation = engine.create(provisioner.InstanceRequest( + "install-r27-native-001", instance_id, instance.display_label, + ACCOUNT, port(), release, + )) + except Exception as error: + raise RuntimeError( + f"create failed in disposable root {work}: {error}; " + f"actual subprocess failures={failed_child}" + ) from error + finally: + provisioner.subprocess.run = original_run + require(creation.get("result") == "COMPLETE" and controller.loaded(instance), + "Product instance creation with real server failed") + identity_before = (instance.data_root / "runtime-identity.json").read_bytes() + descriptor_before = instance.descriptor.read_bytes() + preserve = engine.preserve( + instance_id, "preserve-r27-native-001", confirm_instance_id=instance_id, + ) + preserved = preserve["receipt"]["evidence"] + require(preserved.get("lifecycle_state") == "UNINSTALLED_DATA_PRESERVED" + and preserved.get("provider_auth_state") == "PRESERVED_REQUIRES_REVERIFICATION" + and not controller.loaded(instance), + "Preserve did not remove own server and demote provider state") + require((instance.data_root / "runtime-identity.json").read_bytes() == identity_before + and instance.descriptor.read_bytes() == descriptor_before, + "Preserve changed instance identity/data") + provider_rejected = [] + for context in providers.provider_contexts(instance): + try: + providers.readback(context) + except providers.SystemProviderContextError: + provider_rejected.append(context.provider) + require(set(provider_rejected) == {"codex", "github"}, + "Preserved synthetic provider evidence remained ready") + restore = engine.restore( + instance_id, "restore-r27-native-001", + preserve_operation_id="preserve-r27-native-001", release=release, + ) + restored = restore["receipt"]["evidence"] + require(restored.get("lifecycle_state") == "RESTORED_REQUIRES_PROVIDER_REVERIFICATION" + and restored.get("provider_auth_state") == "PRESERVED_REQUIRES_REVERIFICATION" + and restored.get("ready") is False and not controller.loaded(instance), + "Restore activated service or promoted provider") + require((instance.data_root / "runtime-identity.json").read_bytes() == identity_before + and instance.descriptor.read_bytes() == descriptor_before, + "Restore changed instance identity/data") + require(all( + not context.auth_receipt.exists() + or "PRESERVED" in context.auth_receipt.read_text() + for context in providers.provider_contexts(instance) + ), "Restore unexpectedly generated fresh provider authentication") + return { + "status": "PASS_ADAPTED_LIFECYCLE_WITH_REAL_INITIAL_SERVER", + "uid": uid, "gid": gid, "server_pid": controller.started_pid, + "release": "2.3.105", "wheel_sha256": DIGEST, + "preserve_state": preserved["lifecycle_state"], + "restore_state": restored["lifecycle_state"], + "provider_readback_rejected_after_preserve": provider_rejected, + "restore_ready": restored["ready"], + "server_loaded_after_restore": controller.loaded(instance), + "test_root": str(work), + "limits": "Synthetic provider records and filesystem service adapter; no launchd or live provider authentication", + } + finally: + controller.quiesce(instance) + +if __name__ == "__main__": + try: + configure() + print(json.dumps(main(), sort_keys=True)) + except Exception as error: + print(json.dumps({"status": "FAIL", "error": str(error)}, sort_keys=True)) + raise diff --git a/tools/qualification/ep_nonroot_macos_r27.py b/tools/qualification/ep_nonroot_macos_r27.py new file mode 100644 index 00000000..993b984d --- /dev/null +++ b/tools/qualification/ep_nonroot_macos_r27.py @@ -0,0 +1,352 @@ +#!/usr/bin/env python3 +"""Bounded EP 2.3.105 foreground process/API qualification under a real macOS test UID.""" +import hashlib +import argparse +import importlib.metadata +import json +import os +from pathlib import Path +import pwd +import signal +import socket +import subprocess +import sys +import tempfile +import time +import urllib.error +import urllib.request + +ACCOUNT = "" +HOME = Path("/") +WHEEL = Path("/") +WHEEL_SHA = "22dd1e49c263b55dc9eee396810a09fc43509984fe685f3c00d26289d55e8adc" +SIBLING_FIXTURE = Path("/") +VENV = Path("/") +PYTHON = Path("/") +EXPECTED_UID = -1 +EXPECTED_ENV = {} + +def configure(): + global ACCOUNT, HOME, WHEEL, SIBLING_FIXTURE, VENV, PYTHON, EXPECTED_UID, EXPECTED_ENV + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--account", required=True) + parser.add_argument("--expected-uid", type=int, required=True) + parser.add_argument("--home", type=Path, required=True) + parser.add_argument("--wheel", type=Path, required=True) + parser.add_argument("--venv", type=Path, required=True) + parser.add_argument("--synthetic-sibling-fixture", type=Path, required=True) + args = parser.parse_args() + ACCOUNT, EXPECTED_UID = args.account, args.expected_uid + HOME, WHEEL, VENV = args.home, args.wheel, args.venv + SIBLING_FIXTURE = args.synthetic_sibling_fixture + require(EXPECTED_UID > 0 and all( + path.is_absolute() for path in (HOME, WHEEL, VENV, SIBLING_FIXTURE) + ), "Explicit absolute qualification inputs required") + PYTHON = VENV / "bin/python" + EXPECTED_ENV = { + "HOME": str(HOME), "PATH": "/usr/bin:/bin:/usr/sbin:/sbin", + "LANG": "C", "LC_ALL": "C", "TMPDIR": str(HOME), + "PYTHONDONTWRITEBYTECODE": "1", + } + +def require(ok, message): + if not ok: + raise RuntimeError(message) + +def command(args, *, timeout=30): + return subprocess.run( + args, cwd=HOME, env=EXPECTED_ENV, text=True, capture_output=True, + timeout=timeout, check=False, + ) + +def port(): + with socket.socket() as sock: + sock.bind(("127.0.0.1", 0)) + return sock.getsockname()[1] + +def api(port_number, path, headers=None): + request = urllib.request.Request( + f"http://127.0.0.1:{port_number}{path}", headers=headers or {}, + ) + try: + with urllib.request.urlopen(request, timeout=2) as response: + return response.status, json.load(response) + except urllib.error.HTTPError as error: + return error.code, json.load(error) + +def launch(data_root, instance_id, log_path): + log = open(log_path, "ab", buffering=0) + child = subprocess.Popen( + [str(PYTHON), "-I", "-m", "engineering_platform.server", "serve", + "--data-root", str(data_root), "--expected-instance-id", instance_id], + cwd=HOME, env=EXPECTED_ENV, stdin=subprocess.DEVNULL, stdout=log, + stderr=subprocess.STDOUT, start_new_session=True, + ) + log.close() + return child + +def stop(child): + if child is None or child.poll() is not None: + return + child.terminate() + try: + child.wait(timeout=12) + except subprocess.TimeoutExpired: + child.kill() # exact supervised child only + child.wait(timeout=5) + +def wait_api(child, port_number, expected_id): + deadline = time.monotonic() + 20 + last = None + while time.monotonic() < deadline: + if child.poll() is not None: + raise RuntimeError(f"Server exited early: {child.returncode}") + try: + status, body = api(port_number, "/health") + if body.get("instance_id") == expected_id: + return status, body + last = f"foreign instance {body.get('instance_id')}" + except (OSError, ValueError) as error: + last = type(error).__name__ + time.sleep(0.2) + raise RuntimeError(f"Server health timeout: {last}") + +def main(): + result = { + "assignment": "L2-EP-NONROOT-RUNTIME-CONFORMANCE-V1-20260929", + "boundary": "REAL_MACOS_NONROOT_FOREGROUND_SERVER", + "cases": {}, + } + uid = os.geteuid() + gid = os.getegid() + pw = pwd.getpwnam(ACCOUNT) + require(uid == pw.pw_uid and uid == EXPECTED_UID and gid == pw.pw_gid, "Wrong process UID/GID") + require(os.getuid() == uid and uid != 0, "Unexpected real UID") + require(HOME.resolve() == Path(pw.pw_dir).resolve() + and HOME.stat().st_uid == uid + and HOME.stat().st_mode & 0o077 == 0, + "Test home is not private and owned by the exact process identity") + unexpected = set(os.environ) - set(EXPECTED_ENV) + changed = {key for key, value in EXPECTED_ENV.items() if os.environ.get(key) != value} + require( + unexpected <= {"__CF_USER_TEXT_ENCODING"} and not changed, + f"Ambient environment was not scrubbed: unexpected_keys={sorted(unexpected)}, " + f"missing_or_changed_keys={sorted(changed)}", + ) + require(sys.executable == str(PYTHON), "Unexpected Python executable") + require(sys.version_info[:2] == (3, 14), "Wrong interpreter version") + require(importlib.metadata.version("engineering-platform") == "2.3.105", "Wrong distribution version") + import engineering_platform + package_file = Path(engineering_platform.__file__).resolve() + require(package_file.is_relative_to(VENV), "Import escaped installed venv") + require(hashlib.sha256(WHEEL.read_bytes()).hexdigest() == WHEEL_SHA, "Published wheel digest mismatch") + result["uid"] = uid + result["gid"] = gid + result["groups"] = os.getgroups() + result["executable"] = sys.executable + result["python_version"] = sys.version.split()[0] + result["installed_package"] = str(package_file) + result["wheel_sha256"] = WHEEL_SHA + result["cases"]["native_executable_and_wheel"] = "PASS" + + work = Path(tempfile.mkdtemp(prefix="ep-r27-native-", dir=HOME)) + result["test_root"] = str(work) + child = None + child_b = None + try: + data_a, data_b = work / "instance-a", work / "instance-b" + pa, pb = port(), port() + require(pa != pb, "Port collision") + init_a = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + "init", "--data-root", str(data_a), "--bind-port", str(pa)]) + require(init_a.returncode == 0, f"A init failed: {init_a.stderr[-400:]}") + identity_a = json.loads(init_a.stdout)["instance_id"] + init_b = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + "init", "--data-root", str(data_b), "--bind-port", str(pb)]) + require(init_b.returncode == 0, f"B init failed: {init_b.stderr[-400:]}") + identity_b = json.loads(init_b.stdout)["instance_id"] + require(identity_a != identity_b, "Instance ID collision") + for data_root in (data_a, data_b): + configuration = json.loads((data_root / "server.json").read_text()) + managed_prefix = Path(configuration["managed_codex_cli_prefix"]) + require(managed_prefix.is_relative_to(HOME), + "Product configuration selected a different user's HOME") + result["cases"]["disposable_product_init_ab"] = "PASS" + result["cases"]["interactive_user_home_independence"] = "PASS" + + wrong = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + "serve", "--data-root", str(data_a), + "--expected-instance-id", identity_b], timeout=12) + require(wrong.returncode != 0 and "EP_SERVER_INSTANCE_ID_MISMATCH" in wrong.stdout, + f"Wrong expected instance did not fail closed: {wrong.stdout[-400:]} {wrong.stderr[-200:]}") + result["cases"]["wrong_expected_instance_rejected"] = "PASS" + + child = launch(data_a, identity_a, work / "server-a.log") + http_status, health = wait_api(child, pa, identity_a) + require(health.get("service") == "engineering-platform-server", "Wrong service") + require(health.get("product_version") == "2.3.105", "Wrong API product release") + require(health.get("schema_version") == 72, "Wrong live Server store schema") + require(health.get("running") is True, "Health is not live") + require( + health.get("runtime_identity", {}).get("artifact", {}).get("digest") + == "sha256:" + WHEEL_SHA, + "Live response did not observe the pinned wheel", + ) + result["server_pid"] = child.pid + process = command(["/bin/ps", "-ww", "-p", str(child.pid), "-o", "uid=", "-o", "gid=", "-o", "command="]) + require(process.returncode == 0, "Live server process inventory unavailable") + process_line = process.stdout.strip() + require(process_line.split()[:2] == [str(uid), str(gid)] + and "/Python.app/Contents/MacOS/Python " in process_line + and "engineering_platform.server" in process_line + and " serve " in process_line, + f"Live server process is not the expected non-root executable: {process_line}") + result["live_process_readback"] = process_line + result["api_http_status"] = http_status + result["api_instance_id"] = identity_a + result["api_product_version"] = health.get("product_version") + result["api_runtime_identity"] = health.get("runtime_identity") + result["cases"]["real_server_api_identity"] = "PASS" + + child_b = launch(data_b, identity_b, work / "server-b.log") + _, health_b = wait_api(child_b, pb, identity_b) + require(health_b.get("product_version") == "2.3.105" + and health_b.get("instance_id") != health.get("instance_id"), + "A/B live identity collision") + result["cases"]["live_ab_logical_isolation"] = "PASS" + stop(child_b) + child_b = None + + require(SIBLING_FIXTURE.stat().st_uid != uid + and SIBLING_FIXTURE.stat().st_mode & 0o777 == 0o600, + "Synthetic sibling fixture ownership invalid") + try: + SIBLING_FIXTURE.read_text() + except PermissionError: + pass + else: + raise RuntimeError("Test UID could read synthetic other-UID private fixture") + result["cases"]["synthetic_cross_uid_denial"] = "PASS" + + compatibility_status, compatibility = api(pa, "/v1/producer-compatibility") + require(compatibility_status == 200 + and compatibility.get("instance", {}).get("id") == identity_a + and compatibility.get("producer", {}).get("version") == "2.3.105", + "Public compatibility declaration unavailable") + scoped_status, scoped = api( + pa, "/v1/producer-compatibility", + {"EP-Project-ID": "ep-r27-disposable-project", + "EP-Repository-ID": "ep-r27-disposable-repository"}, + ) + require(scoped_status in (401, 403), "Missing scoped bearer was accepted") + result["cases"]["api_auth_required_for_scoped_readback"] = "PASS" + + project = "ep-r27-disposable-project" + repository = "ep-r27-disposable-repository" + consumer = "ep-r27-disposable-consumer" + repo_root = work / "synthetic-repository" + declaration = repo_root / ".engineering-platform/repository.json" + declaration.parent.mkdir(parents=True) + declaration.write_text(json.dumps({ + "schema_version": "1.0", + "project": {"id": project, "authority_repository_id": repository}, + "repository": {"id": repository, "role": "authority"}, + "validation": {"kind": "none"}, + })) + for arguments in ( + ["bootstrap-topology", "--project-id", project, "--repository-id", repository], + ["bind-repository", "--project-id", project, "--repository-id", repository, + "--path", str(repo_root)], + ): + outcome = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + *arguments, "--data-root", str(data_a)]) + require(outcome.returncode == 0, f"Disposable API topology failed: {outcome.stderr[-300:]} {outcome.stdout[-300:]}") + issued = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + "issue-consumer-credential", "--project-id", project, + "--consumer-id", consumer, "--data-root", str(data_a)]) + require(issued.returncode == 0, "Disposable consumer credential issuance failed") + # The synthetic credential remains in process memory and is never printed. + token = json.loads(issued.stdout)["credential"] + scoped_headers = { + "EP-Project-ID": project, + "EP-Repository-ID": repository, + "Authorization": "Bearer " + token, + } + authenticated_status, authenticated = api(pa, "/v1/producer-compatibility", scoped_headers) + require(authenticated_status == 200 + and authenticated.get("instance", {}).get("id") == identity_a + and authenticated.get("authentication", {}).get("consumer_id") == consumer + and authenticated.get("authentication", {}).get("local_repository_binding") == "BOUND", + f"Authenticated scoped API readback failed: {authenticated_status} {authenticated}") + result["cases"]["authenticated_scoped_api_identity"] = "PASS" + wrong_scope_status, _ = api(pa, "/v1/producer-compatibility", { + **scoped_headers, "EP-Project-ID": "ep-r27-wrong-project", + }) + require(wrong_scope_status == 403, "Wrong project scope was accepted") + result["cases"]["wrong_scoped_api_identity_rejected"] = "PASS" + + provider_status, provider = api(pa, "/api/provider-login-status") + require(provider_status == 200, "Provider status endpoint unavailable") + result["provider_readback"] = provider + require("READY" not in json.dumps(provider), "Provider unexpectedly READY without evidence") + result["cases"]["missing_provider_not_ready"] = "PASS" + + original_wheel = hashlib.sha256(WHEEL.read_bytes()).hexdigest() + try: + with open(package_file, "ab") as writable: + writable.write(b"EP-R27-SHOULD-NOT-WRITE") + except PermissionError: + pass + else: + raise RuntimeError("Immutable installed package unexpectedly writable by test UID") + require(hashlib.sha256(WHEEL.read_bytes()).hexdigest() == original_wheel, + "Published wheel changed during server test") + result["cases"]["installed_runtime_immutable_to_test_uid"] = "PASS" + + blocked_parent = work / "blocked-parent" + blocked_parent.mkdir(mode=0o500) + try: + blocked_init = command([str(PYTHON), "-I", "-m", "engineering_platform.server", + "init", "--data-root", str(blocked_parent / "forbidden")]) + require(blocked_init.returncode != 0 + and not (blocked_parent / "forbidden").exists(), + "Unwritable data parent was silently repaired or accepted") + finally: + blocked_parent.chmod(0o700) + result["cases"]["nonwritable_data_parent_rejected"] = "PASS" + + stop(child) + child = None + child = launch(data_a, identity_a, work / "server-a-restart.log") + _, restarted = wait_api(child, pa, identity_a) + require(restarted.get("product_version") == "2.3.105", "Restart changed release") + again_status, again_provider = api(pa, "/api/provider-login-status") + require(again_status == 200 and "READY" not in json.dumps(again_provider), + "Restart promoted provider state") + result["cases"]["real_foreground_restart_identity_and_provider"] = "PASS" + persisted_status, persisted = api(pa, "/v1/producer-compatibility", scoped_headers) + require(persisted_status == 200 + and persisted.get("authentication", {}).get("consumer_id") == consumer, + "Disposable authenticated API identity was not preserved on restart") + result["cases"]["restart_preserves_disposable_api_identity"] = "PASS" + + result["status"] = "PASS_WITH_DECLARED_LIMITS" + result["limits"] = [ + "No LaunchDaemon/LaunchAgent or physical reboot", + "No live provider authentication", + "Cross-UID denial uses a synthetic sibling fixture, not another EP server", + "No EP preserve/restore in this smoke slice", + ] + return result + finally: + stop(child_b) + stop(child) + result["own_server_stopped"] = child is None or child.poll() is not None + +if __name__ == "__main__": + try: + configure() + print(json.dumps(main(), sort_keys=True)) + except Exception as exc: + print(json.dumps({"status": "FAIL", "error": str(exc)}, sort_keys=True)) + raise From e9c014eb4dda3df787cf8181fc5e0bcdd74a1a08 Mon Sep 17 00:00:00 2001 From: Peter van Tol Date: Tue, 29 Sep 2026 14:54:28 +0200 Subject: [PATCH 2/5] Bind runtime slot installation to owned working directory --- docs/development/ENGINEERING_PLATFORM_ROADMAP.md | 5 ++++- docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md | 10 +++++++--- .../system_instance_provisioner.py | 2 ++ tests/engineering/test_system_instance_provisioner.py | 4 +++- tools/qualification/ep_nonroot_lifecycle_macos_r27.py | 3 +++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md index 8b623afb..a6f5a468 100644 --- a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md +++ b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md @@ -31,7 +31,10 @@ UNAVAILABLE state and normal restart passed. This narrows the missing runtime/readiness portion of OI-2 and OI-5 without changing their parent statuses. System service registration, reboot and live provider login remain outside this native qualification. The EP-owned preserve/restore continuation -is still under diagnosis after a non-root runtime-slot installation failure. +is pending a native rerun: the released provisioner inherited an inaccessible +caller working directory during runtime-slot installation. A source correction +binds its venv and pip children to the account-owned slot; the published +2.3.105 wheel remains unchanged. No machine-readable DAG in this repository contains OI-2 or OI-5 IDs; no new DAG node or parallel backlog is created. diff --git a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md index 09d0c74c..2bca480f 100644 --- a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md +++ b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md @@ -77,6 +77,10 @@ foreground Server and the product's own live health verifier checks it. The first native lifecycle attempt under UID 20000 stopped during the product-owned immutable runtime-slot installation, before preserve/restore. -The underlying package installer error is under diagnosis in the same -assignment; preserve/restore is not claimed PASS from the interactive-UID -development dry-run. +The actual pip traceback showed `PermissionError` at `os.getcwd()` because +the released provisioner inherited its caller's inaccessible working +directory. The pending source correction runs both venv creation and wheel +installation from the account-owned runtime slot. The exact 2.3.105 wheel is +not changed; its native lifecycle qualification must use an accessible +disposable working directory. Preserve/restore is not claimed PASS from the +interactive-UID development dry run. diff --git a/src/engineering_platform/system_instance_provisioner.py b/src/engineering_platform/system_instance_provisioner.py index a718aa87..1ea7bbc6 100644 --- a/src/engineering_platform/system_instance_provisioner.py +++ b/src/engineering_platform/system_instance_provisioner.py @@ -706,6 +706,7 @@ def _install_slot(self, release: ReleaseRequest) -> system_installation_topology result = subprocess.run( (sys.executable, "-I", "-m", "venv", str(slot.venv)), text=True, capture_output=True, check=False, + cwd=slot.root, env={"PYTHONNOUSERSITE": "1", "PYTHONSAFEPATH": "1"}, ) if result.returncode: @@ -717,6 +718,7 @@ def _install_slot(self, release: ReleaseRequest) -> system_installation_topology str(release.artifact), ), text=True, capture_output=True, check=False, + cwd=slot.root, env={"PYTHONNOUSERSITE": "1", "PYTHONSAFEPATH": "1", "PIP_CONFIG_FILE": os.devnull}, ) if result.returncode: diff --git a/tests/engineering/test_system_instance_provisioner.py b/tests/engineering/test_system_instance_provisioner.py index a2c68231..d2b4bdf4 100644 --- a/tests/engineering/test_system_instance_provisioner.py +++ b/tests/engineering/test_system_instance_provisioner.py @@ -410,11 +410,13 @@ def test_runtime_slot_and_data_initialization_boundaries(self) -> None: ) completed = SimpleNamespace(returncode=0, stdout="", stderr="") with ( - patch.object(provisioner_module.subprocess, "run", return_value=completed), + patch.object(provisioner_module.subprocess, "run", return_value=completed) as run, patch.object(provisioner_module.operational_installation, "package_identity", return_value={"version": self.release.version}), ): slot = concrete._install_slot(self.release) self.assertEqual(concrete._install_slot(self.release), slot) + self.assertEqual(run.call_count, 2) + self.assertTrue(all(call.kwargs["cwd"] == slot.root for call in run.call_args_list)) instance = self._instance("ep-production-0001", "EP production") interpreter = self.base / "python" diff --git a/tools/qualification/ep_nonroot_lifecycle_macos_r27.py b/tools/qualification/ep_nonroot_lifecycle_macos_r27.py index e1db39d5..8410eabd 100644 --- a/tools/qualification/ep_nonroot_lifecycle_macos_r27.py +++ b/tools/qualification/ep_nonroot_lifecycle_macos_r27.py @@ -134,6 +134,9 @@ def main(): require(sys.version_info[:2] == (3, 14), "Wrong Python version") require(hashlib.sha256(WHEEL.read_bytes()).hexdigest() == DIGEST[7:], "Wrong published wheel digest") + # The released provisioner inherits its caller's working directory for + # pip. Keep this qualification inside the admitted account's private home. + os.chdir(HOME) work = Path(tempfile.mkdtemp(prefix="ep-r27-lifecycle-", dir=HOME)) product_root = work / "product" launch_root = work / "launch-standin-only" From 79e1e3e6773610001d9052c15dd932d5fbcd43ca Mon Sep 17 00:00:00 2001 From: Peter van Tol Date: Tue, 29 Sep 2026 15:18:21 +0200 Subject: [PATCH 3/5] Record native adapted preserve restore qualification --- docs/development/ENGINEERING_PLATFORM_ROADMAP.md | 11 +++++++---- docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md | 13 ++++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md index a6f5a468..a3b4bda0 100644 --- a/docs/development/ENGINEERING_PLATFORM_ROADMAP.md +++ b/docs/development/ENGINEERING_PLATFORM_ROADMAP.md @@ -31,10 +31,13 @@ UNAVAILABLE state and normal restart passed. This narrows the missing runtime/readiness portion of OI-2 and OI-5 without changing their parent statuses. System service registration, reboot and live provider login remain outside this native qualification. The EP-owned preserve/restore continuation -is pending a native rerun: the released provisioner inherited an inaccessible -caller working directory during runtime-slot installation. A source correction -binds its venv and pip children to the account-owned slot; the published -2.3.105 wheel remains unchanged. +passed an adapted native preserve/restore rerun under UID 20000 with a real +initial foreground Server and a filesystem-only service adapter. Preserve +retained identity/data; restore stayed inactive and required provider +reverification. The released provisioner had inherited an inaccessible caller +working directory during the first attempt; a source correction binds its venv +and pip children to the account-owned slot. The published 2.3.105 wheel remains +unchanged. Neither rerun claims launchd, reboot or live provider authentication. No machine-readable DAG in this repository contains OI-2 or OI-5 IDs; no new DAG node or parallel backlog is created. diff --git a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md index 2bca480f..cdf624c2 100644 --- a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md +++ b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md @@ -81,6 +81,13 @@ The actual pip traceback showed `PermissionError` at `os.getcwd()` because the released provisioner inherited its caller's inaccessible working directory. The pending source correction runs both venv creation and wheel installation from the account-owned runtime slot. The exact 2.3.105 wheel is -not changed; its native lifecycle qualification must use an accessible -disposable working directory. Preserve/restore is not claimed PASS from the -interactive-UID development dry run. +unchanged; its lifecycle rerun used an accessible disposable working directory. + +That rerun executed the released wheel under UID/GID 20000 with a real initial +foreground Server and a filesystem-only service adapter. Product preserve +reported `UNINSTALLED_DATA_PRESERVED`; the server was stopped and the original +identity and data stayed intact. Both deliberately failing synthetic provider +records were rejected after preserve. Product restore reported +`RESTORED_REQUIRES_PROVIDER_REVERIFICATION`, `ready=false`, and did not load +the service or generate fresh provider authentication. This is an adapted +lifecycle PASS, not a macOS system-service or live-provider-login PASS. From ddbee2aedd4891eff6a76b2c28ff9ce215113814 Mon Sep 17 00:00:00 2001 From: Peter van Tol Date: Tue, 29 Sep 2026 15:25:36 +0200 Subject: [PATCH 4/5] Prepare Engineering Platform 2.3.106 release --- package-lock.json | 4 ++-- package.json | 2 +- pyproject.toml | 2 +- src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json | 2 +- .../ENGINEERING_PLATFORM_VERSION.json | 8 ++++---- src/engineering_platform/platform_version.py | 2 +- src/engineering_platform/templates/workspace-config.json | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index af0f59c8..b88d6020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "engineering-platform-browser-validation", - "version": "2.3.105", + "version": "2.3.106", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "engineering-platform-browser-validation", - "version": "2.3.105", + "version": "2.3.106", "devDependencies": { "@playwright/test": "1.63.0" } diff --git a/package.json b/package.json index 1f61cd0d..52298d20 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "engineering-platform-browser-validation", "private": true, - "version": "2.3.105", + "version": "2.3.106", "scripts": { "test:engineering-dashboard": "PYTHONPATH=src python3 -m engineering_platform.dashboard_browser_validation", "test:engineering-dashboard-logic": "node --test tests/engineering/dashboard_status_store.test.mjs tests/engineering/ui_localization_contract.test.mjs tests/engineering/dashboard_translation.test.mjs", diff --git a/pyproject.toml b/pyproject.toml index c6625bbc..cb967f2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "engineering-platform" -version = "2.3.105" +version = "2.3.106" description = "Local-first Engineering Platform execution operations runtime" readme = "README.md" requires-python = ">=3.14,<3.15" diff --git a/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json b/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json index aeb43bb4..e1abff02 100644 --- a/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json +++ b/src/engineering_platform/ENGINEERING_PLATFORM_CONFIG.json @@ -3,7 +3,7 @@ "platform": { "id": "engineering-platform", "name": "Engineering Platform", - "version": "2.3.105", + "version": "2.3.106", "generation": 2, "documentation_namespace": "engineering-platform", "capability_registry_version": 1 diff --git a/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json b/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json index 7a11ab91..7efdccd5 100644 --- a/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json +++ b/src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json @@ -1,15 +1,15 @@ { "bootstrap_contract": "2026.12", "checkpoint_format": 1, - "dashboard_version": "2.3.105", + "dashboard_version": "2.3.106", "handoff_protocol": 1, "memory_format": 2, "minimum_codex_cli": "0.146.0", "inbox_protocol": 1, - "platform_version": "2.3.105", + "platform_version": "2.3.106", "report_format": 2, - "runner_version": "2.3.105", + "runner_version": "2.3.106", "status_model": 1, "storage_schema": 45, - "watcher_version": "2.3.105" + "watcher_version": "2.3.106" } diff --git a/src/engineering_platform/platform_version.py b/src/engineering_platform/platform_version.py index 4fbb7ccc..a6a988f2 100644 --- a/src/engineering_platform/platform_version.py +++ b/src/engineering_platform/platform_version.py @@ -12,7 +12,7 @@ SEMVER = re.compile(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$") CONTRACT = re.compile(r"^(\d{4})\.(0[1-9]|1[0-2])$") -CURRENT_PLATFORM_VERSION = "2.3.105" +CURRENT_PLATFORM_VERSION = "2.3.106" MANIFEST_FIELDS = frozenset( { "platform_version", diff --git a/src/engineering_platform/templates/workspace-config.json b/src/engineering_platform/templates/workspace-config.json index 8fda2e14..ff512f95 100644 --- a/src/engineering_platform/templates/workspace-config.json +++ b/src/engineering_platform/templates/workspace-config.json @@ -3,7 +3,7 @@ "platform": { "id": "engineering-platform", "name": "Engineering Platform", - "version": "2.3.105", + "version": "2.3.106", "generation": 2, "documentation_namespace": "engineering-platform", "capability_registry_version": 1 From 525bebff1b8dc55868f7ec7771f8c465b469e638 Mon Sep 17 00:00:00 2001 From: Peter van Tol Date: Tue, 29 Sep 2026 15:34:14 +0200 Subject: [PATCH 5/5] Record repository native harness reruns --- docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md index cdf624c2..4977148d 100644 --- a/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md +++ b/docs/engineering/EP_SERVER_MACOS_NONROOT_2_3_105.md @@ -73,6 +73,13 @@ synthetic records serve only to exercise preserve/restore state transitions; they do not qualify a provider login. The controller starts a real initial foreground Server and the product's own live health verifier checks it. +Both repository harnesses were rerun under the admitted UID/GID 20000 with +the unchanged published wheel. The foreground/API harness returned +`PASS_WITH_DECLARED_LIMITS`, including independent live process and HTTP +readback, scoped authentication, HOME isolation and exact-child stop. The +lifecycle harness returned `PASS_ADAPTED_LIFECYCLE_WITH_REAL_INITIAL_SERVER`; +its service and provider limits remain as described below. + ## Lifecycle boundary The first native lifecycle attempt under UID 20000 stopped during the