# Execution supervisor qualification packaging This subtree packages a candidate only. `productionQualified=false` and `redistributionCleared=false` remain explicit in the image, snapshot and workload. No build, image execution, cluster call or deployment was performed by these tools. This is the execution lane only: no strict TypeScript compiler, Node, renderer, QQQ application or printing service is added. Existing peer resources are untouched. ## Local snapshot and build handoff Use existing CPython 3.13+; scripts use only its standard library. No environment install or dependency resolver is needed. `snapshot_execution.py` accepts a JSON object with exactly these keys: `supervisor`, `jna`, `json`, `extism`, `wasm`, `license`, `notice`, `licenseReview`, `cargoInventory`. Each value has exactly `path` (absolute existing local file) and lowercase `sha256`. Supply actual values; there is deliberately no descriptor containing guessed artifact locations/hashes. The supervisor hash must come from the accepted standalone build, not an app QBit JAR. LICENSE/NOTICE are the supervisor's own files; licenseReview/cargoInventory are the bounded release inventory under `../wasm-runtime/docs`. Extism1.41.0, JNA5.18.1, JSON20251224 and the fixed Wasm hash (`WASM_SHA`, kept equal to `../wasm-runtime/PINNED-WASM.json` by `test_deploy.PinnedWasmTest`; rebuild with `../wasm-runtime/Build-Wasm.ps1`) are also enforced in the script. The JNA Linux x86-64 JNI bytes are extracted from that exact JAR and separately hashed. No guest code, certificates, secrets, test fixtures, SDK, compiler or operator configuration is copied. Supervisor class inventory rejects foreign Java package classes; native headers must be ELF64 little-endian x86-64. Run from this directory (paths below are operator-created, not bundled defaults): ```text python snapshot_execution.py ABSOLUTE_LOCAL_INPUTS_JSON ABSOLUTE_NEW_USER_CACHE_DIRECTORY python snapshot_execution.py --verify ABSOLUTE_EXISTING_CACHE_CONTEXT python -m unittest -v test_deploy ``` The output directory must be new and resolve beneath the current user's `.cache`. All hashes are checked before copying and again after copying. Failure never overwrites an existing snapshot; preserve a partial failed context for diagnosis. `metadata/candidate.json` inventories copied inputs without leaking host paths. The closed Docker context contains only Containerfile/payload/metadata. All input files remain unchanged; no recursive cleanup or global package/cache writes occur. The verification mode refuses any unlisted file, symlink or changed hash. Run it again immediately before the separately authorized build; keep the context operator-owned and frozen between verification and build. It does not authenticate an attacker-rewritten manifest: retain its independently recorded digest outside the context as part of the root artifact handoff. Root/operator-only build recipe, **not executed here**, after checking the base image is already cached and the snapshot is reviewed: ```text docker build --network=none --pull=false --platform=linux/amd64 --file ABSOLUTE_CACHE_CONTEXT/Containerfile --tag LOCAL_CANDIDATE_TAG ABSOLUTE_CACHE_CONTEXT ``` BuildKit itself must already exist; this file does not fetch an external syntax frontend. Base is the exact reviewed Temurin21.0.13+9 amd64 manifest `eclipse-temurin@sha256:db724162e4ff5f71fa0a2815026314d9e5e0e9a139f49be1d4717e6930e93341`. The sole RUN removes explicitly named shell/download-client files **inside that image layer**, never on the host. It installs nothing. Root must inspect final layers for unexpected shell aliases/utilities and dependency/linker availability; this pruning is not a containment guarantee or a complete minimal-OS inventory. The exec-form entrypoint bypasses the base certificate shell script. TLS stores are supplied separately. JNA uses its explicit read-only native directory with unpack disabled. Root-owned0555 payload directories/files are non-writable by UID/GID65532; Kubernetes also makes the whole root filesystem read-only. Final-image checks remain required: exact source/artifact/OCI hashes, actual Java/native versions and linkage, no duplicate provider/dependency, real nonroot read-only launch, fixed trusted ABI corpus, mTLS identity, resource/retirement behavior, final OS/native/Wasm SBOM and complete notices. See NOTICE-GAPS.md; packaging that gap report does not discharge any notice obligation. ## Qualification manifest renderer Copy `qualification.disabled.json` to a private local descriptor, explicitly fill every field, and enable only for the agreed qualification exercise. Rendering refuses disabled/missing/unknown/duplicate keys, floating image tags, default RuntimeClass, absent client selectors, secrets as values, and invalid bounds. ```text python render_qualification.py PRIVATE_OPERATOR_DESCRIPTOR NEW_LOCAL_MANIFEST_JSON ``` This creates a Kubernetes `List` and never runs kubectl. The namespace must begin `qqq-qual-` and be distinct from the selected QQQ client namespace. It must be a new, dedicated qualification namespace: a Namespace object is not proof that an existing namespace is safe to adopt. Before any separately authorized deployment, review resource ownership and validate against the target Kubernetes schema and admission policies. The script does not create or change RuntimeClass, node PID settings, client resources, credentials, roles or service accounts. `fixtures/` contains a complete **synthetic, never-deploy** input and rendered List using the reserved `registry.invalid` domain. The positive tests compare the whole artifact and separately check object references, network selectors, volume/Secret paths, security and actual supervisor configuration keys. This is local structural validation, not a substitute for target-cluster schema and admission validation. Wire profile/toolchain/evidence/client namespace strings are limited to the actual supervisor's128-character `[A-Za-z0-9._:-]` grammar; Kubernetes selector keys/values use their separate label and DNS-prefix grammar. Required operator inputs include immutable execution image@sha256; actual sandbox RuntimeClass and selected sandbox nodes; explicit Pod Security version; existing Secret names; exact client certificate DER SHA256→protocol namespace map; QQQ namespace plus nonempty pod labels; profile/toolchain/evidence IDs; finite CPU/memory/tmp/guest/cache/admission limits; and actual node PID policy evidence. Equal evidence strings are a wire precondition, **not qualification**. The server Secret must contain `server.p12`, the trust Secret `clients.p12`, and the password Secret `keyStorePassword`/`trustStorePassword`. Only references enter the manifest. Restrict these Secrets to the qualification namespace and ensure the server certificate matches the DNS name used by the client. The fixed image contains neither credentials nor mutable trust. Clients retain current QQQ authority and broker tokens; readiness supplies no execution permission. Restricted Pod security includes nonroot65532, dropped capabilities, no privilege escalation, RuntimeDefault seccomp, read-only root and bounded memory-backed/tmp. CPU/memory requests equal limits; the memory floor is a conservative refusal check, not demonstrated capacity. Extism common-runtime compilation, per-slot native heap, JVM, frames and caches still need measurements. No service-account token is mounted. No host namespaces, host volumes, PVC, ingress exposure or service-account/RBAC resources are generated. The namespace default-deny policy denies ingress and egress. A second rule permits only TCP18443 from **both** the explicit QQQ namespace and pod labels in one peer. No DNS/HTTP/other outbound rule is added; established response traffic uses the incoming connection. An enforcing CNI and control of other additive policies are prerequisites. Host/kubelet traffic and CNI semantics require actual verification. See the primary [NetworkPolicy specification](https://kubernetes.io/docs/concepts/services-networking/network-policies/) and [Restricted Pod Security controls](https://kubernetes.io/docs/concepts/security/pod-security-standards/). Kubernetes has no per-PodSpec PID-limit field. `pidLimit` and `pidPolicyEvidence` produce explicit expectation annotations only; the operator must configure and verify the selected kubelet/runtime `podPidsLimit` (or stronger sandbox equivalent) and node process reservation before qualification. Node labels are scheduling intent, not enforcement. See [official PID-limit guidance](https://kubernetes.io/docs/concepts/policy/pid-limiting/). ## Readiness and termination limits The server binds its port after fixed-runtime slot compilation and CPU-accounting checks. TCP startup/readiness probes establish **listener availability only**; they cannot prove authenticated admission capacity, intact prepared publications, usable compiler, current grants or safe native cleanup. They may transiently consume a handshake thread; measure this with configured connection limits. The existing QQQ native warm health check, including fresh authenticated heartbeat and complete current required pins, must gate QQQ application traffic. This manifest does not install or bypass that application health check. There is deliberately no TCP liveness probe presented as a native-free watchdog. Hung cleanup and occupied/retired engine slots can leave a listening process. Independent hard-termination/liveness policy is an **open qualification gate**. The30s Pod termination grace permits the current15s bounded server drain and then orchestrator termination; actual CRI/sandbox enforcement must be tested. Do not claim that a signal, Java timer, NetworkPolicy or these manifests alone qualify hostile code or production Kubernetes operation.