Error transparency and permissions audit
Dated design and evidence record. Selected design and evidence quotations retain their source line anchors and historical identities; use the current guides for operation.
# Error transparency and permissions audit Read-only audit of this repository, 2026-10-20 16:47–16:56 UTC. Source checkpoint: 127aef7; diagnostic projection unchanged from the tested image. Runtime probes used installed controller image sha256:129a218bf8d5ce9665f049ef5fd9e0112028c4adfb0b350385be5d01b4c24c96, network none, read-only root, UID 65532, no capabilities, bounded resources. Permission probes used synthetic files in a private temporary container filesystem. No real credentials, model calls, API changes, source edits, or permission changes. ## Reproduced error losses 1. process_reports.py::failure_evidence omits ExchangeFailed.response_head and ChatFailed.reason. A received HTTP 429 plus x-request-id followed by timeout renders only ChatFailed/ExchangeFailed/TimeoutError, losing both received facts. Requested fix: reviewed status/correlation projection; no raw header/body dump. 2. PreparationRetirementFailed(operation_failure=InputRejected(message, diagnostic=...), cleanup=EIO) renders the message and EIO, but drops the native reader diagnostic. Cleanup prevents ordinary AnalysisFailure persistence. 3. Two ToolConversation endpoints failing request-limit then HTTP 503 leave two entries in endpoint_failures, but the propagated exception report contains only the second cause. Successful fallback retains reason/status in public routes, not the earlier protected cause. Preserve safe endpoint evidence through an existing boundary, without transcripts or a new journal. 4. Reviewed AllocationUnconfirmed, RetirementUnconfirmed and ExecutionRefused render as bare class names. Their safe absent/malformed/unconfirmed-receipt reasons disappear. Further source review identifies ResultRejected and other binding outcome classes missing from the explicit projection inventory. 5. process.py::_failure_report writes stderr before trying _publish. A synthetic BrokenPipeError at stderr prevents failure.json publication even when the file sink is available. The independent outputs must both be attempted. 6. The service proxy projects DNS owner-created OSError reasons with errno=None as just OSError; errno=None, losing NXDOMAIN rcode, truncated reply, and mismatched-question distinctions. Preserve reviewed protocol reasons at owner. ## Additional concrete scenarios sent for verification - Cancellation during a model POST bypasses ChatFailed wrapping and can strand HttpTransport.last_failure evidence; requested service cancellations are skipped by ProviderService::_record_task_failure. Test real process shutdown after response headers and with nested cleanup causes. An intentional stop need not become a failure, but known causes/effect uncertainty must survive. - StartFailed.acknowledgement and PublicationFailed.outcome are retained internally but their receipt-presence facts are absent from the operator projection. Distinguish received-but-not-durable from no verified response without dumping records or claiming a new lifecycle authority. - Review safe ResultRejected, ConformerShortfall/ConformerOutputLimit, ModelReportedInputProblem and UploadInputRejected when cleanup prevents their ordinary outcome/evidence path. Do not dump partial coordinate collections. - Proxy 403 becomes a bare httpcore.ProxyError on the controller side. The proxy owns the safe refusal log; verify correlated operator access to both surfaces. ## Preliminary permissions evidence - config.py::read_startup_file: synthetic secret modes 0400/0600 accepted; 0640/0644/0660/0666 refused. Both API signing artifacts and interpreter keys use this secret path; opened descriptor owns UID/mode admission, not a pathname stat. - process.py diagnostics: private directory 0700 and final file 0600 under umasks 000, 022 and 077. AttemptFiles similarly requires root 0700 and records 0600, same UID, single link; it uses descriptor-relative exclusive publication. - Installed /opt/provider: zero group- or other-writable entries. - Three current native-service receipt trees (TMRiIqjV, wMwkAIMq, P3INGwm9): zero group/other permission bits on any retained entry. - No world-writable or set-ID entries found in maintained checkout paths outside .work, .git and the upstream submodule. No set-ID entries found in .work. - Full .work scan found 21 world-writable old qualification scratch entries from Oct 14–15 (formatted source copies/output directories). The private home ancestor is 0700, with no extended ACL grants on inspected roots. Do not present these old public fixture copies as a demonstrated credential exposure or blanket-chmod an active shared tree. - provider_workers_open under umask 000 creates root 0700 but child requests, receipts, ipc and owned directories 0777. Existing service qualification sets umask 077. Production launcher must establish the private creation contract; a bind-mounted child must be assessed in its receiving namespace, not assumed protected by the host-only ancestor. ## References at source checkpoint 127aef7 These locations refer to commit 127aef7, not moving line numbers during repairs. The synthetic probes used the installed image built from 9bb0783; the relevant diagnostic projection was unchanged at 127aef7. - nmrnet_provider/process_reports.py:60,105,162: explicit cause relationships, reviewed owner summaries, bounded private receiving renderer. - nmrnet_provider/process.py:221: stderr/file report publication ordering. - packages/provider-core/src/provider_core/chat.py:72,136: private carrier failure fields and completion/interruption boundary. - packages/provider-core/src/provider_core/conversation.py:71,153: conversation owner and retained per-endpoint failures; _run selects the final cause. - nmrnet_provider/service.py:255: requested task-cancellation observation. - nmrnet_provider/allocation.py:25 and retirement.py:21: reviewed host allocation and retirement reasons omitted from the original receiving projection. - nmrnet_provider/result.py:62: reviewed scientific result-admission reasons. - nmrnet_provider/smiles.py:55 and smiles_protocol.py:56: shortfall/output-limit evidence that normally follows the AnalysisFailure path. - packages/provider-core/src/provider_core/starting.py:27 and publication.py:25: received acknowledgement/outcome retained alongside independent storage failure. - tools/provider_proxy.py:34: native failure projection; tools/bound_http_proxy.py _query_ipv4 and resolve_ipv4_bound: DNS protocol failure creation and aggregation. - nmrnet_provider/config.py:212: descriptor-based startup ownership/mode checks. - packages/provider-core/src/provider_core/attempt_files.py:99,147,289: private store-root admission, record admission and exclusive durable publication. - tools/provider_workers.sh:10: private root versus inherited child creation modes. Observed native-service receipt directories: .work/qualification/provider-service-nmrnet-native-service-TMRiIqjV .work/qualification/provider-service-nmrnet-native-service-wMwkAIMq .work/qualification/provider-service-nmrnet-native-service-P3INGwm9 Representative old world-writable scratch entries (metadata only; not consumed as trusted runtime configuration in this audit): .work/qualification/native-returned-diagnostics-20261015/formatted.py (0666) .work/qualification/explicit-launcher-presence-20261014/outputs (0777) ## Repair checkpoint, 2026-10-20 17:03 UTC Peer reports that new receiving tests cover missing owner reasons, native input diagnostics, received-but-not-durable receipt facts, broken stderr with working file output, and both outputs failing. These edits remain uncommitted at this checkpoint and have not yet been independently revalidated by this auditor. Endpoint-history and interruption-evidence handoffs are still being implemented. Do not treat the original findings as verified repaired based on acknowledgement. ## Independently qualified receiving repair, 2026-10-20 The first repair closes reproduced findings 1, 2, 4 and 5 in current source. The correlation helper moved unchanged from api.py::_header_request_id to transport.py::response_request_id, reused by API and operator projection. The renderer reads current ChatFailed/ExchangeFailed response metadata, admits one bounded correlation ID, includes the owned chat reason and excludes all other headers/body/notes. InputRejected's native diagnostic uses the existing redact-before-head/tail window, alongside its primary and independent cleanup. The exact-owner inventory now includes allocation/retirement and lifecycle refusals, ResultRejected, shortfall/output-limit/model-reported input summaries, UploadInputRejected and CredentialRejected's original parser cause. Serialized scientific replies, partial coordinate arrays, model explanation/observation and arbitrary native exception messages remain excluded from this projection. StartFailed reports acknowledgement presence and observed Attempt state; PublicationFailed distinguishes a received observation, matching commit receipt and reviewed conflict. These facts establish neither durable storage nor reuse. Both protected report outputs are attempted independently. Broken or closed stderr does not prevent file publication. Reporting failures join the original operation/cleanup causes; both failed sinks raise the owned aggregate. The held process's existing finally still retains its work/store. A real child fault witness verifies both errno causes, held process/store, absent forbidden cleanup and release only after exact parent kill. The extra child marker is test-only observation, not another production diagnostic sink or journal. Qualification: coordinator and independent authority reviewer each ran make test/integration/provider-core/process: 32 tests passed (independent run 17.721 seconds). Tests receive actual stderr plus failure.json and exercise real signed local API/process shutdown; no external model or scientific native execution was needed. Selected-file Ruff check/format and Bash syntax passed. Independent authority/provenance inspection found no remaining signal in this subset. Local logs: /tmp/nmrnet-transparency-receivers-final.log and /tmp/nmrnet-independent-reports.log (ephemeral; maintained tests are the proof). The installed image quoted above is the original audited artifact, not a claim that it contains this source repair; refreshed image qualification remains due. Still open: finding 3 (endpoint history), finding 6 (DNS protocol reasons), interruption/effect handoff, joint proxy/controller operator access and production creation/mount permissions. Existing permission observations remain observations from the original audit; no historical scratch permissions were changed. ## Independently qualified DNS repair, 2026-10-20 Finding 6 is now qualified in current source. The existing DNS response/name decoders create exact owner-typed refusals from a fixed reason vocabulary; the response code is the parsed four-bit numeric field. OSError/ValueError catch contracts and DNS/parser ordering remain unchanged. Service diagnostics render only those exact owned reasons; arbitrary native errors remain type/errno only. No remote name, resolver address, packet bytes, exception note or request header is rendered. Alias-cycle text no longer interpolates the destination hostname. Four binary-packet witnesses exercise real _query_ipv4 -> resolve_ipv4_bound -> ServiceProxyHandler receiving output: rcode3, short response, wrong question and truncated compression pointer. Only UDP I/O, resolver inventory, transaction ID and time are injected. Each verifies the owned reason, fixed 502, one closed UDP exchange, no destination TCP allocation and absence of private packet/request canaries. Coordinator and independent provenance reviewer each ran make test/unit/provider/proxy: 60 tests passed, including all selected acquisition and proxy-posture regressions. Independent code/provenance source review found no further signal; selected-file Ruff/format and existing guard scans passed. Ephemeral independent log: /tmp/nmrnet-independent-dns.log. Endpoint history, interruption/effect handoff, joint operator access and the production host creation/mount contract remain open. This protocol-diagnostic repair does not establish external DNS/network reachability or deployment. ## Useful private diagnostic correction, 2026-10-20 Review of df951d0 found that the first scientific/model cleanup tests wrongly treated useful private diagnostics as secret canaries. Safe summaries alone did not preserve the reason normally retained by session._failed_preparation. That first checkpoint was therefore incomplete for these cleanup scenarios. Current source projects ConformerShortfall.partial.diagnostic, only the native diagnostic text from ConformerOutputLimit's serialized reply, and the model's explanation through the existing redact-before-head/tail window. Model explanation remains explicitly unverified on the protected operator surface. Coordinates, stereochemistry, raw provenance and observation/transcript bytes remain excluded. The receiving regression now requires useful native/model text, native tail and omission facts, alongside independent cleanup EIO. Configured-key spellings, Bearer/key-field canaries are redacted; a PRIVATE_* prefix is not itself a secret classification. Coordinator and independent provenance reviewer each reran make test/integration/provider-core/process: 32 passed (independent 16.017s). Independent authority/provenance source review found no further signal in this correction. Fresh log: /tmp/nmrnet-independent-private-diagnostics.log. The adjacent DNS simplification keeps the two exact disclosure-owner exception types and direct code-owned English at each raise. The unused reason-code table and attributes are removed; only the parsed numeric rcode is interpolated. The existing binary-packet witnesses and full focused proxy lane still pass (60 tests). No new abstraction or routing behavior was introduced. The permission probes above are preliminary. The requested full permissions audit remains due after the transparency repairs; production creation/mounted subtree qualification is still open. Historical scratch was not blanket-chmodded. ## Endpoint-history failure handoff, 2026-10-20 The core now transfers its indexed original endpoint failures on final failure, cleanup failure and successful conversation return. A foreign scientific/tool failure keeps its exact exception identity and prior explicit cause through an owned context; no successful tool is repeated. The operator graph deliberately traverses these owned indexed causes under its existing 64-node bound. The maintained process receiving test uses real local TLS ChatEndpoints: endpoint 0 rejects an oversized request without sending it, then endpoint 1 receives HTTP 503. Both stderr and failure.json retain both reasons, received status and the reviewed request ID, excluding Job content, response body, other headers and keys. The focused process lane passes 33 tests; core chat passes 27, including fallback followed by exact cancellation with its original earlier cause and no extra dispatch. Independent source review identified an installed-test namespace mistake, corrected before the passing run; no remaining source signal reported. Ephemeral logs: /tmp/nmrnet-endpoint-history-receiving-final.log and /tmp/nmrnet-endpoint-history-core-final.log. This closes the terminal-failure history loss. Successful history is handed off by core but its binding/durable evidence retention remains the next repair. Interruption during a handed-off POST and the full permissions/launcher work remain open. This source result does not update the previously quoted image. ## TLS fixture lifetime qualification, 2026-10-20 The history receiving/service checks exposed a fixture lifetime gap: asyncio accepts TLS handshakes before TlsPeer.handle registers its task. A real ClientHello observed by the SNI callback, with no completed handshake or HTTP handler, made the existing two-second server teardown fail. The fixture now supplies explicit 0.5-second TLS handshake/shutdown deadlines inside that observation budget and closes late handler entrants. After accepted transports close, it gathers the final handler set so a late handler's failure is also observed by its owner. It does not widen the teardown deadline or alter production transport budgets. The new adversarial packet/handshake witness went red before the correction and green after it; the chat lane passes 28 tests. Logs: /tmp/nmrnet-tls-handshake-fixture-red.log and /tmp/nmrnet-tls-handshake-fixture-final.log. This proves retirement of an admitted incomplete test-peer handshake. A separate intermittent service Hello retirement failure was not causally established by its original wrapper-only trace. One scratch receiving-renderer diagnostic run of that unchanged test stopped cleanly, with HTTP200 plus cancellation retained on the API/transport owner and no cleanup failure. This is evidence for the still-open interruption-reporting work, not proof that the earlier failure had the same cause. No production deadline was relaxed or retry added. ## Successful fallback evidence retention, 2026-10-20 Before each scientific tool dispatch, the interpreter projects original indexed endpoint failures using the existing configured-key-aware operator renderer. Immutable private bytes stay on InputPreparation, outside public interpretation. NMRNetSession includes them in its prepared identity under the existing total ProtectedEvidence capacity gate, before prediction preparation, then carries them into terminal success or recognized scientific/model failure evidence. An evidence overflow refuses prediction and retains the complete attempted evidence; it is not truncated, retried or called invalid input. Model-report cleanup can also traverse original endpoint causes without disclosing transcript/body content. Connected local TLS witnesses cover request-limit -> HTTP503 -> successful SMILES preparation, exactly one generation and prediction, private terminal retention, unchanged public result, and fresh-store recovery of execution entry after an injected stop before prediction. All four model-report guidance cases also retain prior endpoint causes while reaching the original failure recipient. These are scripted model replies, not real semantic-interpreter qualification. Focused contained lanes pass: service 22, prepared-identity 31, interpreter 18. The identity lane exposed two older API fixtures using generic unmarked TLS responses. Independent scratch reproduction traced both failures to the exact missing Nmr-Api-Topology response marker. Those fixtures now use the existing api_tls_peer; production envelope admission remains strict. Source review found no further ownership/privacy signal. Logs: /tmp/nmrnet-success-history-service-qualified.log, /tmp/nmrnet-success-history-identity-qualified.log, /tmp/nmrnet-success-history-interpreter.log and /tmp/nmrnet-independent-identity-causal.log (ephemeral). Interruption during a handed-off POST, full permissions audit and the connected production launcher remain open. Previously quoted installed image is stale; source-level qualification does not update or qualify that artifact. ## Model interruption and nested operation evidence, 2026-10-20 ChatEndpoint now attaches its owned interrupted-request context to the exact caller cancellation, preserving the live transport failure and any previous explicit cause. Transport's original primary may be that same cancellation; the protected graph deliberately represents this cycle with exception references. InputPreparation preserves a distinct chooser failure when joining after an outer failure, on both clean and failed retirement. A bare expected child cancellation remains an ordinary stop. A settled operational child error keeps its original object and diagnostic; successful joining is not called retirement failure. AttemptExecutor captures child cancellation inside the actual coroutine, before Task.result can consume it. Its existing owned failure is now updated in place, so escaped references receive late operation evidence and independent cleanup observations. Caller cancellation remains primary through cleanup cancellation; an ordinary/API primary remains reachable when cleanup cancellation propagates. Session retirement retains the cancellation's earlier owned cause, and controller settlement no longer clears that chain. Service suppresses only bare requested cancellation and records initiating failures before shutdown-induced observations. The real foreground witness receives a model response head, then SIGTERM. Both protected operator outputs retain HTTP200, the reviewed request ID and an explicit statement that the model request may have been processed. One model POST, zero prediction/source effects, no terminal send and no resend are required. With independent host-retirement EIO, the process stays alive and its actual store stays locked until exact parent kill. Native allocation is a recording test port; the interpreter, TLS/CONNECT, input owner, controller, signals, store and process reports are real. This does not qualify a production native launcher or external model interpretation. Ordinary idle SIGTERM still exits zero. Focused contained results: process 35; core chat 29; core prepared-identity unit 68; service 22. These include the actual receiver for nested model diagnostic plus cleanup cancellation and exact canonical-record recovery after a timed-out child join. A later user finding exposed non-cancellation WorkerReportedFailure after parent cancellation: the corrected fixture reproduced the absent parent cause, then the narrow condition repair passed all 19 interpreter tests. That witness also receives stderr and failure.json, requires the useful worker reason, redacts credential-field text and requires no retirement failure after a clean join. The first attempt had a fixture constructor error; it was not behavioral proof. Logs: /tmp/nmrnet-interrupted-model-receiving-final.log, /tmp/nmrnet-interruption-executor-final.log, /tmp/nmrnet-interruption-chat.log, /tmp/nmrnet-interruption-service-final.log, /tmp/nmrnet-operational-child-red-final.log and /tmp/nmrnet-operational-child-qualified.log. Independent source audits found no remaining signal in this subset. An independent sequential rerun also passed process 35 (22.142s) and interpreter 19 (0.393s); no lane containers remained. Independent logs: /tmp/nmrnet-independent-interruption-process.log and /tmp/nmrnet-independent-interruption-interpreter.log. These still use recording native/fault ports; they do not establish real native cleanup or image freshness. Still open: expected Hello cancellation retains API evidence on its API owner but does not yet reach the final process recipient. The planned narrow follow-up retains it as a protected shutdown observation, separate from failures deciding exit/release; received headers must not imply verified Hello acceptance. Full permissions qualification and the connected production launcher remain due. The earlier installed image remains stale until rebuilt and qualified. ## Expected Hello interruption reaches shutdown output, 2026-10-20 The service retains the original dedicated Hello API failure when its requested task cancellation interrupts an actual request. This single observation does not change success/failure or release decisions. After confirmed retirement, the existing protected result.json includes reviewed status/correlation/cause evidence and acceptance_confirmed=false. HTTP200 headers are not a verified HelloAccepted body. If an independent failure requires failure.json/stderr instead, that same observation joins the existing report only after exit/release decisions. No new journal, protocol, replay or lifecycle authority is introduced. The real foreground witness completes startup Hello, then receives headers for the second periodic Hello and signals SIGTERM. A child-only received-head number gives a distinct barrier, avoiding a delayed parent erasing the periodic marker. The process exits zero with the protected observation, empty reopened store and exactly two Hello sends. A separate adversarial result-publication EACCES witness requires the Hello observation and write error in both stderr and failure.json, exit one, confirmed resource release and no extra send. The API peer and private CONNECT route are real local TLS; only the fixed head marker and optional result write failure are injected. This is not deployed API/GUI proof. The old source reproduced a missing interrupted_hello field on that actual clean stop. Focused process qualification now passes 37 tests (27.189s); selected-file Ruff check/format and whitespace checks pass. Independent code review found the initial shared-marker race; the numbered barrier and failure-output witness correct it. Independent authority/privacy and code reviews found no remaining signal. The independent process rerun also passed 37 tests (27.482s), with no lane containers left. Log: /tmp/nmrnet-independent-hello-observation.log. Logs: /tmp/nmrnet-hello-observation-red.log and /tmp/nmrnet-hello-observation-final.log (ephemeral). The reproduced error-transparency repairs are now implemented in source, with the receiving checks above. The installed controller image still needs refresh; full permission probes and production host creation/mount qualification remain open. Preliminary modes from the original artifact are not current-image proof. ## Refreshed controller and full permission audit, 2026-10-20 The controller was rebuilt once after the error repairs at source 1131107: sha256:62eb7abc76846b404b194432080d946d9dcd2670dce5538349d9e2966909a675. The build succeeded and .work/provider/image-id identifies that artifact. The focused installed-runtime lane passed four tests. Build/runtime logs (ephemeral): /tmp/nmrnet-provider-repaired-image-build.log and /tmp/nmrnet-provider-repaired-runtime.log. Independent final source rerun at 1131107 passed process 37, interpreter 19 and proxy 60; report supplied by the foreground auditor, /tmp/nmrnet-monitor-errors-final-20261020.log. Scientific accuracy witnesses were not repeated for these diagnostics-only repairs. Independent foreground audit on that refreshed image reports: secret modes 0400/0600 accepted, 0640/0644/0660/0666 refused; diagnostic directories 0700 and files 0600 under umasks 000/022/077. /opt/provider has zero group/other-writable entries; an attempted runtime-root write fails EROFS (30). Through an actual read-only bind grant, caller UID:GID 1000:1000 can read a synthetic 0600 key but cannot write it (EROFS). UID 65533 with the same GID 1000 receives EACCES (13) on read and write. No real credentials were used. The production caller must explicitly select the admitted file owner's UID/GID; the image default UID 65532 is not a reason to weaken same-EUID or credential-mode checks. Read-only metadata inspection at 1131107 found 533 maintained tracked regular files excluding the upstream/.git trees, all caller-owned/single-link, without maintained-tree symlinks, set-ID, world-writable files or extended/default ACLs. The 79 provider capture roots contain 191 private directories and 1041 files: 891 mode0600, 150 mode0664 metadata markers behind private directories. The 12 service captures specifically contain 434 files0600 and 124 directories0700. A native-capture snapshot contains 83 files0600 and 35 directories0700. No unexpected links, special files, set-ID or ACL grants were found in those captures. Counts are observations of changing qualification outputs, not a permanent inventory. The foreground auditor additionally inspected upstream and .git: no world-writable/set-ID entries, and recursive getfacl --skip-base across .work/.git/upstream found no extended ACL grants. No credential-named files were found in .work; this is a filename observation, not a secret-content scan. No credential contents were read by these metadata probes. The earlier 21 world-writable public-fixture scratch entries remain: ten files and eleven directories. A symlink's displayed 0777 is not evidence about its target. Private ancestor traversal prevents demonstrated cross-UID exposure here. These observations do not authorize blanket chmod or historical deletion. The remaining creation defect was reproduced using actual provider_workers_open under umasks000/022/077, without engine dispatch: its allocation root is0700 but requests/receipts/ipc/owned are respectively0777/0755/0700. Role directories and create-intent likewise inherit the mask. A worker's later umask cannot repair an existing bind root; its host ancestor is absent in the receiving namespace. The qualification caller already uses077. Fresh host creation needs an explicit private contract, followed by actual production caller UID/mount qualification. Synthetic reproduction retained under /tmp/nmrnet-permission-open.fMNR3VZu. Independent artifact/mount probe confirms the image input label sha256:5963a602de5e9bb50e8d3405c4a9b5801a6caea7c4a1bbb6266ef8cd640e5c61, matching committed controller inputs at113110723085a730e2f442afec4e7296e4aa4d52. It inspected /opt/provider, /usr/local/bin, /usr/local/lib, /usr/lib and resolved symlink targets:3629 entries,96 symlinks; zero g/o-writable, set-ID, non-root-owned, broken or unreadable entries. Image user65532:65532, isolated process entrypoint, no declared volumes/ports or unexpected environment names; values not displayed. The only key/config filename candidate was certifi's public CA bundle. Six actual read-only grant mutation probes failed EROFS; intended Unix-socket communication succeeded. CallerUID1000:GID1000, networknone, zero capabilities, no-new-privileges, 2CPU,512MiB/no swap,64PIDs were observed. The old separately mounted receipts root retained0777 in its receiving namespace, confirming the host-creation finding. Report (ephemeral): /tmp/nmrnet-provider-permissions.8mI39ttH/report.json, SHA2563a660c45064f8bc2427eedd40297ac9a048a36e15f28d74317257856e6b68550. Both exact probe containers were removed; ownership-filtered inspection was empty. These are artifact/component proofs using synthetic grants, not production launcher proof or whole-image secret-content forensics. Fresh host-creation repair: provider_workers.sh now creates its bind roots, role/diagnostic/IPC directories and both receipt branches with explicit0700; create-intent uses scoped077. It neither changes the caller's mask nor modifies retained history. The maintained make test/unit/provider/allocation witness reproduced requests0777/0755 under000/022 before the repair; all23 tests then passed, including all three masks, live IPC permissions before removal, retained files0600/directories0700, unchanged caller mask, no-allocation retirement receipt and unchanged six exact modeled engine calls. This tests actual host Bash with a recording engine, not real container grants or native science. Logs: /tmp/nmrnet-allocation-permission-red.log and /tmp/nmrnet-allocation-permission-final.log. A production caller must still set077 before its own unrelated host creation and prove its actual mounted grants. The installed-image owner probe exercised30 startup,15 diagnostic and27 store state/fault/reopen cases under000/022/077. It imported production modules only from the installed environment. Temporary synthetic ownership setup occurred only in tmpfs; the actual calls ranUID1000 with zero capabilities, networknone, read-only root,512MiB,2CPU,64PIDs. Report (ephemeral): /tmp/nmrnet-permissions-installed.aIp4EAln/output/report.json; log /tmp/nmrnet-permissions-installed-audit-verified.log. Its exact container was retired. Startup checks covered link/FIFO/directory/foreign-owner refusal and nonsecret writable input; diagnostic checks included partial publication faults; store checks included retained state, write faults and reopening. That probe found one additional creation gap: process._publish's default open creates0666/0644 under000/022 before its fchmod. A failing fchmod leaves only an empty broad-mode pending file under its0700 parent: no diagnostic bytes were written, and no credential leak was demonstrated. The cached refreshed image reproduced exactly0666/empty under000 in /tmp/nmrnet-pending-permission-red.log. The source repair supplies0600 atomically through built-in open's descriptor opener, preserving exclusive creation and the existing with-block close owner. fchmod remains to normalize more restrictive ambient masks before writing; there is no raw-descriptor transfer framework. The new receiving regression injects that exact failure under000/022/077, requires the original exception, empty0600 staging and no final file. The focused process lane passes38 tests (27.797s), including existing independent-sink and held-store witnesses. Selected-file Ruff and whitespace checks pass. Source-only authority and provenance audits found no additional signal. Log (ephemeral): /tmp/nmrnet-pending-permission-final.log. This small source correction awaits the next coherent image refresh; the1131107 artifact above truthfully still has its reproduced empty-staging defect. The final installed-owner audit extended store coverage to42 cases (rather than the earlier27), including wrong root/record modes, actual foreign ownership, link/hardlink/FIFO/directory refusal, and root-owned public startup input. Report: /tmp/nmrnet-permissions-storage.qWy7vXOD/output/report.json; log /tmp/nmrnet-permissions-storage-audit.log. Earlier synthetic setup failures retired before production-owner calls and are not qualification evidence. Installed repair qualification after the coherent startup-capture build: source9b9c347, image sha256:cf5d5ca374b2c5dbd21db44a5a201a4d54f731add22c5c585a8bccacfdc4b741. The installed process.py SHA256 76fd951484b2acabcbbccf29a638f62bf1048edc942ba06e400d6c7e67fe67ab matches source. Six independent cases exercise normal publication and injected fchmod-EIO under000/022/077: normal exact bytes0600 with no pending alias; the identical EIO object escapes, leaving only empty0600/currentUID/nlink1 pending and no final file. UID1000, capabilities0, read-only root, networknone, no-new- privileges,2CPU,256MiB/no swap,64PIDs; only a synthetic read-only probe script and private tmpfs were granted, without source/test ports, state or native grants. Exact container wait returned0, stopped inspection was confirmed and removal completed. Evidence: /tmp/nmrnet-installed-publish.zSlzD2jm/start.stdout and its adjacent posture/retirement receipts; log /tmp/nmrnet-installed-publish-fault.log. The four installed-runtime tests additionally pass on this image (0.733s), including imports of the actual capture/proxy modules. Logs: /tmp/nmrnet-startup-capture-image-build.log and /tmp/nmrnet-startup-capture-installed-runtime.log. The unchanged full permission and scientific matrices were not repeated; production launch grants remain open. ## Limits and follow-through These are local source and installed-renderer checks. They do not qualify a real external interpreter or deployed API/GUI recipient. The production host launcher is still being connected. Peer implementation and regression results remain to be reviewed; notification is not proof of repair. Continue monitoring. ## Actual foreground/API run observation, 2026-10-21T21:00Z Qualification source bb15cf2676525cc605949e2431b741a2ff9a616d, installed controller sha256:5b40da88e76255b3761a21386a3aa5135aac9c82fb165f8eb106ed20bce05bea. The first complete successful actual-API witness is detailed in003 R21, with retained capsule .work/qualification/provider-api-pasted-20261021-2100. Independent read-only reviewers inspected the actual captured metadata and exact retirement receipts; no real keys were read or effects rerun during that review. All ten container IDs (peer, stage, public client, capture/controller/three routes, reader and prediction) have stopped/removal receipts. Captured posture establishes caller UID/GID1000, readonly roots, dropped capabilities and no-new-privileges. The peer has only fixed fixtures/public model output/diagnostics; real provider and client credentials appear only in their separate readonly grants. Successful startup/Hello also exercised the real descriptor-based credential UID/mode admission. Private native, state, source, component, route and output trees have no group/ other permission bits. Public source-code capture copies are0644/0755 under0700 ancestors; these are code, not credential material. No blanket chmod was performed. The process's protected result says stopped/requires_host_retirement=false and retains an interrupted Hello's acceptance-unconfirmed cause. The actual accepted AnalysisResult is independently verified through signed public readback. This is connected evidence for error/effect separation, not a new lifecycle authority. Limit: helper postures enumerate mounts; controller/native posture receipts rely on the existing source-owned mount argv and fixed profile checks rather than an independent full live mount enumeration. This run supplies positive production creation/credential-admission evidence for one caller UID; it does not repeat or replace the earlier synthetic denial/foreign-UID/EROFS/ACL matrix, prove deployment, or qualify every future environment. Original private paths/state remain outside version control; the compact receipt archive explicitly excludes key contents. ## Corrected interpreter rejection evidence, 2026-10-22 Repair commit af63281 retains correction evidence that corrected selections previously lost. Before the repair, ToolConversation counted a rejected tool turn and kept its last safe feedback text, but discarded the caught ToolRejected object. A later accepted selection therefore lost that reason and the chained InputRejected's private parser diagnostic from the retained interpreter evidence. The new focused tests reproduced the missing history before implementation. This keeps the reason for an input change available to an operator after selection succeeds, under the existing model-feedback and scientific-effect policy. ToolConversation now retains (one-based turn number, ToolRejected) entries within the existing total model-turn limit. Original dispatch rejection objects and their causes survive corrected success, exhausted turns, later operational failure, cancellation and independent connection-cleanup failure. The primary failure and cancellation objects retain their identity and earlier causes. Multiple-call refusals retain the conversation owner's safe typed reason. InputInterpreter combines earlier endpoint failures and correction failures in the existing private interpreter_diagnostics capability before invoking the next preparation tool. The session regression uses installed provider-core and current NMRNet source, a failed endpoint, a reader rejection and then one successful generated-input preparation. It checks that the safe reason and bounded, credential-redacted parser diagnostic are present before generation and survive prepared/result evidence. The public interpretation exposes the correction count, with no correction reason, parser dump, model transcript or raw tool arguments added. A final model problem report also retains the earlier correction evidence privately. The process renderer admits the exact ToolRejected safe message and traverses correction histories, including an exhausted conversation followed by independent cleanup failure. Focused contained qualification passed: make test/integration/provider-core/chat (31 tests), make test/integration/provider-core/interpreter (24 tests), and make test/integration/provider-core/process (39 tests). Ruff 0.15.15 lint/format passed for the seven changed Python files in the recorded offline checker image; Bash syntax and diff whitespace checks passed. The interpreter selector now names its interpreter/preparation test files explicitly: the previous wildcard also collected ambiguity tests without their separately owned fixture mount, causing two reproduced ModuleNotFoundError failures unrelated to correction retention. References fixed at af63281: - packages/provider-core/src/provider_core/conversation.py::ToolConversation.run, _run, _retire_endpoint and retire; ConversationResult/ConversationFailed/ ConversationRetirementFailed carry the private correction history. - nmrnet_provider/interpreter.py::InputInterpreter.run and ModelReportedInputProblem; process_reports.py::_owned_relationships and _safe_owner_details; tools/container.sh's interpreter test selector. - packages/provider-core/tests/integration/chat/normative/test_conversation.py:: test_corrected_success_retains_original_rejection_without_public_reason_or_arguments; adversarial/test_conversation.py::test_prior_correction_survives_exhaustion_operation_failure_cancellation_and_cleanup. - tests/integration/provider_core/adversarial/test_nmrnet_interpreter.py:: test_corrected_reader_rejection_keeps_private_diagnostics_and_prior_endpoint_failure_before_generation and test_expected_reader_rejection_returns_only_its_safe_reason. - tests/integration/provider_core/normative/test_nmrnet_reports.py:: test_exhausted_correction_keeps_turn_reason_and_private_parser_diagnostic_through_cleanup. ## Received scientific/preparation evidence repair, 2026-10-22 Three further receiving regressions reproduced a separate gap: when scientific result assembly or preparation-evidence admission failed, the owning exception kept the received payload in memory, but the protected process report omitted useful result metadata or preparation diagnostics. Repair commit bdd95d2 adds reviewed partial projections so the operator can identify the received result and inspect relevant preparation failures when ordinary evidence admission fails. The scientific-result summary reports structural facts, request hash fields with valid SHA-256 spelling, and the prepared identity's schema, byte length and hash. It records received geometry/row counts, inspected row counts, row-shape failures and omissions. It copies no prediction values, coordinates or provenance blobs. Preparation summaries retain reviewed fingerprints/counts and credential-redacted diagnostic windows, including generation, unverified model-report and earlier interpreter failure evidence. The projection selects known fields from its owned preparation document. Existing geometry/atom limits bound structural inspection; the existing 64-node failure budget bounds interpreter entries. Diagnostic windows retain at most 8192 characters after redaction, with explicit omission counts. Malformed diagnostic graphs do not prevent the other owned causes from reaching the operator. ResultAssemblyFailed and PreparationEvidenceFailed now say explicitly that the full raw result or rejected preparation payload remains only in memory. The process report carries partial metadata/diagnostics and the underlying cause. It cannot reconstruct the complete result and grants no salvage, replay or repeated-science authority. The regression receives a malformed worker result once, preserves its result-admission cause and independent cleanup cause, and proves that another execute attempt cannot repeat that scientific dispatch. An oversized preparation diagnostic fails before scientific prediction starts. Final post-format qualification at bdd95d2: make test/integration/provider-core/process passed 44 tests in 27.543 seconds. Pinned Ruff 0.15.15 lint/format passed for the three changed Python files; diff whitespace checks passed. The earlier 42-test run was intermediate, not the final proof. Ephemeral local logs, not tracked repair artifacts: - /tmp/nmrnet-received-evidence.vaZga7/red-process.log SHA256 45332d538ae1c49685903431a1bdc123072413228d88094eb126a81c33b2d6cc - /tmp/nmrnet-received-evidence.vaZga7/final-formatted-process.log SHA256 3e51ba89a5958fbfe0e86205343da15ecddf7efa5e2f3585b5888c110dc1cbbc Only these references are recorded here; raw logs and full private trees were not added to version control. References fixed at bdd95d2: - nmrnet_provider/session.py::ResultAssemblyFailed and PreparationEvidenceFailed; process_reports.py::_received_result_summary and failure_evidence's preparation_summary and exact-owner projections. - tests/integration/provider_core/normative/test_nmrnet_reports.py:: test_received_result_is_identified_without_retaining_numeric_output_or_repeating_science; test_unretained_preparation_diagnostic_has_bounded_receiving_evidence_before_prediction; test_received_result_projection_bounds_malformed_geometry_and_row_metadata; test_owned_preparation_diagnostic_variants_keep_safe_facts_and_redact_even_valid_digest_secrets; test_malformed_preparation_diagnostics_do_not_prevent_other_causes_from_reaching_the_operator. These checkpoints concern contained source and receiving-report behavior. No live external model/API calls or native scientific execution were repeated for these repairs. They do not clear the original permissions audit, qualify a new installed/deployed image, or replace the earlier live-run and permission evidence. ## Aggregate fixture follow-through, 2026-10-22 The aggregate provider-core integration lane exposed missing test-input grants and three stale core fixtures after the focused repair lanes had passed. A contained probe inspected the recovery exceptions' actual owned causes: PublicationFailed.cause and StartFailed.cause were ApiFailure objects rejecting the missing configured Nmr-Api-Topology marker. Their generic TLS fixtures sent only content-type, cache-control and content-length; these were envelope failures, not replay expiry or clock failures. Fixture repair 2a2f7a9 reuses the existing api_tls_peer helper for the publication and starting tests. Their original exact retained-body, one explicit resend and refused-repeat assertions remain. The Upload fixture separately issued a grant expiring 2026-10-19 while the receiving owner's wall clock had reached 2026-10-22. The positive acquisition test now freezes only provider_core.uploads.datetime.now at 2026-10-18 around acquire(). Signing, grant parsing and monotonic deadlines keep their own clocks; the grant date, production expiry check and existing expired-grant refusal test are unchanged. No production implementation changed. Focused installed-core qualification selected test_publication.py, test_starting.py and test_upload_acquisition.py: five tests passed in 0.329 seconds. Pinned Ruff 0.15.15 lint/format passed for those three files. The owned-cause probe was private diagnostic code, not a new maintained runner or runtime feature. The baseline failures remain in the ephemeral local log /tmp/nmrnet-received-evidence.vaZga7/aggregate-provider-core.log, lines 722-784. The focused five-test output was observed in the tool transcript, without a separate saved log. Harness/probe repair f096e7c grants the existing inspection-probe modules and preparation fixtures read-only to their aggregate/dedicated test lanes. The resource helper is granted only to the aggregate integration lane. The inspection-only capability implements the existing immutable diagnostic-retention contract and keeps correction evidence in its private result, with malformed argument/key canaries excluded. This adds no scientific preparation or replay authority. Source/test references fixed at f096e7c are tools/container.sh, tests/test_provider_core_launcher.py, tests/integration/provider_runtime/ interpreter_ambiguity.py::_InspectionOnly and run_batch, and tests/integration/ provider_core/adversarial/test_nmrnet_interpreter_ambiguity.py. Final aggregate qualification ran 375 tests in 65.722 seconds, OK with 11 existing native-runtime gates skipped: six native-service tests newly discoverable after the resource grant was repaired, three scientific-lifecycle tests, one live-worker test and one Upload-reader test. These skips do not qualify native execution. After that run, the resource-helper grant was narrowed to aggregate-only. The printed aggregate argv before/after narrowing was byte-equal; the aggregate was not rerun. Final narrowed-launcher qualification passed eight tests in 0.402 seconds, and the dedicated inspection-probe lane passed nine in 0.267 seconds. No live model or native scientific effects were rerun for these fixture repairs. Ephemeral local receipts under /tmp/nmrnet-received-evidence.vaZga7/: - final-aggregate-provider-core.log SHA256 0f343d508273449079d5b948eb75a4358dbee5d84e72bc0d7b3ecde6701e07ec - aggregate-before-resource-narrowing.argv and aggregate-after-resource-narrowing.argv, identical SHA256 233c35bca87e083eb18e88252e8975f249dd215a763557690e2039632c19865c - final-narrowed-launcher-module.log SHA256 1ca3692c56ca4704f736d5f8194df439074ec18a73c08a4a182e0ae66c8b92de - green-probe-port.log SHA256 45d9e14f365bfe829e33297ff37953bec7701cf8982ce9bbe09012edec82e660 These are local test/argv references, not tracked raw evidence or an installed production-image qualification. The original permissions and deployment limits above remain in force.