cf-bootstrap-instance 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,671 @@
1
+ """External JSON-lines instance apply provider."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import configparser
6
+ import hashlib
7
+ import json
8
+ from email.parser import BytesParser
9
+ import os
10
+ import re
11
+ from pathlib import Path
12
+ import secrets
13
+ import shutil
14
+ import stat
15
+ import tempfile
16
+ import time
17
+ import zipfile
18
+
19
+ from .install import create_environment, install, prepare_launchers, remove_build_tools
20
+ from .layout import atomic_write, read_marker, validate_root
21
+ from .model import InstanceError, PROTOCOL, RESULT_SCHEMA, RESULT_SCHEMA_V2, canonical_json, digest, marker, marker_v2, parse_request
22
+ from .verify import inventory
23
+
24
+
25
+ def _lock(stream: object, acquire: bool) -> None:
26
+ if os.name == "nt":
27
+ import msvcrt
28
+ stream.seek(0)
29
+ msvcrt.locking(stream.fileno(), msvcrt.LK_NBLCK if acquire else msvcrt.LK_UNLCK, 1)
30
+ else:
31
+ import fcntl
32
+ fcntl.flock(stream.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB if acquire else fcntl.LOCK_UN)
33
+
34
+
35
+ def _open_lock(path: Path) -> object:
36
+ """Open the persistent lock without following a path-level redirect."""
37
+ flags = os.O_RDWR | os.O_CREAT
38
+ nofollow = getattr(os, "O_NOFOLLOW", 0)
39
+ try:
40
+ before = os.lstat(path)
41
+ except FileNotFoundError:
42
+ before = None
43
+ except OSError as error:
44
+ raise InstanceError("LOCK_INVALID", "lifecycle lock cannot be inspected") from error
45
+ if before is not None:
46
+ if stat.S_ISLNK(before.st_mode) or not stat.S_ISREG(before.st_mode) or _is_reparse(before):
47
+ raise InstanceError("LOCK_INVALID", "lifecycle lock is not a regular non-link file")
48
+ if os.name != "nt" and before.st_mode & 0o077:
49
+ raise InstanceError("LOCK_INVALID", "lifecycle lock permissions are too broad")
50
+ try:
51
+ descriptor = os.open(os.fspath(path), flags | nofollow, 0o600)
52
+ except OSError as error:
53
+ raise InstanceError("LOCK_INVALID", "lifecycle lock cannot be opened safely") from error
54
+ try:
55
+ after = os.fstat(descriptor)
56
+ current = os.lstat(path)
57
+ if not stat.S_ISREG(after.st_mode) or stat.S_ISLNK(current.st_mode) or not stat.S_ISREG(current.st_mode) or _is_reparse(current) or (after.st_dev, after.st_ino) != (current.st_dev, current.st_ino):
58
+ raise InstanceError("LOCK_INVALID", "lifecycle lock changed during safe open")
59
+ if os.name != "nt" and after.st_mode & 0o077:
60
+ raise InstanceError("LOCK_INVALID", "lifecycle lock permissions are too broad")
61
+ return os.fdopen(descriptor, "a+b")
62
+ except BaseException:
63
+ os.close(descriptor)
64
+ raise
65
+
66
+
67
+ def _is_reparse(value: os.stat_result) -> bool:
68
+ return os.name == "nt" and bool(getattr(value, "st_file_attributes", 0) & getattr(stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0x400))
69
+
70
+
71
+ def _same_path(left: Path | str, right: Path | str) -> bool:
72
+ left_path = os.path.normcase(os.fspath(Path(left).resolve(strict=False)))
73
+ right_path = os.path.normcase(os.fspath(Path(right).resolve(strict=False)))
74
+ return left_path == right_path
75
+
76
+
77
+ _SAFE_LAUNCHER_NAME = re.compile(r"[A-Za-z0-9._-]+\Z")
78
+
79
+
80
+ def _safe_launcher_name(value: object, label: str) -> str:
81
+ if not isinstance(value, str) or not value or value != value.strip() or not _SAFE_LAUNCHER_NAME.fullmatch(value) or Path(value).name != value or value in {".", ".."}:
82
+ raise InstanceError("ARTIFACT_INVALID", f"{label} is unsafe")
83
+ return value
84
+
85
+
86
+ def _regular(path: Path, label: str, directory: bool = False) -> None:
87
+ current = path
88
+ while current != Path(current.anchor):
89
+ try:
90
+ value = os.lstat(current)
91
+ except FileNotFoundError:
92
+ current = current.parent
93
+ continue
94
+ if stat.S_ISLNK(value.st_mode) or (os.name == "nt" and bool(getattr(value, "st_file_attributes", 0) & getattr(stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0x400))):
95
+ raise InstanceError("ARTIFACT_INVALID", f"{label} contains a link or reparse point")
96
+ current = current.parent
97
+ if path.is_symlink() or not (path.is_dir() if directory else path.is_file()):
98
+ raise InstanceError("ARTIFACT_INVALID", f"{label} is missing or unsafe")
99
+ if os.name == "nt" and bool(getattr(path.lstat(), "st_file_attributes", 0) & getattr(stat, "FILE_ATTRIBUTE_REPARSE_POINT", 0x400)):
100
+ raise InstanceError("ARTIFACT_INVALID", f"{label} is a reparse point")
101
+
102
+
103
+ def _launcher_script_name(target_name: str) -> str:
104
+ return _safe_launcher_name(target_name, "launcher target") + (".exe" if os.name == "nt" else "")
105
+
106
+
107
+ def _launcher_retained_name(target_name: str) -> str:
108
+ suffix = ".exe" if os.name == "nt" else ""
109
+ return f"launcher-{_safe_launcher_name(target_name, 'launcher target')}{suffix}"
110
+
111
+
112
+ def _launcher_targets(wheelhouse: Path, artifacts: list[dict[str, object]]) -> list[str]:
113
+ targets: list[str] = []
114
+ seen: set[str] = set()
115
+ for item in artifacts:
116
+ wheel = wheelhouse / str(item["filename"])
117
+ try:
118
+ _regular(wheel, "recovery wheel")
119
+ with zipfile.ZipFile(wheel) as archive:
120
+ entry_points = [entry for entry in archive.namelist() if entry.endswith(".dist-info/entry_points.txt")]
121
+ if len(entry_points) > 1:
122
+ raise ValueError("launcher metadata is incomplete")
123
+ if not entry_points:
124
+ continue
125
+ parser = configparser.ConfigParser(interpolation=None)
126
+ parser.optionxform = str
127
+ parser.read_string(archive.read(entry_points[0]).decode("utf-8"))
128
+ except (OSError, UnicodeDecodeError, ValueError, zipfile.BadZipFile, KeyError, configparser.Error) as error:
129
+ raise InstanceError("ARTIFACT_INVALID", f"recovery launcher metadata is invalid: {wheel.name}") from error
130
+ if not parser.has_section("console_scripts"):
131
+ continue
132
+ for target_name, _target_value in parser.items("console_scripts", raw=True):
133
+ target_name = _safe_launcher_name(target_name, "recovery launcher target")
134
+ key = target_name.casefold()
135
+ if key in seen:
136
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher names are duplicated or invalid")
137
+ seen.add(key)
138
+ targets.append(target_name)
139
+ return sorted(targets)
140
+
141
+
142
+ def _launcher_collision_keys(names: set[str]) -> set[str]:
143
+ return {name.casefold() for name in names}
144
+
145
+
146
+ def _launcher_images(scripts: Path, target_names: list[str], wheel_names: set[str]) -> list[dict[str, object]]:
147
+ records: list[dict[str, object]] = []
148
+ retained_names: set[str] = set()
149
+ wheel_collision_names = _launcher_collision_keys(wheel_names)
150
+ for target_name in target_names:
151
+ retained_name = _launcher_retained_name(target_name)
152
+ retained_key = retained_name.casefold()
153
+ if retained_key in retained_names or retained_key in wheel_collision_names or retained_name == "recovery-manifest.json":
154
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher filenames collide")
155
+ source = scripts / _launcher_script_name(target_name)
156
+ if source.is_symlink() or not source.is_file():
157
+ raise InstanceError("ARTIFACT_INVALID", f"recovery launcher is missing: {source.name}")
158
+ stat_result = source.lstat()
159
+ if _is_reparse(stat_result):
160
+ raise InstanceError("ARTIFACT_INVALID", f"recovery launcher is unsafe: {source.name}")
161
+ data = source.read_bytes()
162
+ records.append({"target_launcher": target_name, "retained_filename": retained_name, "size": stat_result.st_size, "sha256": hashlib.sha256(data).hexdigest(), "mode": stat.S_IMODE(stat_result.st_mode)})
163
+ retained_names.add(retained_key)
164
+ return sorted(records, key=lambda item: (str(item["target_launcher"]), str(item["retained_filename"])))
165
+
166
+
167
+ def _validate_launcher_images(bundle: Path, launcher_images: object, target_names: list[str], wheel_names: set[str]) -> list[dict[str, object]]:
168
+ if not isinstance(launcher_images, list):
169
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher metadata is invalid")
170
+ expected_targets = {name.casefold() for name in target_names}
171
+ wheel_collision_names = _launcher_collision_keys(wheel_names)
172
+ if len(launcher_images) != len(expected_targets):
173
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher metadata is incomplete")
174
+ records: list[dict[str, object]] = []
175
+ seen_targets: set[str] = set()
176
+ seen_retained: set[str] = set()
177
+ for raw in launcher_images:
178
+ if not isinstance(raw, dict) or set(raw) != {"target_launcher", "retained_filename", "size", "sha256", "mode"}:
179
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher metadata is invalid")
180
+ target = _safe_launcher_name(raw["target_launcher"], "launcher target")
181
+ retained = _safe_launcher_name(raw["retained_filename"], "retained launcher filename")
182
+ retained_key = retained.casefold()
183
+ if retained != _launcher_retained_name(target) or retained_key in wheel_collision_names or retained == "recovery-manifest.json":
184
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher filenames collide")
185
+ target_key = target.casefold()
186
+ if target_key in seen_targets or retained_key in seen_retained:
187
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher names are duplicated or invalid")
188
+ if target_key not in expected_targets:
189
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher names are outside the accepted set")
190
+ path = bundle / retained
191
+ _regular(path, "retained launcher image")
192
+ stat_result = path.lstat()
193
+ data = path.read_bytes()
194
+ if type(raw["size"]) is not int or type(raw["mode"]) is not int or raw["size"] != len(data) or raw["sha256"] != hashlib.sha256(data).hexdigest() or stat.S_IMODE(stat_result.st_mode) != raw["mode"]:
195
+ raise InstanceError("ARTIFACT_INVALID", "retained launcher image is invalid")
196
+ seen_targets.add(target_key)
197
+ seen_retained.add(retained_key)
198
+ records.append({"target_launcher": target, "retained_filename": retained, "size": raw["size"], "sha256": raw["sha256"], "mode": raw["mode"], "bundle": str(path)})
199
+ if seen_targets != expected_targets:
200
+ raise InstanceError("ARTIFACT_INVALID", "recovery launcher metadata is incomplete")
201
+ return sorted(records, key=lambda item: (str(item["target_launcher"]), str(item["retained_filename"])))
202
+
203
+
204
+ _OPERATION_SCHEMA = "cf.bootstrap.instance-operation.v1"
205
+ _OWNER_NAME = ".cogniflow-staging-owner.json"
206
+
207
+
208
+ def _operation_path(root: Path) -> Path:
209
+ return root.parent / f".{root.name}.operation.json"
210
+
211
+
212
+ def _operation_value(root: Path, staging: Path, plan_digest: str, artifact_digest: str) -> dict[str, str]:
213
+ return {"schema": _OPERATION_SCHEMA, "installation_root": str(root.resolve(strict=False)), "staging_root": str(staging.resolve(strict=False)), "operation_token": secrets.token_hex(32), "plan_digest": plan_digest, "artifact_set_digest": artifact_digest}
214
+
215
+
216
+ def _safe_read(path: Path) -> tuple[dict[str, object], bytes]:
217
+ try:
218
+ before = os.lstat(path)
219
+ if not stat.S_ISREG(before.st_mode) or _is_reparse(before) or (os.name != "nt" and before.st_mode & 0o077):
220
+ raise InstanceError("CLEANUP_FAILED", "ownership record is not a regular file")
221
+ descriptor = os.open(os.fspath(path), os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0))
222
+ try:
223
+ after = os.fstat(descriptor)
224
+ if (before.st_dev, before.st_ino) != (after.st_dev, after.st_ino) or not stat.S_ISREG(after.st_mode) or _is_reparse(after) or (os.name != "nt" and after.st_mode & 0o077):
225
+ raise InstanceError("CLEANUP_FAILED", "ownership record changed during read")
226
+ raw = os.read(descriptor, 1024 * 1024)
227
+ finally:
228
+ os.close(descriptor)
229
+ value = json.loads(raw)
230
+ except InstanceError:
231
+ raise
232
+ except (OSError, UnicodeDecodeError, json.JSONDecodeError) as error:
233
+ raise InstanceError("CLEANUP_FAILED", f"ownership record is unreadable: {type(error).__name__}: {error}") from error
234
+ if not isinstance(value, dict) or raw != canonical_json(value):
235
+ raise InstanceError("CLEANUP_FAILED", "ownership record is not canonical")
236
+ return value, raw
237
+
238
+
239
+ def _safe_create(path: Path, data: bytes) -> None:
240
+ flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0)
241
+ try:
242
+ descriptor = os.open(os.fspath(path), flags, 0o600)
243
+ try:
244
+ os.write(descriptor, data)
245
+ os.fsync(descriptor)
246
+ finally:
247
+ os.close(descriptor)
248
+ except FileExistsError as error:
249
+ raise InstanceError("CLEANUP_FAILED", "ownership record already exists") from error
250
+ except OSError as error:
251
+ raise InstanceError("CLEANUP_FAILED", "ownership record could not be created") from error
252
+
253
+
254
+ def _safe_unlink(path: Path) -> None:
255
+ if not os.path.lexists(path):
256
+ return
257
+ _safe_read(path)
258
+ try:
259
+ path.unlink()
260
+ except OSError as error:
261
+ raise InstanceError("CLEANUP_FAILED", "ownership record could not be cleared") from error
262
+
263
+
264
+ def _validate_operation(value: dict[str, object], root: Path, staging: Path | None, plan_digest: str, artifact_digest: str) -> Path:
265
+ expected_root = root.resolve(strict=False)
266
+ if set(value) != {"schema", "installation_root", "staging_root", "operation_token", "plan_digest", "artifact_set_digest"} or value.get("schema") != _OPERATION_SCHEMA or not _same_path(str(value["installation_root"]), expected_root) or value["plan_digest"] != plan_digest or value["artifact_set_digest"] != artifact_digest:
267
+ raise InstanceError("CLEANUP_FAILED", "ownership record is not bound to this operation")
268
+ token = value["operation_token"]
269
+ if not isinstance(token, str) or len(token) != 64 or any(char not in "0123456789abcdef" for char in token):
270
+ raise InstanceError("CLEANUP_FAILED", "ownership token is invalid")
271
+ recorded = Path(str(value["staging_root"]))
272
+ if not recorded.is_absolute() or not _same_path(recorded.parent, expected_root.parent) or not recorded.name.startswith(f".{root.name}.staging-") or (staging is not None and not _same_path(recorded, staging)):
273
+ raise InstanceError("CLEANUP_FAILED", "staging path is not bound to the final root")
274
+ return recorded
275
+
276
+
277
+ def _validate_owner(staging: Path, value: dict[str, object], plan_digest: str, artifact_digest: str) -> None:
278
+ if staging.is_symlink() or not staging.is_dir() or _is_reparse(os.lstat(staging)):
279
+ raise InstanceError("CLEANUP_FAILED", "owned staging root is not a real directory")
280
+ owner, _ = _safe_read(staging / _OWNER_NAME)
281
+ if owner != value or owner["plan_digest"] != plan_digest or owner["artifact_set_digest"] != artifact_digest:
282
+ raise InstanceError("CLEANUP_FAILED", "staging owner marker does not match operation record")
283
+
284
+
285
+ def _delete_owned(staging: Path, value: dict[str, object], plan_digest: str, artifact_digest: str) -> None:
286
+ _validate_owner(staging, value, plan_digest, artifact_digest)
287
+ _cleanup_staging(staging)
288
+
289
+
290
+ def _recover_staging(root: Path, record_path: Path, plan_digest: str, artifact_digest: str) -> None:
291
+ lookalikes = list(root.parent.glob(f".{root.name}.staging-*"))
292
+ if not os.path.lexists(record_path):
293
+ if lookalikes:
294
+ raise InstanceError("CLEANUP_FAILED", "unowned staging lookalike exists")
295
+ return
296
+ record, _ = _safe_read(record_path)
297
+ staging = _validate_operation(record, root, None, plan_digest, artifact_digest)
298
+ marker_path = root / ".cogniflow-instance.json"
299
+ if root.exists():
300
+ if not marker_path.is_file():
301
+ raise InstanceError("CLEANUP_FAILED", "owned operation conflicts with an unbound root")
302
+ marker, _ = read_marker(marker_path)
303
+ if not _same_path(str(marker["installation_root"]), root) or marker["plan_digest"] != plan_digest or marker["artifact_set_digest"] != artifact_digest or os.path.lexists(staging):
304
+ raise InstanceError("CLEANUP_FAILED", "stale ownership record conflicts with final root")
305
+ _safe_unlink(record_path)
306
+ return
307
+ _delete_owned(staging, record, plan_digest, artifact_digest)
308
+ _safe_unlink(record_path)
309
+
310
+
311
+ def _cleanup_staging(path: Path) -> None:
312
+ if not path.exists():
313
+ return
314
+ if os.environ.get("CF_BOOTSTRAP_TEST_CLEANUP_FAILURE") == "1":
315
+ raise InstanceError("CLEANUP_FAILED", "injected staging cleanup failure")
316
+ try:
317
+ shutil.rmtree(path)
318
+ except OSError as error:
319
+ raise InstanceError("CLEANUP_FAILED", "staging root could not be removed") from error
320
+
321
+
322
+ def _test_abort(boundary: str) -> None:
323
+ if os.environ.get("CF_BOOTSTRAP_TEST_PAUSE_AT") == boundary:
324
+ ready = Path(os.environ["CF_BOOTSTRAP_TEST_PAUSE_FILE"])
325
+ ready.write_text("ready\n", encoding="utf-8")
326
+ release = ready.with_suffix(".release")
327
+ while not release.exists():
328
+ time.sleep(0.01)
329
+ if os.environ.get("CF_BOOTSTRAP_TEST_ABORT_AT") == boundary:
330
+ os._exit(97)
331
+ if os.environ.get("CF_BOOTSTRAP_TEST_FAIL_AT") == boundary:
332
+ raise InstanceError("TEST_FAILURE", "injected transaction failure")
333
+
334
+
335
+ def _response(identifier: object, **body: object) -> dict[str, object]:
336
+ return {"jsonrpc": "2.0", "protocol": PROTOCOL, "id": identifier, **body}
337
+
338
+
339
+ def _validate_wheelhouse_metadata(wheelhouse: Path, artifact_set: dict[str, object], mode: str) -> None:
340
+ manifest = wheelhouse / "artifact-set.json"
341
+ if manifest.is_symlink() or not manifest.is_file():
342
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse artifact-set.json is missing or unsafe")
343
+ try:
344
+ raw = manifest.read_bytes()
345
+ parsed = json.loads(raw)
346
+ except (OSError, UnicodeDecodeError, json.JSONDecodeError) as error:
347
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse artifact-set.json is invalid") from error
348
+ if raw != canonical_json(parsed) or parsed != artifact_set:
349
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse artifact-set.json is not bound to the request")
350
+ expected_lines = [f"{item['normalized_distribution']}=={item['version']} --hash=sha256:{item['sha256']}" for item in artifact_set["artifacts"]]
351
+ if mode == "pypi":
352
+ lock = wheelhouse / "requirements.lock"
353
+ if lock.is_symlink() or not lock.is_file():
354
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse requirements.lock is missing or unsafe")
355
+ lock_bytes = lock.read_bytes()
356
+ if hashlib.sha256(lock_bytes).hexdigest() != artifact_set["lock_sha256"]:
357
+ raise InstanceError("ARTIFACT_INVALID", "requirements.lock hash does not match artifact set")
358
+ expected_lock = ("\n".join(expected_lines) + "\n").encode("utf-8")
359
+ if lock_bytes != expected_lock:
360
+ raise InstanceError("ARTIFACT_INVALID", "requirements.lock does not exactly match artifact set")
361
+
362
+
363
+ def apply(params: object, *, recovery_authority: tuple[dict[str, object], dict[str, object], Path] | None = None) -> dict[str, object]:
364
+ plan, resolution, root = parse_request(params)
365
+ if plan.get("schema") == "cf.bootstrap.plan.v2":
366
+ return _apply_v2(plan, resolution, root)
367
+ artifact_set = resolution["artifact_set"]
368
+ wheelhouse = Path(str(resolution["wheelhouse_path"])).absolute()
369
+ source = plan["artifact_source"]
370
+ checkout = Path(source["checkout_path"]).absolute() if isinstance(source, dict) and source.get("mode") == "local-repository" else None
371
+ validate_root(root, checkout, wheelhouse, Path(plan["cogniflow_home"]))
372
+ if not wheelhouse.is_dir() or wheelhouse.is_symlink():
373
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse is not a real directory")
374
+ root.parent.mkdir(parents=True, exist_ok=True)
375
+ lock_path = root.parent / f".{root.name}.lifecycle.lock"
376
+ record_path = _operation_path(root)
377
+ stream = None
378
+ acquired = False
379
+ staging: Path | None = None
380
+ owner_removed = False
381
+ try:
382
+ try:
383
+ stream = _open_lock(lock_path)
384
+ stream.seek(0, os.SEEK_END)
385
+ if stream.tell() == 0:
386
+ stream.write(b"0")
387
+ stream.flush()
388
+ _lock(stream, True)
389
+ acquired = True
390
+ except (OSError, BlockingIOError) as error:
391
+ raise InstanceError("INSTANCE_LOCKED", "instance lifecycle lock is held") from error
392
+ _recover_staging(root, record_path, digest(plan), digest(artifact_set))
393
+ marker_path = root / ".cogniflow-instance.json"
394
+ if root.exists() and not marker_path.is_file():
395
+ raise InstanceError("ROOT_CONFLICT", "existing installation root contains foreign files")
396
+ _validate_wheelhouse_metadata(wheelhouse, artifact_set, plan["artifact_source"]["mode"])
397
+ if root.exists() and marker_path.is_file():
398
+ current, _ = read_marker(marker_path)
399
+ if current["plan_digest"] != digest(plan):
400
+ raise InstanceError("PLAN_CONFLICT", "existing instance belongs to another plan")
401
+ if current["artifact_set_digest"] != digest(artifact_set):
402
+ raise InstanceError("ARTIFACT_SET_CONFLICT", "existing instance belongs to another artifact set")
403
+ environment = Path(str(current["environment_root"]))
404
+ executable = Path(str(current["python_executable"]))
405
+ if not _same_path(str(current["installation_root"]), root) or not _same_path(environment, root / "environment") or environment.is_symlink() or not _same_path(executable, environment / ("Scripts/python.exe" if os.name == "nt" else "bin/python")) or not executable.is_file():
406
+ raise InstanceError("VENV_INVALID", "existing instance is not root-bound")
407
+ installed = inventory(executable, environment, artifact_set, checkout)
408
+ if current["installed_distributions"] != installed:
409
+ raise InstanceError("VERIFY_FAILED", "existing marker inventory differs from target")
410
+ return {"schema": RESULT_SCHEMA, "status": "unchanged", "marker": str(marker_path), "installation_root": str(root), "environment_root": str(environment), "python_executable": str(executable), "installed_distributions": installed}
411
+ expected_wheels = {item["filename"] for item in artifact_set["artifacts"]}
412
+ allowed = expected_wheels | {"artifact-set.json"}
413
+ if plan["artifact_source"]["mode"] == "pypi":
414
+ allowed.add("requirements.lock")
415
+ children = list(wheelhouse.iterdir())
416
+ if any(child.is_symlink() or child.is_dir() for child in children) or {child.name for child in children} != allowed:
417
+ raise InstanceError("ARTIFACT_INVALID", "wheelhouse contains unexpected entries")
418
+ staging = Path(tempfile.mkdtemp(prefix=f".{root.name}.staging-", dir=root.parent))
419
+ try:
420
+ operation = _operation_value(root, staging, digest(plan), digest(artifact_set))
421
+ _safe_create(record_path, canonical_json(operation))
422
+ _safe_create(staging / _OWNER_NAME, canonical_json(operation))
423
+ _test_abort("staging")
424
+ environment = staging / "environment"
425
+ temp_dir = staging / "temp"
426
+ temp_dir.mkdir()
427
+ executable = create_environment(environment, temp_dir)
428
+ _test_abort("venv")
429
+ install(executable, wheelhouse, artifact_set, temp_dir)
430
+ _test_abort("install")
431
+ final_executable = root / "environment" / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
432
+ prepare_launchers(executable, final_executable)
433
+ _test_abort("launchers")
434
+ remove_build_tools(executable)
435
+ installed = inventory(executable, environment, artifact_set, checkout)
436
+ _test_abort("verify")
437
+ _cleanup_staging(temp_dir)
438
+ (staging / "state").mkdir()
439
+ (staging / "logs").mkdir()
440
+ _test_abort("state")
441
+ if recovery_authority is None:
442
+ marker_value = marker(plan, artifact_set, root, root / "environment", final_executable, installed)
443
+ else:
444
+ accepted_plan, accepted_artifact_set, accepted_wheelhouse = recovery_authority
445
+ recovery_path, recovery_digest = _retain_recovery_bundle(staging, root, accepted_wheelhouse, accepted_artifact_set, accepted_plan, executable, final_executable)
446
+ marker_value = marker_v2(accepted_plan, accepted_artifact_set, root, root / "environment", final_executable, installed, recovery_path, recovery_digest)
447
+ atomic_write(staging / ".cogniflow-instance.json", canonical_json(marker_value))
448
+ _test_abort("marker")
449
+ validate_root(root, checkout, wheelhouse, Path(plan["cogniflow_home"]))
450
+ if root.exists():
451
+ raise InstanceError("ROOT_CONFLICT", "installation root appeared during publication")
452
+ _test_abort("before-rename")
453
+ _safe_unlink(staging / _OWNER_NAME)
454
+ owner_removed = True
455
+ staging.replace(root)
456
+ _test_abort("after-rename")
457
+ _safe_unlink(record_path)
458
+ finally:
459
+ if staging is not None and staging.exists():
460
+ if owner_removed:
461
+ _cleanup_staging(staging)
462
+ _safe_unlink(record_path)
463
+ else:
464
+ _recover_staging(root, record_path, digest(plan), digest(artifact_set))
465
+ return {"schema": RESULT_SCHEMA, "status": "ready", "marker": str(marker_path), "installation_root": str(root), "environment_root": str(root / "environment"), "python_executable": str(final_executable), "installed_distributions": installed}
466
+ except InstanceError:
467
+ raise
468
+ except OSError as error:
469
+ raise InstanceError("PUBLISH_FAILED", "instance publication failed") from error
470
+ finally:
471
+ if acquired and stream is not None:
472
+ _lock(stream, False)
473
+ if stream is not None:
474
+ stream.close()
475
+
476
+
477
+ def _minimum_recovery_artifacts(wheelhouse: Path, artifacts: list[object]) -> list[dict[str, object]]:
478
+ records = {str(item.get("normalized_distribution", "")).replace("_", "-"): item for item in artifacts if isinstance(item, dict)}
479
+ roots = {"cf-runtime", "cf-service-client", "cf-install-services", "cf-service-mcp-server", "cf-bootstrap-source-local"}
480
+ if not roots <= records.keys():
481
+ raise InstanceError("ARTIFACT_INVALID", "minimum service-plane roots are incomplete")
482
+ dependencies: dict[str, set[str]] = {}
483
+ for name, item in records.items():
484
+ wheel = wheelhouse / str(item["filename"])
485
+ try:
486
+ with zipfile.ZipFile(wheel) as archive:
487
+ metadata_names = [entry for entry in archive.namelist() if entry.endswith(".dist-info/METADATA")]
488
+ if len(metadata_names) != 1:
489
+ raise ValueError("wheel metadata is incomplete")
490
+ metadata = BytesParser().parsebytes(archive.read(metadata_names[0]))
491
+ except (OSError, ValueError, zipfile.BadZipFile, KeyError) as error:
492
+ raise InstanceError("ARTIFACT_INVALID", f"recovery wheel metadata is invalid: {wheel.name}") from error
493
+ required = set()
494
+ for requirement in metadata.get_all("Requires-Dist", []):
495
+ dependency = re.split(r"[ (<>=!;\\[]", requirement, maxsplit=1)[0].lower().replace("_", "-").replace(".", "-")
496
+ if dependency in records:
497
+ required.add(dependency)
498
+ dependencies[name] = required
499
+ closure = set(roots)
500
+ pending = list(roots)
501
+ while pending:
502
+ for dependency in dependencies[pending.pop()]:
503
+ if dependency not in closure:
504
+ closure.add(dependency)
505
+ pending.append(dependency)
506
+ return sorted((records[name] for name in closure), key=lambda item: (str(item["normalized_distribution"]), str(item["filename"])))
507
+
508
+
509
+ def _retain_recovery_bundle(content_root: Path, authority_root: Path, wheelhouse: Path, artifact_set: dict[str, object], plan: dict[str, object], staging_executable: Path, final_executable: Path) -> tuple[str, str]:
510
+ """Retain the bootstrap-host-selected minimum closure inside the instance."""
511
+ artifacts = artifact_set.get("artifacts")
512
+ if not isinstance(artifacts, list):
513
+ raise InstanceError("ARTIFACT_INVALID", "recovery artifact set is invalid")
514
+ selected = _minimum_recovery_artifacts(wheelhouse, artifacts)
515
+ launcher_targets = _launcher_targets(wheelhouse, selected)
516
+ scripts = staging_executable.parent
517
+ wheel_names = {str(item["filename"]) for item in selected}
518
+ launcher_images = _launcher_images(scripts, launcher_targets, wheel_names)
519
+ bundle = content_root / "state" / "minimum-service-plane"
520
+ bundle.mkdir(parents=True, exist_ok=True)
521
+ for item in selected:
522
+ source = wheelhouse / str(item["filename"])
523
+ if source.is_symlink() or not source.is_file() or source.stat().st_size != item["size"] or hashlib.sha256(source.read_bytes()).hexdigest() != item["sha256"]:
524
+ raise InstanceError("ARTIFACT_INVALID", f"recovery wheel validation failed: {source.name}")
525
+ destination = bundle / source.name
526
+ shutil.copy2(source, destination)
527
+ if destination.is_symlink() or destination.stat().st_size != item["size"] or hashlib.sha256(destination.read_bytes()).hexdigest() != item["sha256"]:
528
+ raise InstanceError("PUBLISH_FAILED", f"retained recovery wheel verification failed: {source.name}")
529
+ _test_abort("recovery-copy")
530
+ for item in launcher_images:
531
+ source = scripts / _launcher_script_name(str(item["target_launcher"]))
532
+ destination = bundle / str(item["retained_filename"])
533
+ shutil.copy2(source, destination)
534
+ if destination.is_symlink() or destination.stat().st_size != item["size"] or hashlib.sha256(destination.read_bytes()).hexdigest() != item["sha256"] or stat.S_IMODE(destination.lstat().st_mode) != item["mode"]:
535
+ raise InstanceError("PUBLISH_FAILED", f"retained launcher verification failed: {source.name}")
536
+ _test_abort("recovery-copy")
537
+ closure = sorted(str(item["normalized_distribution"]).replace("_", "-") for item in selected)
538
+ manifest = {"schema": "cf.bootstrap.minimum-service-recovery-manifest.v2", "instance_id": plan["instance_id"], "plan_digest": digest(plan), "artifact_set_digest": digest(artifact_set), "target_python": str(final_executable), "bootstrap_plan": plan, "recovery_distributions": closure, "artifacts": sorted(selected, key=lambda item: (item["normalized_distribution"], item["filename"])), "launcher_images": launcher_images}
539
+ manifest_path = bundle / "recovery-manifest.json"
540
+ atomic_write(manifest_path, canonical_json(manifest))
541
+ _test_abort("recovery-manifest")
542
+ published_path = authority_root / "state" / "minimum-service-plane" / "recovery-manifest.json"
543
+ return str(published_path), "sha256:" + hashlib.sha256(manifest_path.read_bytes()).hexdigest()
544
+
545
+
546
+ def _validate_retained_authority(root: Path, marker_value: dict[str, object], plan: dict[str, object], artifact_set: dict[str, object], wheelhouse: Path) -> None:
547
+ recovery_path = Path(str(marker_value.get("recovery_manifest_path", "")))
548
+ expected_path = root / "state" / "minimum-service-plane" / "recovery-manifest.json"
549
+ if recovery_path != expected_path or recovery_path.is_symlink() or not recovery_path.is_file():
550
+ raise InstanceError("VERIFY_FAILED", "existing recovery authority is missing or unsafe")
551
+ raw = recovery_path.read_bytes()
552
+ if marker_value.get("recovery_manifest_digest") != "sha256:" + hashlib.sha256(raw).hexdigest():
553
+ raise InstanceError("VERIFY_FAILED", "existing recovery authority is tampered")
554
+ try:
555
+ retained = json.loads(raw)
556
+ except (OSError, ValueError, json.JSONDecodeError) as error:
557
+ raise InstanceError("VERIFY_FAILED", "existing recovery authority is invalid") from error
558
+ selected = _minimum_recovery_artifacts(wheelhouse, artifact_set["artifacts"])
559
+ launcher_targets = _launcher_targets(wheelhouse, selected)
560
+ closure = sorted(str(item["normalized_distribution"]).replace("_", "-") for item in selected)
561
+ wheel_names = {str(item["filename"]) for item in selected}
562
+ launcher_images = _validate_launcher_images(recovery_path.parent, retained.get("launcher_images"), launcher_targets, wheel_names)
563
+ launcher_images = [{key: item[key] for key in ("target_launcher", "retained_filename", "size", "sha256", "mode")} for item in launcher_images]
564
+ expected = {"schema": "cf.bootstrap.minimum-service-recovery-manifest.v2", "instance_id": plan["instance_id"], "plan_digest": digest(plan), "artifact_set_digest": digest(artifact_set), "target_python": str(root / "environment" / ("Scripts/python.exe" if os.name == "nt" else "bin/python")), "bootstrap_plan": plan, "recovery_distributions": closure, "artifacts": sorted(selected, key=lambda item: (item["normalized_distribution"], item["filename"])), "launcher_images": launcher_images}
565
+ if raw != canonical_json(expected) or retained != expected:
566
+ raise InstanceError("VERIFY_FAILED", "existing recovery authority does not match the accepted closure")
567
+ expected_names = wheel_names | {str(item["retained_filename"]) for item in launcher_images} | {"recovery-manifest.json"}
568
+ children = list(recovery_path.parent.iterdir())
569
+ if {child.name for child in children} != expected_names or any(child.is_symlink() or not child.is_file() for child in children):
570
+ raise InstanceError("VERIFY_FAILED", "existing recovery bundle contains missing or foreign state")
571
+ for item in selected:
572
+ wheel = recovery_path.parent / str(item["filename"])
573
+ if wheel.stat().st_size != item["size"] or hashlib.sha256(wheel.read_bytes()).hexdigest() != item["sha256"]:
574
+ raise InstanceError("VERIFY_FAILED", f"retained recovery artifact is tampered: {wheel.name}")
575
+ handoff_path = root / ".cogniflow-profile-handoff.json"
576
+ if handoff_path.exists():
577
+ if handoff_path.is_symlink() or not handoff_path.is_file():
578
+ raise InstanceError("VERIFY_FAILED", "accepted handoff record is unsafe")
579
+ try:
580
+ handoff = json.loads(handoff_path.read_bytes())
581
+ except (OSError, ValueError, json.JSONDecodeError) as error:
582
+ raise InstanceError("VERIFY_FAILED", "accepted handoff record is invalid") from error
583
+ if not isinstance(handoff, dict) or handoff.get("schema") != "cf.bootstrap.accepted-handoff.v2" or handoff.get("record_digest") != digest({key: value for key, value in handoff.items() if key != "record_digest"}) or handoff.get("instance_id") != plan["instance_id"] or handoff.get("plan_digest") != digest(plan) or handoff.get("recovery_manifest_path") != str(recovery_path) or handoff.get("recovery_manifest_digest") != marker_value["recovery_manifest_digest"]:
584
+ raise InstanceError("VERIFY_FAILED", "accepted handoff record is not bound to retained authority")
585
+
586
+
587
+ def _apply_v2(plan: dict[str, object], resolution: dict[str, object], root: Path) -> dict[str, object]:
588
+ """Run the hardened v1 installer with a lossless v2 validation boundary."""
589
+ artifact_set = resolution["artifact_set"]
590
+ wheelhouse = Path(str(resolution["wheelhouse_path"])).absolute()
591
+ source = plan["artifact_source"]
592
+ checkout = Path(str(source["checkout_path"])).absolute() if isinstance(source, dict) and source.get("mode") == "local-repository" else None
593
+ validate_root(root, checkout, wheelhouse, Path(str(plan["cogniflow_home"])))
594
+ if not wheelhouse.is_dir() or wheelhouse.is_symlink():
595
+ raise InstanceError("ARTIFACT_INVALID", "v2 wheelhouse is not a real directory")
596
+ marker_path = root / ".cogniflow-instance.json"
597
+ if root.exists() and marker_path.is_file():
598
+ current, _ = read_marker(marker_path)
599
+ if current.get("schema") != "cf.bootstrap.instance-marker.v2":
600
+ raise InstanceError("PLAN_CONFLICT", "existing instance is not a v2 target")
601
+ if current.get("plan_digest") != digest(plan):
602
+ raise InstanceError("PLAN_CONFLICT", "existing instance belongs to another plan")
603
+ if current.get("artifact_set_digest") != digest(artifact_set):
604
+ raise InstanceError("ARTIFACT_SET_CONFLICT", "existing instance belongs to another artifact set")
605
+ environment = Path(str(current["environment_root"]))
606
+ executable = Path(str(current["python_executable"]))
607
+ if environment.resolve() != root.resolve() / "environment" or executable.resolve() != environment.resolve() / ("Scripts/python.exe" if os.name == "nt" else "bin/python"):
608
+ raise InstanceError("VENV_INVALID", "existing v2 target is not root-bound")
609
+ installed = inventory(executable, environment, artifact_set, checkout)
610
+ if current.get("installed_distributions") != installed:
611
+ raise InstanceError("VERIFY_FAILED", "existing v2 marker inventory differs from target")
612
+ _validate_retained_authority(root, current, plan, artifact_set, wheelhouse)
613
+ return {"schema": RESULT_SCHEMA_V2, "status": "unchanged", "marker": str(marker_path), "installation_root": str(root), "environment_root": str(environment), "python_executable": str(executable), "installed_distributions": installed, "profile": plan["profile"], "selection_digest": artifact_set["selection_digest"]}
614
+ temporary = Path(tempfile.mkdtemp(prefix="cf-bootstrap-v2-install-", dir=str(wheelhouse.parent)))
615
+ try:
616
+ legacy_artifacts = []
617
+ for item in artifact_set["artifacts"]:
618
+ legacy = {key: item[key] for key in ("distribution", "normalized_distribution", "version", "filename", "sha256")}
619
+ legacy["size_bytes"] = item["size"]
620
+ if item["source_kind"] == "stonecastle-local":
621
+ legacy["source_project"] = item["source_project"]
622
+ if item.get("artifact_kind") == "native":
623
+ legacy.update({key: item[key] for key in ("artifact_kind", "wheel_tags", "executable")})
624
+ else:
625
+ legacy["source_kind"] = "external-wheelhouse"
626
+ legacy_artifacts.append(legacy)
627
+ shutil.copy2(wheelhouse / item["filename"], temporary / item["filename"])
628
+ legacy_set = {"schema": "cf.bootstrap.artifact-set.v1", "source_mode": "local-repository", "source_digest": artifact_set["repository_source_digest"], "index_digest": artifact_set["index_digest"], "artifacts": legacy_artifacts}
629
+ (temporary / "artifact-set.json").write_bytes(canonical_json(legacy_set))
630
+ legacy_plan = {key: value for key, value in plan.items() if key != "profile"}
631
+ legacy_plan["schema"] = "cf.bootstrap.plan.v1"
632
+ legacy_resolution = {"schema": "cf.bootstrap.local-artifact-resolution.v1", "wheelhouse_path": str(temporary), "artifact_set": legacy_set}
633
+ result = apply({"schema": "cf.bootstrap.instance-apply.request.v1", "bootstrap_plan": legacy_plan, "artifact_resolution": legacy_resolution}, recovery_authority=(plan, artifact_set, wheelhouse))
634
+ marker_path = root / ".cogniflow-instance.json"
635
+ installed = result.get("installed_distributions", [])
636
+ executable = Path(str(result["python_executable"]))
637
+ environment = Path(str(result["environment_root"]))
638
+
639
+
640
+
641
+ return {"schema": RESULT_SCHEMA_V2, "status": result["status"], "marker": str(marker_path), "installation_root": str(root), "environment_root": str(environment), "python_executable": str(executable), "installed_distributions": installed, "profile": plan["profile"], "selection_digest": artifact_set["selection_digest"]}
642
+ finally:
643
+ shutil.rmtree(temporary, ignore_errors=True)
644
+
645
+
646
+ def handle(payload: object) -> dict[str, object]:
647
+ identifier = payload.get("id") if isinstance(payload, dict) else None
648
+ try:
649
+ if not isinstance(payload, dict) or set(payload) != {"jsonrpc", "protocol", "id", "method", "params"} or payload.get("jsonrpc") != "2.0" or payload.get("protocol") != PROTOCOL or payload.get("method") != "instance/apply":
650
+ raise InstanceError("INVALID_ENVELOPE", "instance provider envelope is invalid")
651
+ return _response(identifier, result=apply(payload["params"]))
652
+ except InstanceError as error:
653
+ return _response(identifier, error={"code": error.code, "message": str(error), "details": error.details})
654
+ except Exception as error:
655
+ return _response(identifier, error={"code": "INTERNAL_ERROR", "message": "instance provider failed unexpectedly", "details": {"exception": type(error).__name__, "diagnostic": str(error)[:500]}})
656
+
657
+
658
+ def main() -> int:
659
+ import sys
660
+ for line in sys.stdin:
661
+ try:
662
+ response = handle(json.loads(line))
663
+ except json.JSONDecodeError:
664
+ response = _response(None, error={"code": "MALFORMED_JSON", "message": "request must be valid JSON", "details": {}})
665
+ sys.stdout.write(canonical_json(response).decode())
666
+ sys.stdout.flush()
667
+ return 0
668
+
669
+
670
+ if __name__ == "__main__":
671
+ raise SystemExit(main())