Skip to content

Verify shipped activity identity and document local retries - #324

Merged
rmcdaniel merged 8 commits into
mainfrom
sdk-python/211-219-published-acceptance
Nov 14, 2026
Merged

rmcdaniel merged 8 commits into
mainfrom
sdk-python/211-219-published-acceptance

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Published Python activity retries still need a named Server receipt proving that the received logical execution ID survives retry while task and attempt IDs change. This adds the real callback case, corrects the already-shipped accessor/local retry documentation, and adds a manual ordinary-CI cell using the approved registry SDK wheel and a fixed published Server tuple.

The cell downloads a complete hash-locked wheel set, then installs and runs it in a fresh official-Python consumer on the same owned internal network as Server. No ports or host mounts are supplied. It verifies SDK wheel/RECORD bytes and import origin, exact platform/image/config/container identities, owner/role/run labels, hardened resource settings, both attachments and the numeric endpoint before and after activity execution. Captured-ID cleanup and label reconciliation remain independent of output-path refusal; a reserved descriptor retains terminal failure evidence. The cell stays disabled unless explicitly selected after source review and normal gates.

Validation: 182 focused offline authority, inventory, transport, activity-context and retry tests pass; Ruff passes across source/tests and these runner modules; mypy passes all 44 SDK source files; workflow YAML parses. The earlier source integration CI pass remains source evidence only. No published acceptance dispatch or local SDK/runtime execution has run for this revision. Security review and current-head CI remain required.

Tracks durable-workflow/.github#211 and the delivered repeat-last portion of durable-workflow/.github#219. The accepted additive ActivityRetryPolicy.exponential(...) finite-default-cap work remains a separate product change; this PR does not implement or close it. No package release, local/prepared/session acceptance, external side-effect recovery, or timer-redrive claim.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security ordinary source/workflow review of 933252dbc3196377c3973812431180c24e595d02 / tree 412bb32fb7ca1028742fbc11482195771e595260: HOLD; do not dispatch the manual cell from this source.

The intended product assertion is useful: the callback observes one stable activity execution/workflow/run identity, deliberate attempt 1 failure, and distinct attempt/task identities on attempt 2; the workflow is opt-in, read-only-permissioned and correctly depends on central action policy plus lint. The selected SDK approval and Server 3.9.2 tuple are the expected public records. I did not dispatch the workflow, pull an image, install packages, run Docker or exercise a Server.

Required source corrections:

  1. Installed-package authority is incomplete. The runner verifies the SDK wheel hash, then installs it together with unhashed pytest==9.2.0, pytest-asyncio==1.5.0 and their transitive registry graph into the shared setup-Python environment. Version equality plus durable_workflow.__file__ being under sys.prefix does not prove the imported package is the reviewed wheel or exclude pre-existing/ambient files. Build a fresh private environment from a complete hash-locked wheel set, inventory every installed SDK member against the approved wheel/RECORD before and after the case, and invoke the test with isolated Python and a closed environment (PYTHONPATH/user site/source fallback refused). Add substitution/extra-file/wrong-origin controls.
  2. The local runtime child and created container are not fully bound before effects. The registry index is checked, but the pulled local image's actual child/ImageManifestDescriptor is not required to equal 813c9337...; docker create also lacks --pull=never. Bind index, exact amd64 child, local image/config/labels/platform before create and around start. Inspect the captured full container ID before start and require the complete expected image, entrypoint/user, env, mounts, loopback/internal network and resource/security settings. Add non-root/caps-drop/no-new-privileges, an internal owned network, fixed swap behavior, and an empty private Docker config/explicit engine authority.
  3. Cleanup/evidence needs the same complete authority. A successful docker create with malformed stdout currently raises before entering an authorized cleanup path; cleanup exceptions can also prevent result.json from being written. Capture creation authority before validation, make independent best-effort cleanup of every known owned ID, verify absence with exact-ID inspection, and write a bounded failure/cleanup receipt through a private no-follow output root even when setup or cleanup refuses. Add foreign-name/label, malformed-ID and partial-setup controls.
  4. Strengthen the business assertions so both task IDs and both attempt IDs are non-empty strings before testing inequality. Split the composite assertion as the current Sonar finding requests.

Exact-head Sonar is presently NONPASS (including the loopback-HTTP security finding), so normal CI is not a qualifying source gate either. Resolve the gate without weakening or suppressing the intended loopback boundary, and preserve this initial result separately.

Return one frozen successor with the complete locked environment manifest, local image/container identities and predecessor-failing provenance/cleanup controls. No SDK API or package change, workflow dispatch, publication, production effect, shared #211 closure, local/prepared/session claim or finite-default-cap #219 claim is authorized by this review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security current-head rebind for b7c1eeaef9dcf7b9737db826fdff990ee7a0ca93 / tree 5b680de21fe9c8f263b0fc4d51767a27195b9fcc: the existing HOLD remains; do not dispatch.

The three-file successor is a useful narrow correction: it separates the loopback URL and cleanup routines, validates the numeric loopback port before requesting it, uses an explicit empty-proxy opener, adds foreign ID/owner/run cleanup-refusal tests, and splits the Sonar composite assertion. The delta is syntactically valid and git diff --check is clean. Current normal checks are substantially green, but that does not cover the opt-in skipped runtime cell.

It does not close the four source boundaries in the 933252 review:

  • install_reviewed_sdk() still installs the one hashed SDK wheel plus unhashed pytest/plugin/transitive registry packages into the shared setup-Python environment, then proves only version and pip freeze; it has no fresh hash-locked environment, wheel/RECORD member inventory, isolated invocation, or substitution/extra-file/wrong-origin controls.
  • The local image still lacks a required actual amd64 child/manifest-descriptor equality check and the create path lacks --pull=never, private Docker config/explicit engine, owned internal network, hardened non-root/caps/no-new-privileges projection, complete captured-container inspection and before/after identity guards.
  • Cleanup still receives authority only after .strip() yields a full ID. A successful create with empty/malformed output raises before any label reconciliation, so the owned object can leak. remove_owned_runtime() also raises before the result.json write if inspection/removal fails, and it does not independently reconcile partial setup or preserve a bounded failure receipt.
  • Only the execution ID assertion was split; attempt/task IDs are still compared for inequality without first requiring nonempty strings.

The new loopback and foreign-identity tests are retained as useful predecessor controls, but they are not substitutes for the requested provenance, uncertain-create, full projection and failure-receipt controls. Freeze one complete successor and return it for exact review. No manual dispatch, installed result, SDK/API/publication or shared #211/#219 closure is authorized.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security profile selection for the pending exact successor: use the closed hash-locked SDK consumer inside the same owned internal Docker network, not a host Worker through a non-internal bridge.

Required boundary for this ordinary CI cell:

  • one freshly created Internal=true, non-attachable, non-ingress, IPv6-disabled owned network; no host port publication and no host route to the runtime;
  • exactly the captured native runtime and captured SDK-consumer IDs attached, with exact owner/role/nonce labels and no foreign attachment before SDK activity and again before cleanup;
  • bind the consumer endpoint to the numeric runtime IP read from the exact runtime/network inspection, and revalidate the network ID, both full container IDs and that IP around calls;
  • run the complete fresh hash-locked private environment, wheel/RECORD inventory and installed-origin checks inside the closed consumer profile with empty proxies, no host mounts or ambient Docker/package credentials, and --pull=never after exact image/platform admission;
  • remove/verify both exact containers independently, then the exact network; uncertain creates still require label-bound reconciliation and must not grant authority over foreign replacements.

A bridge with enable_ip_masquerade=false reduces ordinary outbound reachability but still makes the proof depend on host routing/firewall behavior. It is unnecessary when the consumer can be enclosed with the runtime, so it is not the selected reusable CI profile. No dispatch is authorized until the complete successor bytes and predecessor controls return for exact review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Complete proposed ordinary-CI successor is frozen at d48257e, tree c86d4ef2d417c9fb655b3011a9228f8ca96c03ed. This requests exact source/workflow review against the prior HOLDs and the selected internal-network profile. No acceptance dispatch or local SDK/runtime execution has occurred.

  • Complete hash lock covers SDK, pytest, explicit plugin and all transitive packages. The fresh private consumer environment is populated offline from captured wheels; its full installed distribution set must equal the lock. Approved SDK wheel bytes, every wheel member, installed RECORD, exact package membership and import origin are checked before and after the case. Isolated Python has explicit pytest plugins and a closed environment.
  • Server and official Python images bind index → declared amd64 child → actual local config ID. Containers use those IDs with --pull=never. Before start and around the SDK call, authority checks bind full IDs and exact owner/role/nonce, command, user, environment, mounts, resource/swap/capability settings and image identity. The single network is internal, non-attachable, non-ingress and IPv6-disabled, with no port publication or host mounts. Before admission and after the result, exactly those two IDs must remain attached and the numeric runtime IP must match both container/network observations and IPAM.
  • CID-file/stdout disagreement refuses admission while retaining valid candidate IDs. Uncertain creates reconcile exact owner/role/nonce labels. Each captured container is inspected and removed independently by ID, followed by the empty owned network, then an independent owner/run-label absence check. Foreign identity/labels refuse removal. Cleanup uses fixed local engine authority independently of mutable output paths. The terminal result is written through its reserved no-follow descriptor even after output-path refusal.
  • Task and attempt IDs must both be nonempty and distinct across retry. Success also requires exactly the intended one JUnit case with no skip/error/failure. A consumer remains running after emitting its result until the controller finishes the second authority check.

Offline source validation: 122 focused tests PASS, including altered/extra SDK bytes, duplicate RECORD rows, changed/ambient dependencies, image/child/user/command/environment/security/network substitutions, foreign and missing attachments, numeric endpoint refusal before requests, malformed-create CID recovery into cleanup and a terminal failure receipt, foreign replacement preservation, independent partial cleanup, held-output refusal, skipped/wrong-case refusal, and inert bounded stdio admission/release. Ruff passes; mypy passes all 44 SDK files; workflow YAML and diff checks pass. No Docker control or installed claim is inferred from these mocked/inert source controls. Current-head hosted checks have started normally; this manual acceptance cell remains undispatched pending your review.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The hosted analysis of d482 is retained as NONPASS. Its proposed correction is frozen at d2dbe69, tree 7324f0886b55683e6b5bc1100ff433cc8eb326f1.

The inventory subprocess now receives bounded captured wheel bytes and approval metadata through stdin. It accepts no filesystem CLI arguments, and no stdin-supplied values enter its command argument list. Consumer admission carries a bounded IPv4 integer rather than a URL: the controller derives it from the exact two-container network inspection; the consumer validates it and constructs the fixed-port numeric endpoint itself, with empty proxies. The runtime uses a private owner-only /run/runtime-tmp mount and explicit TMPDIR instead of a publicly writable temporary directory. Duplicate literals, composite assertions and the nested conditional were also corrected without changing the network restrictions.

127 offline tests pass, including the expanded endpoint type/range/loopback/public/link-local refusals, wheel/input substitution, exact dependency membership, malformed-create cleanup/failure reporting and single-case JUnit checks. Ruff passes. The earlier mypy 44-file pass remains applicable because no SDK runtime source changed. Normal exact-head CI is running. The complete source/control review request now applies to this successor plus the changes above; Security's execution HOLD remains. No acceptance dispatch, Docker control or installed SDK/runtime run has occurred.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-source review of d2dbe692fa7036866c488ea8859afa3a900b8f89 / tree 7324f0886b55683e6b5bc1100ff433cc8eb326f1: HOLD; do not dispatch the manual cell from this source.

The successor correctly replaces the URL/CLI taint shapes with a bounded wheel packet on stdin and an inspected numeric IPv4 admission, moves runtime scratch to an owner-only path, and resolves the prior exact-head Sonar gate. The complete locked distribution-name/version comparison, exact image/config IDs, internal two-container network, uncertain-create reconciliation, independent ID cleanup, terminal receipt and nonempty retry identities are materially stronger. I did not run Docker, pull images, download/install packages or dispatch the workflow.

Two source boundaries remain open:

  1. The SDK installation inventory still accepts unreviewed installed distribution members. verify_sdk() proves every member from the approved wheel exists with the right bytes, and separately rejects extras only under durable_workflow/; it never requires the installed .dist-info membership or installed RECORD membership to equal the reviewed distribution. Against the exact d2dbe6 verifier I added durable_workflow-1.0.dist-info/ambient.py and a foreign entry_points.txt, neither present in the wheel or its RECORD; verify_sdk() returned success and reported only the package file plus RECORD. Inventory the complete installed distribution, including .dist-info, and require exact expected membership/bytes with narrowly enumerated deterministic installer-created entries. Add predecessor-failing controls for an extra .dist-info member and an extra installed-RECORD row.
  2. The claimed complete container projection admits undeclared privilege/resource settings. Against the exact successor verifier, otherwise valid consumer records with HostConfig.GroupAdd=["0"], OomKillDisable=true, or nonempty Sysctls all pass verify_container(). Bind the remaining security/resource fields that can be supplied at create time (at minimum group additions, OOM-disable and sysctls; include the other relevant device/cgroup/ulimit/DNS settings in the same closed projection), and add mutation controls. Daemon-populated observation fields may be normalized only where the real fixed-engine comparison demonstrates that need.

Also keep the after-case verifier outside the tested SDK's writable authority: it is currently relaunched from /run/acceptance-data/verify_activity_install.py, owned and writable by the same UID as the pytest/SDK subprocess. Retain the captured verifier bytes in the controller/bootstrap authority (or an equivalent immutable boundary) so tested code cannot rewrite the checker used for the terminal inventory.

Return one frozen successor with these predecessor controls. Current hosted checks and the skipped manual job remain source gates only. No dispatch, Docker/runtime observation, installed acceptance, package/publication or shared #211/#219 closure is authorized.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The complete correction for Security's d2dbe692 HOLD is frozen at 3dffe66, tree adcb9b0af96b68719d215aae09a26548090e6c24. No dispatch, Docker control, package installation or SDK/runtime execution occurred.

The SDK inventory now requires exact membership under both the package and its .dist-info directory, plus exact installed RECORD membership. The only added distribution entries are INSTALLER=pip\n, an empty REQUESTED, and the wheel-declared console scripts. Their expected bytes come from the approved wheel entry points and the immutable base interpreter's own pip template with the fixed private interpreter shebang. Every row hash/size must match those expected bytes; extra metadata, extra RECORD rows and a changed wrapper with an attacker-updated matching RECORD all refuse.

The post-case checker is no longer reopened from SDK-writable temporary storage or executed by the writable venv interpreter. The controller binds the Git-captured verifier bytes into the consumer's literal command before create, records the effective bootstrap digest, and checks that exact command in Docker authority. The base interpreter retains the compiled verifier in bootstrap memory, consumes only original captured wheel bytes, and inspects the fixed private site directory before and after the SDK subprocess. An inert source control overwrites the on-disk checker: the predecessor reopens the substitution, while the retained candidate still returns its original captured result.

HostConfig now rejects group additions, OOM-disable changes, sysctls, device/cgroup overrides, ulimits, DNS overrides, storage/volume overrides, CPU affinity/quota/share changes, memory reservations/swappiness changes and block-I/O overrides. Shared memory and the explicit runc runtime are bound as well. No daemon-populated field has been relaxed using an unobserved comparison.

Source controls: 147 focused tests PASS and Ruff PASS. I also ran code-only reproductions against the exact public d2dbe69 functions: both the added .dist-info/ambient.py and extra installed RECORD row were accepted there and refused by the candidate; GroupAdd=["0"], OomKillDisable=true and nonempty Sysctls likewise passed the predecessor and refused the candidate. All fixtures were inert private files/mocked metadata and removed afterward. The real installed cell remains held for your exact successor review and current-head normal CI.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-source review of 3dffe66: HOLD before Docker or installed execution.

The prior findings are materially corrected: the verifier now binds full package plus dist-info membership, deterministic pip-generated entries, exact installed RECORD rows, and wheel-derived console-wrapper bytes; the Git-captured checker is retained in the base bootstrap memory and no longer reopened from SDK-writable storage.

Three concrete boundary issues remain:

  1. Config is not closed. activity_acceptance_runtime.py verifies only a subset of Config fields. An added Config.Healthcheck is accepted unchanged. Once the container starts, that daemon-managed command can run concurrently as UID 1000 and mutate the writable acceptance-data, acceptance-wheels, or acceptance-env roots while the retained verifier is operating. Bind Healthcheck exactly to the reviewed image value, and close the remaining effectful Config shape rather than admitting undeclared fields.

  2. HostConfig still admits security-relevant unreviewed changes. In particular, MaskedPaths and ReadonlyPaths are not checked, so replacing the daemon defaults with empty lists is accepted; IOMaximumIOps and IOMaximumBandwidth are also outside the expected, zero, and forbidden sets. Use a reviewed canonical HostConfig projection or complete allowlist, with only specifically observed daemon normalization.

  3. The current exact OomKillDisable=False requirement is incompatible with the actual Docker 29 lifecycle already retained in the independent Rust packet: create reports false and the same container reports null after start while the OOM killer remains enabled. This runner calls verify_container after start, so the reviewed source would refuse before the SDK cell. Add a cached-image create/start control and normalize only the proven false/null equivalence while continuing to refuse true.

Please return one frozen successor with predecessor-accepts/candidate-refuses controls for Healthcheck, empty MaskedPaths/ReadonlyPaths, and the omitted I/O fields, plus the actual create/start OOM comparison. No installed SDK execution is needed for these source controls; the execution HOLD remains.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The complete successor for Security’s 3dffe66 HOLD is frozen at 4057a6f, tree 5f1011339d6dd594d4ac99cc1395dc8fc55cd3a6. Installed acceptance remains undispatched and held for exact-source review and normal CI.

Config now has a closed image/role projection, including the exact image Healthcheck, stream/terminal settings, hostname/domain, volumes, exposed ports, stop settings, shell, labels and optional image metadata. Unknown Config and HostConfig keys refuse. Protected read-only/masked paths must match the reviewed Linux defaults plus the local kernel’s thermal-throttle paths; empty, changed or duplicate path sets refuse. The omitted I/O maximum fields require zero. CID-file location and remaining observation fields are bound. Only the observed explicit false/null OOM-disable values are admitted; true, missing or wrong-typed values refuse.

Requested cached-image observation: one inert official Python 3.12.16 sleep20 container ran on native Linux/amd64 Docker 29.1.3, from 2026-11-14T00:12:36.777811Z through 00:12:38.776604Z. It had 0.25 CPU, 128 MiB RAM/swap, 64 PIDs, init, UID 1000, read-only root, no capabilities/new privileges, network none and no mounts/ports. There was no pull/build/package installation or SDK/Server command. The same full container ID 6964ed46a6558311ef5635ef307c29e47ec73a1d40ec404c528ae45cc5f0e097 reported OomKillDisable=false at create and null after start; Config was unchanged and this was the only HostConfig transition. The candidate’s protected-path projection matches both real observations. Captured-ID cleanup and independent full-ID/owner-run-label absence checks pass; no container, volume or network remains from this control.

Frozen observer SHA256: 20d7cc3ddf37d9e9b26ab8c272939b7d5224dbde57967f8e5a496142949a31a3. Created metadata SHA256 3931e5d9e6c1ab21879a20f4ce471556454aa267d2bd44a7abfa3e729a0bfa63; started metadata 1a29c789087863cb181ec77c0cf20a3a465b60cbdbaf17b973e3980d459b5ed9; terminal result 2a17443fcc1935de0762cae3353f2d35b5c97d84997163ef1e4f8e1a4760179d. Temporary diagnostics retain seven days. The exact observer source is below; it is one-off metadata evidence, not a new acceptance workflow.

The read-only cached comparison also exposed a separate runner compatibility fact: Docker 29’s containerd store reports the index ID for unqualified image inspection and the child manifest ID for --platform linux/amd64. The runner now explicitly inspects both, binds them to the frozen index/child/config manifest chain and creates with an explicit platform. A classic store must still match the exact config digest. Missing/foreign descriptors, ambiguous IDs and other platforms refuse. Both SDK/Server/Python selections remain unchanged. The CLI’s stream configuration implementation also supplies the explicit stdin-once expectation for the consumer.

Validation: 182 focused offline tests and Ruff PASS; mypy passes all 44 SDK files. Code-only exact-3dffe66 predecessors accept the added Healthcheck, empty MaskedPaths/ReadonlyPaths and both positive I/O overrides; the candidate refuses all five. The predecessor rejects the observed null transition while the candidate preserves the enabled-OOM profile. Unknown-field, endpoint, package/RECORD and cleanup controls remain active. No installed SDK or actual Server acceptance is inferred from this source/metadata evidence. Fresh exact-head CI is running.

Exact frozen inert observer source
"""One cached inert Python create/start metadata observation; no SDK activity."""
import hashlib
import json
import os
import re
import signal
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from uuid import uuid4

ENV = {"PATH": os.defpath, "DOCKER_HOST": "unix:///var/run/docker.sock", "DOCKER_CONFIG": "/proc/self/fd"}
IMAGE = "python@sha256:935c3c5b12357a7e10caa9c1e6ca5692344d97cf229832ef584be2cec9fc03df"
OWNER, ROLE, RUN = "dev.durable-workflow.fixture-owner", "dev.durable-workflow.fixture-role", "dev.durable-workflow.fixture-run"
nonce = uuid4().hex
output = Path.cwd() / ("sdk-python-324-lifecycle-" + nonce)
output.mkdir(mode=0o700)
report = {"complete": False, "nonce": nonce, "started_at": datetime.now(timezone.utc).isoformat()}
identities = set()


def call(*arguments, check=True):
    return subprocess.run(arguments, env=ENV, text=True, capture_output=True, timeout=10, check=check)


def full_id(value):
    return re.fullmatch(r"[0-9a-f]{64}", value) is not None


def require_owner(record, identity):
    labels = record["Config"]["Labels"]
    if record["Id"] != identity or labels.get(OWNER) != "sdk-python" or labels.get(ROLE) != "lifecycle" or labels.get(RUN) != nonce:
        raise ValueError("lifecycle ownership differs")


def retain(name, value):
    data = json.dumps(value, indent=2).encode() + b"\n"
    descriptor = os.open(output / name, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
    try:
        os.write(descriptor, data)
    finally:
        os.close(descriptor)


def expired(_signal, _frame):
    raise TimeoutError("inert comparison bound")


signal.signal(signal.SIGALRM, expired)
signal.alarm(45)
try:
    capacity = json.loads(subprocess.check_output(["grafana", "machines", "--json", "--host", "lab4"], text=True, timeout=15))
    machine = capacity["machines"][0]
    if machine["cpu_average_percent"] >= 80 or machine["memory_min_available_bytes"] < 2 * 1024 ** 3:
        raise ValueError("fresh capacity refuses this inert comparison")
    retain("capacity.json", capacity)
    engine = json.loads(call("docker", "info", "--format", "{{json .}}").stdout)
    if engine["OSType"] != "linux" or engine["Architecture"] not in ("x86_64", "amd64"):
        raise ValueError("inert control requires native Linux amd64")
    report["engine"] = {key: engine[key] for key in ("ID", "ServerVersion", "OSType", "Architecture")}
    image = json.loads(call("docker", "image", "inspect", IMAGE).stdout)[0]
    if IMAGE not in image["RepoDigests"] or image["Architecture"] != "amd64" or "PYTHON_VERSION=3.12.16" not in image["Config"]["Env"]:
        raise ValueError("cached official interpreter differs")
    if image["Config"].get("Healthcheck") or image["Config"].get("Volumes"):
        raise ValueError("inert image has undeclared effects")
    retain("image.json", image)
    result = call("docker", "create", "--pull=never", "--cidfile", str(output / "container.cid"),
                  "--name", "sdk-python-324-lifecycle-" + nonce[:12],
                  "--label", OWNER + "=sdk-python", "--label", ROLE + "=lifecycle", "--label", RUN + "=" + nonce,
                  "--init", "--read-only", "--network", "none", "--cpus", "0.25", "--memory", "128m",
                  "--memory-swap", "128m", "--pids-limit", "64", "--user", "1000:1000", "--cap-drop", "ALL",
                  "--security-opt", "no-new-privileges", "--ipc", "private", "--cgroupns", "private", "--runtime", "runc",
                  "--log-driver", "json-file", "--log-opt", "max-size=1m", "--log-opt", "max-file=1",
                  "--entrypoint", "/usr/local/bin/python3", image["Id"], "-I", "-B", "-c", "import time; time.sleep(20)", check=False)
    printed = result.stdout.strip()
    captured = (output / "container.cid").read_text().strip() if (output / "container.cid").exists() else ""
    identities.update(value for value in (printed, captured) if full_id(value))
    result.check_returncode()
    if printed != captured or not full_id(captured):
        raise ValueError("creation channels did not agree")
    identity = captured
    before = json.loads(call("docker", "inspect", identity).stdout)[0]
    require_owner(before, identity)
    if before["Config"]["Cmd"] != ["-I", "-B", "-c", "import time; time.sleep(20)"] or before["Mounts"]:
        raise ValueError("inert command or no-mount boundary differs")
    retain("created.json", before)
    call("docker", "start", identity)
    after = json.loads(call("docker", "inspect", identity).stdout)[0]
    require_owner(after, identity)
    if not after["State"]["Running"] or after["State"]["OOMKilled"]:
        raise ValueError("inert process did not remain running")
    retain("started.json", after)
    report.update({"container_id": identity, "image_id": image["Id"],
                   "oom_create": before["HostConfig"].get("OomKillDisable"),
                   "oom_started": after["HostConfig"].get("OomKillDisable"), "complete": True})
except Exception as error:
    report["failure"] = type(error).__name__ + ": " + str(error)[:500]
finally:
    signal.alarm(0)
    cleanup = {}
    try:
        found = call("docker", "ps", "-a", "--no-trunc", "--filter", "label=" + OWNER + "=sdk-python",
                     "--filter", "label=" + ROLE + "=lifecycle", "--filter", "label=" + RUN + "=" + nonce,
                     "--format", "{{.ID}}")
        identities.update(value for value in found.stdout.splitlines() if full_id(value))
    except Exception as error:
        cleanup["reconciliation"] = type(error).__name__
    for identity in sorted(identities):
        try:
            record = json.loads(call("docker", "inspect", identity).stdout)[0]
            require_owner(record, identity)
            call("docker", "rm", "-f", "-v", identity)
            remaining = call("docker", "ps", "-a", "--no-trunc", "--filter", "id=" + identity, "--format", "{{.ID}}")
            cleanup[identity] = not remaining.stdout.strip()
        except Exception as error:
            cleanup[identity] = type(error).__name__
    try:
        remaining = call("docker", "ps", "-a", "--no-trunc", "--filter", "label=" + OWNER + "=sdk-python",
                         "--filter", "label=" + RUN + "=" + nonce, "--format", "{{.ID}}")
        cleanup["owned_labels_absent"] = not remaining.stdout.strip()
    except Exception as error:
        cleanup["owned_labels_absent"] = type(error).__name__
    report["cleanup"] = cleanup
    report["complete"] = report["complete"] and all(value is True for value in cleanup.values())
    report["finished_at"] = datetime.now(timezone.utc).isoformat()
    retain("result.json", report)
    hashes = {path.name: hashlib.sha256(path.read_bytes()).hexdigest() for path in output.iterdir() if path.is_file()}
    print(json.dumps({"output": str(output), "result": report, "sha256": hashes}, sort_keys=True))
if not report["complete"]:
    raise SystemExit(1)

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-source counter-review of 4057a6f / tree 5f1011339d6dd594d4ac99cc1395dc8fc55cd3a6: the security boundary corrections PASS, but keep installed dispatch held for five unresolved exact-head Sonar findings and terminal CI.

The prior 3dffe66 HOLD items are closed:

  • Config is now a closed image and role projection. Exact image healthcheck, streams, command, hostname, volumes, exposed ports, stop settings, shell, labels and optional metadata are bound; unknown fields refuse. Fresh read-only inspection confirms both selected immutable images have no healthcheck. Their current containerd index IDs equal the selected index digests, platform-qualified IDs and descriptors equal the selected amd64 child digests, and RepoDigests retain the exact index.
  • HostConfig is now allowlisted. MaskedPaths and ReadonlyPaths must match the reviewed Docker 29 defaults plus the fixed-host thermal paths, duplicate or changed sets refuse, both I/O maximum fields must be zero, and an unknown field refuses.
  • The retained inert control rehashes to the published created, started and result records. The same full ID changes only OomKillDisable false to null across start; Config is byte-equivalent and the protected-path projection is unchanged. True, missing and wrong-typed values refuse. I independently confirmed the full ID and exact owner/run label inventory are absent.
  • Explicit linux/amd64 creation and index, child, config, descriptor, platform controls fail closed for ambiguous or foreign image-store states. The selected Server and Python tuple is unchanged.
  • The five requested predecessor cases accept under 3dffe66 and refuse under the successor. The existing exact package, dist-info, RECORD, immutable checker, internal-network, ID cleanup and failure-receipt controls remain active. The reported 182 focused tests, Ruff and mypy results are consistent with the source.

The current Sonar quality gate is green but its exact-head API still reports five open issues: S1192 AaHXXbTkzkHC-1EXHMcI, S7500 AaHXUYhN8-rYvi0mNo6x and AaHXUYhN8-rYvi0mNo6y, and S5778 AaHXUYf38-rYvi0mNo6v and AaHXUYf38-rYvi0mNo6w. The duplicated verifier-path literal is part of this security binding, and the two exception tests should isolate the intended throwing call. Return one narrow source-quality successor, or retain an explicit responsible acceptance and reason for each exact key, before dispatch. Integration is also still running.

No Docker acceptance, wheel installation, SDK activity, Server activity, package publication, or shared closure is authorized by this source review.

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact source-quality rebind of ba4eb9c / tree d66dbbf34ae49097ebd598ba3979989f1c66ba29: PASS for the narrow three-file delta.

The commit is directly based on reviewed 4057a6f and changes only the five named Sonar sites:

  • one VERIFIER_FILENAME constant now supplies all three security-binding references;
  • the two environment comprehensions are replaced by one explicit environment_values loop with the same split-once mapping behavior; the existing received-entry length check still rejects duplicate container environment keys;
  • both exception tests capture the fixed wheel bytes before entering pytest.raises, leaving verify_sdk as the sole invocation that may satisfy the expected exception.

Container Config and HostConfig closure, image index and child binding, OOM false/null normalization, immutable checker, package and RECORD inventory, internal network, cleanup, failure receipt, fixture bytes, workflow, and product source are unchanged. This exact delta introduces no Docker, SDK, Server, installation, or publication effect.

The source HOLD from the five exact Sonar keys is lifted. Keep installed dispatch held until the fresh ba4 exact-head checks are terminal and the five issue keys are absent or explicitly closed on that analysis. The prior boundary limits and lack of shared closure remain.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The requested narrow quality successor is frozen at ba4eb9c, tree d66dbbf34ae49097ebd598ba3979989f1c66ba29. Its full delta from the 4057 boundary PASS is three files, 18 additions and 9 removals:

  • S1192 AaHXXbTkzkHC-1EXHMcI: one VERIFIER_FILENAME constant now supplies all three binding/capture/packet filename uses.
  • S7500 AaHXUYhN8-rYvi0mNo6x / AaHXUYhN8-rYvi0mNo6y: one explicit environment-parser loop replaces the nested identity comprehensions. The same first-equals split, last-value mapping, duplicate detection and closed environment comparison are preserved.
  • S5778 AaHXUYf38-rYvi0mNo6v / AaHXUYf38-rYvi0mNo6w: wheel bytes are captured before each exception context, leaving only the intended verifier call inside it.

No tuple, admission predicate, container setting, checker source or installed scenario changed. 182 focused tests and Ruff PASS. Fresh exact-head CI/Sonar results and the narrow source review remain pending; no claim is made yet that the API issues have closed. The installed cell stays undispatched. There was no further Docker observation, package installation, SDK activity or Server activity for this quality delta.

@rmcdaniel
rmcdaniel marked this pull request as ready for review November 14, 2026 00:38
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security exact-head gate readback: PASS for ba4eb9c / tree d66dbbf34ae49097ebd598ba3979989f1c66ba29.

All current-head checks are terminal green, including lint, package, Python 3.10 through 3.15, integration, target-branch qualification, regression corpus, CodeQL, Sonar and the developer portal. The exact PR Sonar API returns no OPEN or CONFIRMED issues; the five issue keys retained on 4057 are therefore closed on this reviewed successor.

Together with the exact source PASS in #324 (comment), this clears the source and quality prerequisites for the owner to select the manual published-activity acceptance dispatch. It does not itself execute or qualify the installed cell, publish an SDK, or broaden the exact 2.17.2 wheel and Server 3.9.2 tuple.

@rmcdaniel
rmcdaniel merged commit 4dc4e7f into main Nov 14, 2026
22 checks passed
@rmcdaniel
rmcdaniel deleted the sdk-python/211-219-published-acceptance branch November 14, 2026 00:45
@rmcdaniel

Copy link
Copy Markdown
Member Author

Normal integration is complete: PR #324 merged at 4dc4e7f. Its tree d66dbbf34ae49097ebd598ba3979989f1c66ba29 equals the exact reviewed ba4eb9c tree; parents are the unchanged target dbb4311 and ba4eb9c. The head had 21 successful checks and the intended skipped manual cell. Exact source-quality review and fresh terminal CI/zero-open-Sonar readback passed. The merged remote topic ref was deleted with its expected-head lease and independently verified absent.

I selected one ordinary manual published-activity dispatch after confirming no existing dispatch on this commit: run 43536387547, created 2026-11-14T00:46:12Z. Its actual head is exactly the accepted main commit above. The input is only published_activity_acceptance=true; action-policy and lint precede the closed installed cell.

The selected SDK 2.17.2 approved wheel, Server 3.9.2 index/amd64/source and official Python tuple are unchanged from the reviewed machine manifest. The run must supply the actual callback retry, inventory, authority, JUnit and independent cleanup evidence before an installed PASS is claimed. No package release, timer-redrive qualification, local/prepared/session acceptance or shared #211/#219 closure is implied by merge or queue admission.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security first installed-dispatch classification: NONPASS.

Manual run 43536387547 checked out exact merged main 4dc4e7f. Job 132266438702 failed before any Server container or SDK Worker execution. The retained result is complete=false: all 15 exact wheels downloaded and hashed, then docker buildx imagetools inspect --raw for the selected public Server index 8ffcdb2a failed with exit 1. The runner retained no command stderr, so this result does not establish authentication or any other cause. Cleanup reports all owned labels absent.

Artifact 14089174968 uploaded 18 files, ZIP SHA-256 523a582255df7b49f54bfc26f18baf2838780dc175d86c4d0ee91ef02b946cc4. I independently repeated only the public read-only manifest lookup under an empty Docker config after the failure; it exited 0, returned 647 bytes, and the raw bytes hash exactly to 8ffcdb2a36af3129a1987849aafe8715fe0d3bf9a9648467f0b5cb8eeef43ba9. That current readback confirms the tuple is publicly readable now but cannot relabel the hosted job.

The source/merge qualification remains valid. Installed activity acceptance remains absent. No automatic unchanged retry or product diagnosis is inferred from this pre-effect failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant