diff --git a/experiments/0001-stack/registry-access/.gitignore b/experiments/0001-stack/registry-access/.gitignore new file mode 100644 index 0000000..d4f588e --- /dev/null +++ b/experiments/0001-stack/registry-access/.gitignore @@ -0,0 +1 @@ +artifacts/ diff --git a/experiments/0001-stack/registry-access/README.md b/experiments/0001-stack/registry-access/README.md new file mode 100644 index 0000000..81f5201 --- /dev/null +++ b/experiments/0001-stack/registry-access/README.md @@ -0,0 +1,79 @@ +# Verified public npm registry path — S00-011 + +Input: S00-002 failed to resolve registry.npmjs.org. Output: a repeatable public +metadata and exact-version tarball probe in the current executor harness. +This is connectivity evidence, not a framework choice or an application build. + +## Execution environment and reproduction + +Verified in the fresh auto-ci-cd-d105e8027730 executor on 2026-10-15: +Node v26.3.0, npm 11.16.0, Python 3, macOS paths. These are observed tools, +not accepted project runtime versions. The supplied harness has network access +enabled, workspace-write sandboxing and approval policy never. No harness, +runner, DNS, proxy, certificate or Git configuration was changed by this task. +The initial working tree contained only the coordinator's state/tasks.json claim. + +The next fresh executor must retain network-enabled execution, working DNS and +HTTPS egress to registry.npmjs.org:443, normal certificate trust, and project-only +source writes with temporary writes under /private/tmp. No credentials are needed. +Do not disable TLS or relax the write sandbox. The previous DNS failure was not +reproduced here; its external correction mechanism is unknown. This report does +not promise network availability in a different or future harness. + +From the project root: + +```sh +npm view react version license engines --json --cache /private/tmp/luma-stack-npm-cache --fetch-retries=0 --fetch-timeout=15000 +python3 experiments/0001-stack/registry-access/verify.py +``` + +The first command exactly repeats the original failure. It returned exit 0: + +```json +{"version":"19.3.1","license":"MIT","engines":{"node":">=0.10.0"}} +``` + +`npm config get strict-ssl` returned `true` (exit 0). The second command uses a +new TemporaryDirectory under /private/tmp with empty user/global npmrc files +and a fresh cache, runs from there to avoid project npmrc, and removes that +temporary directory after execution. It refuses NODE_TLS_REJECT_UNAUTHORIZED=0. +It invokes these argument arrays via subprocess, without a shell: + +```text +npm view react@19.3.1 version license engines dist --json +npm pack react@19.3.1 --ignore-scripts --json --pack-destination=/artifacts +``` + +The exact common options are: + +```text +--registry=https://registry.npmjs.org/ --strict-ssl=true +--fetch-retries=0 --fetch-timeout=15000 +--cache=/cache --userconfig=/user.npmrc +--globalconfig=/global.npmrc +``` + +The probe installs no dependencies, extracts no archive, runs no package scripts +and adds no package manifest/lockfile. React is only a public connectivity sample. +It checks the metadata version and exact HTTPS tarball URL, downloads through +npm, and independently compares Python hashlib SHA-512/base64 with dist.integrity +and npm pack's integrity. It uses standard libraries, not custom cryptography. +Errors/mismatches exit nonzero. Do not print private environment/configuration. + +## Actual result + +Both child npm commands and verify.py returned exit 0, using the fresh cache: + +- Package: react@19.3.1; metadata license MIT. +- URL: https://registry.npmjs.org/react/-/react-19.3.1.tgz +- Retrieved size: 26394 bytes. +- Registry and independently computed integrity: + `sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==` + +The local `artifacts/` directory contains the tarball, public metadata.json and +result.json; it is deliberately ignored by Git. Rerun the probe for independent +review instead of trusting an archived result. No secrets are recorded. Registry +signature/provenance verification is not claimed; the acceptance check is registry +integrity over verified HTTPS. Browser/CORS, dependency install, build, framework +compatibility and license acceptance remain outside this task. S00-002 must run +its own clean install/build and make its own stack/runtime decision after review. diff --git a/experiments/0001-stack/registry-access/verify.py b/experiments/0001-stack/registry-access/verify.py new file mode 100644 index 0000000..1bfceec --- /dev/null +++ b/experiments/0001-stack/registry-access/verify.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""Fetch public npm metadata/tarball without installing or running package code.""" +import base64 +import hashlib +import json +import os +from pathlib import Path +import subprocess +import tempfile + + +ROOT = Path(__file__).resolve().parent +PACKAGE = "react@19.3.1" # Connectivity sample only; not a stack decision. + + +def main(): + if os.environ.get("NODE_TLS_REJECT_UNAUTHORIZED") == "0": + raise SystemExit("Refusing disabled Node TLS verification") + artifacts = ROOT / "artifacts" + artifacts.mkdir(exist_ok=True) + # Empty configuration files prevent inherited npm credentials/config from + # being needed for this public probe. Never print the process environment. + with tempfile.TemporaryDirectory(prefix="luma-registry-", dir="/private/tmp") as temp: + temp = Path(temp) + for name in ("user.npmrc", "global.npmrc"): + (temp / name).write_text("", encoding="utf-8") + common = [ + "--registry=https://registry.npmjs.org/", "--strict-ssl=true", + "--fetch-retries=0", "--fetch-timeout=15000", + f"--cache={temp / 'cache'}", f"--userconfig={temp / 'user.npmrc'}", + f"--globalconfig={temp / 'global.npmrc'}", + ] + + def npm(args): + # Run outside the project so no project .npmrc is inherited. + result = subprocess.run(["npm", *args, *common], cwd=temp, + check=True, capture_output=True, text=True, + timeout=60) + print("npm " + " ".join(args) + " [isolated TLS/cache options]: exit 0") + return json.loads(result.stdout) + + metadata = npm(["view", PACKAGE, "version", "license", "engines", "dist", "--json"]) + if metadata["version"] != "19.3.1": + raise SystemExit("Unexpected package version") + if metadata["dist"]["tarball"] != "https://registry.npmjs.org/react/-/react-19.3.1.tgz": + raise SystemExit("Unexpected tarball origin/path") + integrity = metadata["dist"]["integrity"] + algorithm, expected = integrity.split("-", 1) + if algorithm != "sha512": + raise SystemExit("Expected SHA-512 registry integrity") + base64.b64decode(expected, validate=True) + packed = npm(["pack", PACKAGE, "--ignore-scripts", "--json", + f"--pack-destination={artifacts}"]) + if len(packed) != 1 or packed[0]["filename"] != "react-19.3.1.tgz": + raise SystemExit("Unexpected pack output") + tarball = artifacts / "react-19.3.1.tgz" + actual = "sha512-" + base64.b64encode(hashlib.sha512(tarball.read_bytes()).digest()).decode("ascii") + if actual != integrity or packed[0]["integrity"] != integrity: + raise SystemExit("Tarball integrity mismatch") + (artifacts / "metadata.json").write_text(json.dumps(metadata, indent=2) + "\n", encoding="utf-8") + result = {"package": PACKAGE, "bytes": tarball.stat().st_size, + "integrity": actual, "registry_integrity_match": True} + print(json.dumps(result, indent=2)) + (artifacts / "result.json").write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/planning/TASK_MATRIX.md b/planning/TASK_MATRIX.md index 56fc8ca..ebe6ab7 100644 --- a/planning/TASK_MATRIX.md +++ b/planning/TASK_MATRIX.md @@ -1,6 +1,6 @@ # Матрица задач -Generated; state revision **6**. Canonical status: state/tasks.json. +Generated; state revision **8**. Canonical status: state/tasks.json. | ID | Этап | Оператор | Reviewer | Статус | Owner | Зависимости | Задача | | --- | --- | --- | --- | --- | --- | --- | --- | @@ -13,7 +13,7 @@ Generated; state revision **6**. Canonical status: state/tasks.json. | [S00-007](tasks/S00-007.md) | S00 | security | orchestrator | todo | | S00-004, S00-005 | Утвердить password и crypto unlock модель | | [S00-008](tasks/S00-008.md) | S00 | ci-cd | qa | todo | | S00-003, S00-004 | Описать WSS/upload/TURN/push topology | | [S00-009](tasks/S00-009.md) | S00 | orchestrator | security | todo | | S00-003, S00-004, S00-005, S00-006, S00-007, S00-008 | Согласовать результаты spikes | -| [S00-011](tasks/S00-011.md) | S00 | ci-cd | security | todo | | S00-001 | Restore verified npm registry access for the stack spike | +| [S00-011](tasks/S00-011.md) | S00 | ci-cd | security | review | auto-ci-cd-d105e8027730 | S00-001 | Restore verified npm registry access for the stack spike | | [S00-010](tasks/S00-010.md) | S00 | qa | orchestrator | todo | | S00-001, S00-002, S00-003, S00-004, S00-005, S00-006, S00-007, S00-008, S00-009 | Gate: Профиль и проверка стека | | [S01-001](tasks/S01-001.md) | S01 | orchestrator | security | todo | | S00-010 | Описать identity/model contracts | | [S01-002](tasks/S01-002.md) | S01 | orchestrator | security | todo | | S00-010, S01-001 | Описать async account context | diff --git a/planning/stages/S00.md b/planning/stages/S00.md index 273d67c..772f236 100644 --- a/planning/stages/S00.md +++ b/planning/stages/S00.md @@ -15,7 +15,7 @@ - [S00-007](../tasks/S00-007.md): Утвердить password и crypto unlock модель — security; todo. - [S00-008](../tasks/S00-008.md): Описать WSS/upload/TURN/push topology — ci-cd; todo. - [S00-009](../tasks/S00-009.md): Согласовать результаты spikes — orchestrator; todo. -- [S00-011](../tasks/S00-011.md): Restore verified npm registry access for the stack spike — ci-cd; todo. +- [S00-011](../tasks/S00-011.md): Restore verified npm registry access for the stack spike — ci-cd; review. - [S00-010](../tasks/S00-010.md): Gate: Профиль и проверка стека — qa; todo. ## Граница этапа diff --git a/planning/task_matrix.csv b/planning/task_matrix.csv index 57afc79..4637306 100644 --- a/planning/task_matrix.csv +++ b/planning/task_matrix.csv @@ -8,7 +8,7 @@ S00-006,S00,orchestrator,security,todo,,S00-002,Зафиксировать brows S00-007,S00,security,orchestrator,todo,,"S00-004, S00-005",Утвердить password и crypto unlock модель S00-008,S00,ci-cd,qa,todo,,"S00-003, S00-004",Описать WSS/upload/TURN/push topology S00-009,S00,orchestrator,security,todo,,"S00-003, S00-004, S00-005, S00-006, S00-007, S00-008",Согласовать результаты spikes -S00-011,S00,ci-cd,security,todo,,S00-001,Restore verified npm registry access for the stack spike +S00-011,S00,ci-cd,security,review,auto-ci-cd-d105e8027730,S00-001,Restore verified npm registry access for the stack spike S00-010,S00,qa,orchestrator,todo,,"S00-001, S00-002, S00-003, S00-004, S00-005, S00-006, S00-007, S00-008, S00-009",Gate: Профиль и проверка стека S01-001,S01,orchestrator,security,todo,,S00-010,Описать identity/model contracts S01-002,S01,orchestrator,security,todo,,"S00-010, S01-001",Описать async account context diff --git a/state/commit_messages/auto-ci-cd-d105e8027730.txt b/state/commit_messages/auto-ci-cd-d105e8027730.txt new file mode 100644 index 0000000..584fef0 --- /dev/null +++ b/state/commit_messages/auto-ci-cd-d105e8027730.txt @@ -0,0 +1,4 @@ +Verify public npm access and exact-version tarball integrity + +Changes: Add a scoped fresh-cache registry probe, safe reproduction instructions and artifact ignore rule; record actual TLS-enabled metadata/download results and review handoff without selecting a stack or changing the harness. +Validation: Original npm view command and verify.py returned exit 0; react@19.3.1 tarball (26394 bytes) matched registry SHA-512. make check passed validation and 66 tooling tests. git diff --check passed. App install/build and different-harness connectivity remain unverified. diff --git a/state/evidence/S00-011-auto-ci-cd-d105e8027730.md b/state/evidence/S00-011-auto-ci-cd-d105e8027730.md new file mode 100644 index 0000000..383715c --- /dev/null +++ b/state/evidence/S00-011-auto-ci-cd-d105e8027730.md @@ -0,0 +1,56 @@ +# S00-011 executor evidence + +Agent: auto-ci-cd-d105e8027730; role: ci-cd; date: 2026-10-15. +Result: verified public npm metadata and integrity-checked exact-version tarball +in the current fresh execution harness; awaiting independent security review. + +## Actual changes + +- experiments/0001-stack/registry-access/verify.py: dependency-free Python probe + runs npm with explicit HTTPS registry/strict TLS, empty configs and fresh cache, + retrieves react@19.3.1 without package scripts/install/extraction, checks exact + version/URL and independently compares SHA-512 with registry metadata. +- Scoped README documents exact command forms/options, observed public results, + nonsecret environment prerequisites and limits. Scoped .gitignore excludes + retrieved artifacts. No stack, runtime pin or shared interface was selected. +- Task evidence/handoff/commit message only outside that source scope. No Git, + harness, DNS, npm config, TLS, CORS, immutable specs or plan definitions changed. + +## Commands and actual results + +| Command | Exit | Result | +| --- | --- | --- | +| `python3 scripts/tasks.py resume --agent auto-ci-cd-d105e8027730` | 0 | Assigned S00-011 in_progress, no repeat claim. | +| `python3 scripts/tasks.py show S00-011` | 0 | Bounded scope/acceptance read. | +| `python3 scripts/tasks.py packet S00-011 --agent auto-ci-cd-d105e8027730` | 0 | Current requirements, dependency and no previous handoff. | +| `npm view react version license engines --json --cache /private/tmp/luma-stack-npm-cache --fetch-retries=0 --fetch-timeout=15000` | 0 | Original failed command now returns version 19.3.1, license MIT, engines node >=0.10.0. | +| `node --version` / `npm --version` / `npm config get strict-ssl` | 0 each | v26.3.0 / 11.16.0 / true. Observations only. | +| `python3 experiments/0001-stack/registry-access/verify.py` | 0 | Both npm children exit 0, fresh-cache metadata/download, 26394-byte tarball; independent SHA-512 match. | +| `make check` | 0 | Validated 276 tasks, 22 stages, 221 requirements, 211 allocated Web requirements, revision 7; all 66 tooling tests passed in 10.411s. Foundation integrity only. | +| `git diff --check` | 0 | No tracked whitespace errors; scoped untracked files also inspected directly. | + +Probe child commands and all options are recorded in the scoped README and source. +Public URL: https://registry.npmjs.org/react/-/react-19.3.1.tgz + +Observed registry and calculated integrity: +`sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==`. +Public metadata and result JSON plus actual tarball remain locally in ignored +artifacts/. Security reviewer should regenerate them, not accept this text alone. + +## Context and limits + +Read assigned instructions/card/packet, NFR-007 in specs/tz_clear.md, accepted +ADR 0000 and S00-001 executor/review evidence/handoff. S01 contracts remain future +work and none are changed/needed. The initial working tree showed only the +coordinator's state/tasks.json claim change. No S00-011 handoff or stack experiment +directory existed initially; their read/list attempts returned missing-path errors, +not test failures or evidence of a network blocker. + +Current supplied harness has network enabled, workspace-write sandbox and never +approval policy. No environment permission changes were necessary. The previous +DNS failure no longer reproduces; the external correction mechanism is unknown. +S00-002 must use registry-capable execution with TLS trust intact and perform its +own version/license assessment, clean install/build and stack decision. Future or +different harness connectivity, package signatures/provenance, browser/CORS, +application build and app readiness are not verified by S00-011. No secrets or +production account data were used. No dependency was added to the application. diff --git a/state/handoffs/S00-011.md b/state/handoffs/S00-011.md new file mode 100644 index 0000000..c50643e --- /dev/null +++ b/state/handoffs/S00-011.md @@ -0,0 +1,21 @@ +# S00-011 handoff + +Executor: auto-ci-cd-d105e8027730 (ci-cd). +Result: the current fresh harness can reach the public npm registry with TLS +verification enabled. The original npm view command returned exit 0. A fresh-cache +probe retrieved react@19.3.1 (26394 bytes) and independently matched SHA-512 against +registry metadata. No blocker; no external/harness configuration was modified. + +Review the scoped README, verify.py and .gitignore under +experiments/0001-stack/registry-access. Repeat the original npm view command and +run `python3 experiments/0001-stack/registry-access/verify.py`; generated artifacts +are ignored. Verify explicit strict TLS, exact package/origin, empty npmrc/fresh +cache, ignored lifecycle scripts, independent integrity comparison and scope. +Evidence: state/evidence/S00-011-auto-ci-cd-d105e8027730.md. + +Security reviewer must independently accept or reject via CLI. Executor does not +set done or unblock S00-002. After reviewed done, the coordinator queues a fresh +S00-002 executor, which must retain working DNS/HTTPS egress and perform its own +clean install/build. Current observed Node/npm versions and sample React version +are not a stack selection. No app readiness, browser/provider behavior, signature +verification or future/different-harness network availability is claimed. diff --git a/state/tasks.json b/state/tasks.json index 90e314b..ec704fe 100644 --- a/state/tasks.json +++ b/state/tasks.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "revision": 6, + "revision": 8, "tasks": { "S00-001": { "status": "done", @@ -1120,10 +1120,14 @@ "owner": null }, "S00-011": { - "status": "todo", - "owner": null, + "status": "review", + "owner": "auto-ci-cd-d105e8027730", "external_wait": false, - "reason": "User authorized network access. runner.local.json now passes sandbox_workspace_write.network_access=true with workspace-write. Public npm metadata probe succeeded with TLS in a project-write/network-enabled Codex sandbox; S00-011 must independently verify the actual runner environment and package integrity before S00-002 is unblocked." + "reason": null, + "started_at": "2026-10-14T18:07:56+00:00", + "updated_at": "2026-10-14T18:10:10+00:00", + "evidence": "state/evidence/S00-011-auto-ci-cd-d105e8027730.md", + "handoff": "state/handoffs/S00-011.md" } }, "events": [ @@ -1192,6 +1196,29 @@ "task": "S00-011", "agent": "coordinator-network-0bc0fcf09c86", "reason": "User authorized network access. runner.local.json now passes sandbox_workspace_write.network_access=true with workspace-write. Public npm metadata probe succeeded with TLS in a project-write/network-enabled Codex sandbox; S00-011 must independently verify the actual runner environment and package integrity before S00-002 is unblocked." + }, + { + "revision": 7, + "at": "2026-10-14T18:07:56+00:00", + "action": "claim", + "task": "S00-011", + "agent": "auto-ci-cd-d105e8027730", + "role": "ci-cd", + "from": "todo", + "to": "in_progress", + "reason": null + }, + { + "revision": 8, + "at": "2026-10-14T18:10:10+00:00", + "action": "submit", + "task": "S00-011", + "agent": "auto-ci-cd-d105e8027730", + "role": null, + "from": "in_progress", + "to": "review", + "reason": null, + "evidence": "state/evidence/S00-011-auto-ci-cd-d105e8027730.md" } ], "retired_agents": [