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. Task: S00-011 Agent: auto-ci-cd-d105e8027730 Role: ci-cd Action: claim Status: review Task title: Restore verified npm registry access for the stack spike
69 lines
3.2 KiB
Python
69 lines
3.2 KiB
Python
#!/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()
|