Transport/TLS successor of excluded #139: same-host container tier B, CA trust persistence, certificate lifecycle, origin migration #224
Labels
No labels
accessibility
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
P1
P2
P3
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Creatidy/scarcity-router#224
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Product owner: Scarcity Router; security-critical transport/TLS lane. Registered by the 2026-10-27 owner backlog disposition (D-083) as the active successor of excluded
wontfixissue #139. Preserve every still-required #139 obligation under an eligible active owner without reopening or relabeling the historical issue.Why and Evidence
2026-10-27 read-only reconciliation at
develop4a182affa4775a4a38b47860ad7622a099c56c4averified: D-056 client-transport tier B (same-host container plaintext transport) is documented but not implemented —docs/security.md"Client-transport tiers (D-056)" assigns implementation to excluded #139 whilegateway_server.py(build_gateway, refuses any non-loopback plaintext bind) andcontrol_server.py(same discipline) refuse it in code. Worker-service custom-CA trust configuration is deliberately absent (worker_service.pynotes the #139 assignment). Public-CA/ACME certificate acquisition/renewal and verify-then-commit worker origin migration are unevidenced in code. Tier A (loopback plaintext) and tier C (cross-host TLS-required) are implemented and must not regress.Scope
docs/security.mdtier B specifies. The exception must be an explicit deployment/local-transport mode, apply to the entire composed HTTP listener (never a per-surface plaintext/TLS mix), never a default or general non-loopback0.0.0.0plaintext bind, and fail closed when not explicitly selected. Prove host-local/non-routable deployment boundaries (dedicated orinternal: truenetwork, loopback-only publication) with negative tests that refuse plaintext reachable from LAN/WAN.--ca-cert <path>(or equivalent persisted worker-local trust configuration) consumed by pair/run/service operations and generated service units; no hand-writtenSSL_CERT_FILEenvironment hacks; validation before use.Acceptance Criteria
verify=false, no certificate-verification bypass, no trust-on-first-use, no silent HTTPS→HTTP fallback, no automatic system-trust-store mutation, authentication/authorization/CSRF/credential separation fully enforced in every tier.uv sync --only-dev,make check,uv run basedpyright,git diff --check;make package-checkwhen packaging/workflow affected), deterministic offline tests, redacted fixtures only, fresh independent technical+security review at exact frozen HEAD/base; security-critical classification.Constraints
No plaintext LAN/WAN exposure; no TLS, authorization, CSRF or credential-separation weakening. Any host-local HTTP exception applies to the whole composed listener and requires proven deployment-boundary enforcement. No new vendor control plane or domain dependency; no ZCode-side changes; no live provider calls. Security-critical: rigorous independent review by a sufficiently capable model under D-081.
Links
Excluded predecessor #139 (historical, unchanged); disposition decision D-083 in
docs/decisions.md;docs/security.mdclient-transport tiers; D-056, D-044; distribution lane #186 (independent, not a prerequisite either direction).Selected by authorized /loop2026-10-28 after FULLfresh14-issuequeue/exact6wontfix exclusions and source-backed177producer refresh(comment19692):177 fullconsumer remains genuinely producer-contract-gated (new installedusagefacts acknowledged; no52blanketgate),183 exposuresecurityprerequisite explicit,186 independentGHCR+installedlifecycle units integrated with externalplatform/publication gates stillopen;199retirement and214liveauthority notreactivated. Among remaining eligible unranked same-repo issues,224 precedes226 by registration and has NO nativeprerequisite. Clean freshlyfetched develop2002d348a8d6d5f3d1b742a93ba3adf944d4b24e.
Bounded first224unit (security-critical): Scope2 persisted+validated WORKER-LOCAL CA trust across pair/run/service using existing private WorkerLocalStore, with backward-compatible absent-config/defaultverifiedroots and no globaltrust/envhack. Current evidence worker_client.py:218–224 creates only platformdefaultSSLcontext; pair/run have noCAflag; runtime/defaultfactory shared by CLI/setup/tray. worker_service.py:91–93 records deliberate old139absence; existingservice unit points only at private state, never credentials. worker_setup localsettingsJSONv1 is strict: don't silently mutate its contract or duplicate configuration; prefer an additive explicitlyversioned bounded trustrecord in the already-generic store, origin-bound, with failures preserving old identity/settings and atomic successfulpairing persistence. Preserve customConnectFactory test seam and normal default modes. Validate before network/use/service writes; verifiedTLS/hostnamecheckingneveroff, noTOFU/plaintextfallback, no secret/PEM diagnostics, no credential/unit arguments, no systemtrust mutation. Optional privateCA is not certificate pinning or a new consumer role.
TierB whole-listener topology enforcement, ACME lifecycle and verify-before-commit originmigration remain separate required224scope, NOT silently claimed by this unit; none must block independentlysafeCAwork. No realprovider/accountstate, livecertificateissuance/serviceinstallation/DNS/deployment/release/signing. Synthetic offlineTLSfixtures/servicefakes only. Onebranch/PR/one mutator; expected small coherent runtime/store/CLI/service+focusedtests/docs delta, bounded120minexecution/recovery. Fullgates (+packagecheck for packagedworker), rigorous fresh independent security/correctness/UX review at exactHEAD/base, defaultmaximum10wholePRreviews for224 retainedacrossphases. No findings/approvalcount yet.
Execution recovery note2026-10-28T17:00Z (unit selected15:58Z, declared120min bound retained): GLM provider plan-limit error occurred AFTER substantial source/test work, before final worker report. Actual Git/nativeworker records were inspected; edits preserved, no blindrestart/rollback/uncertainwrite duplicated. Existing branch remains uncommitted, no PR/reviewinvocation yet. Nativeworker history shows redCLIflagproof, newCA tests and focused/typecheck passes; parent is independently re-observing gates rather than claiming a missing finalreport as proof.
Concrete pre-gate implementation issues found during primary acceptance inspection: PEMbase64 conversion alone does not validate X509, separate stat/read/load can violate the claimed single validated trust input; stale trust can outlive a paired-origin change; plaintext --ca-cert and packagedrun handling need fail-closed/coherent behavior. These are material TLS/origin/persistence-boundary questions, not routine admin/testformatting. Approved lower-cost GLM capacity is unavailable. Recover using the owner-permitted documented Luna Max (GPT-5.6Luna/max via OpenAI) ONLY for bounded completion of this security-critical unit and its later fresh independent review; no silent substitution, GPT-6Sol, paidgatewayfallback, globaltrust change or new authority. Existing implementationcontext may be resumed for implementation, NEVER transferred to the fresh independent reviewer. Modelprovider/resourcechange is diagnosed; remaining budget/scope/required fullgates/reviewunchanged. Other224lanes remain open.
Owner-directed development stop — 2026-10-28. Further development is paused because other significant changes are necessary. This issue remains OPEN; no remaining #224 lane is treated as complete. The bounded worker-local CA trust implementation is preserved on branch
issue-224-worker-ca-trust, commit30ad84a95184b085974476f4ec5c4295e574f332, in open PR #233. Validation observed: 3184 tests OK/18 skips, basedpyright 0/0/0, package-check passed. This is not merge acceptance.PR #233's first review invocation was completed using GPT-5.6 Luna and returned REQUEST_CHANGES (2 P1, 2 P2); those findings remain actionable and unresolved. The owner rejected that review-model choice for this security-critical change; no Sol 6.1 replacement review was dispatched or completed before this stop. Therefore PR #233 remains unmerged and must not be represented as approved. The implementation covers only worker-local CA trust; D-056 tier-B whole-listener transport, certificate lifecycle and safe origin migration remain outstanding. No further code, review, merge, release or deployment is authorized by this status note.
Scoped CA-trust delivery remains open as PR #233 at
5d2aa7258905743368953e74d9fbee7c6d2dc3ec, current base516c155963c3cd06cb9c3dd74323fe4ddaf1b6ed. Independent native review #6 APPROVE with no findings at these exact refs; local full feature and exact prospective-merge gates passed. Required current-head Forgejo CI #3360 failed after 6 seconds; MCP jobs/artifacts endpoints return 404 and the browser run view requires authentication, so the cause is unverified and the CI gate is not waived. No merge has occurred. Live Windows validation is also not claimed. The remaining issue scope still includes tier B transport, certificate acquisition/renewal and verified origin migration; none was implemented or closed by this delivery.Scoped CA-trust PR #233 integrated into
developasf141a6998fb0b9588d4908bc22c286586d1efc1a. Its parents are reviewed base516c155963c3cd06cb9c3dd74323fe4ddaf1b6edand approved HEAD5d2aa7258905743368953e74d9fbee7c6d2dc3ec; integrated tree461ba9de7aa0a2ecf1f930e0488f61b4bfd56432exactly matches the independently reviewed and locally validated prospective tree. Fresh Forgejo Actions run #3360 / UI #313 completed successfully for the exact HEAD after owner infrastructure correction. The latestci / check (pull_request)context is success; the MCP status resource reports aggregate failure while retaining older same-context failures, a discrepancy documented on PR #233. The merge was the normal Forgejo merge with no force or bypass.Independent native review #6 APPROVE with no findings remains unchanged (session
ses_e76de085dffeu0ZEGKsLl8ZmjV, GPT-6.1 Sol/openai/high dispatch; backend runtime identity unobserved). A clean credential-free anonymousuv sync --only-devverified the exact locked MI revision. Local full and package checks are recorded on the PR. Live Windows / packaged-executable acceptance remains unverified; earlier intermittent ZCode plan-lane failure root cause remains unverified. This issue stays OPEN for tier B transport, certificate acquisition/renewal and verified origin migration. No release or deployment.2026-10-30 delivery checkpoint: scoped origin-credential containment is present but UNCOMMITTED in the designated checkout on branch
issue-224-origin-bound-worker, based onf141a6998fb0b9588d4908bc22c286586d1efc1a. It refuses worker runtime connection to an origin different from the stored paired identity before credential disclosure; it is not verified origin migration and does not complete #224. Focused worker/CA/TLS tests: 143 passed. Final-sourcemake check: 3,181 passed, 18 skipped, basedpyright 0/0;uv sync --only-dev, package check and whitespace check passed. No live Windows or network acceptance is claimed.Delivery is stopped before commit:
git config --get user.nameresolves from the global config to a value with literal surrounding apostrophes rather than the requiredAdrian Tkacz; effectivegit varoutput is sanitized, but repository policy requires both configured and effective identity to match and prohibits silently changing Git configuration. No commit, push, PR, new reviewer invocation or integration occurred; existing review #1–6 history remains unchanged. The global Git identity requires correction before delivery can resume. The remaining independently executable tier-B and certificate-lifecycle implementation is not satisfied or gated by #227; preserve the current uncommitted work rather than replacing it. No deployment or release occurred.Owner-corrected Git identity verified; preserved containment changes committed as
ce7be1b1241c24f4a785d6c7e8a928231a091b8eand submitted as PR #236 againstf141a6998fb0b9588d4908bc22c286586d1efc1a. Review #7/10 has been reserved on the PR and dispatched to fresh native sessionses_e74174032ffeunZ7bEpmZkBCh4using GPT-6.1 Sol/openai/high; runtime backend identity remains unobserved. Forgejo run #3376 is running. No review verdict, CI acceptance, merge, verified migration or other remaining #224 scope is claimed.PR #236 origin-mismatch containment and clean-runner fixture repair integrated by normal Forgejo merge
98ae0e4e6cbeac66d098c194aa914fafb57a1460. Parents are approved basef141a6998fb0b9588d4908bc22c286586d1efc1aand approved HEAD4b903874da53dc6ba06740b70d5aedb55054f252; integrated treedc9c8ff299ca563fd2de2825b872037e2a3cb91amatches reviewed HEAD. Independent review #8 APPROVE with no findings (GPT-6.1 Sol/openai/high dispatch, native sessionses_e73e588c7ffeMVlkB9BVh3wQzy, backend identity unobserved) and Forgejo CI run #3379 passed on exact HEAD. Full fixed-seed local gate 3181 passed/18 skipped; an earlier intermittent fake-feeder failure remains recorded, root cause not independently established. No live Windows/network acceptance. This is NOT verified origin migration: issue remains OPEN for tier B, certificate lifecycle and migration; #224 review invocations #1–8 remain consumed.Certificate replacement PR #237 opened at HEAD
ea4328f5b9c75c07cdd232aa7c26bf9b5e8bbcddagainst base98ae0e4e6cbeac66d098c194aa914fafb57a1460. Review #9/10 reserved and dispatched to fresh native sessionses_e73adc43bffedY1bBiYxEQP114(GPT-6.1 Sol/openai/high requested; runtime backend identity unobserved); CI #3383 running. Local fixed-seed full gate passed 3,186 tests/18 skipped, basedpyright and package-check passed; no deployed certificate issuance or renewal is claimed. Tier B and verified origin migration remain open.PR #237 verified certificate reload integrated by normal Forgejo merge
209f7d39f3ecebbd1b98b11d7c44c63192fe50a4. Parents match reviewed base98ae0e4e6cbeac66d098c194aa914fafb57a1460and reviewed HEAD89f39161e42d6a788edf3a3d6d85ba880005777a; integrated treebf579838da6651b46df77df6e99f43199d893db0matches approved HEAD. Review #10/10 APPROVE with no findings, fresh nativepr-reviewersessionses_e7398c2d0ffe3Y6ynokXoxzdKK, GPT-6.1 Sol/openai/high requested, runtime backend identity unobserved. Forgejo CI #3384 passed on exact HEAD; local fixed-seed full gate 3,186 tests passed/18 skipped, basedpyright and package-check passed. No live Windows/network, deployed Certbot hook or public certificate acceptance is claimed.#224 remains OPEN: tier B host-local plaintext boundary, authenticated verified origin migration and any live/operator certificate acceptance remain unmet. #227 is downstream acceptance, not an implementation prerequisite. All #224 whole-PR review ordinals #1–10 are consumed; #9 requested changes and #10 approved its remediation at the exact recorded refs. The default D-069/D-069A ceiling provides no review capacity for another #224 patch or new PR, and no verified greater finite exception has been identified. STOP: do not start an unreviewable patch, invent #11, transfer approval, or close the issue. An explicit owner-controlled disposition is necessary before additional consequential #224 implementation can receive its required fresh independent review; any exception must meet the existing exact canonical issue/linked-PR, direct-owner-source and integrated-policy requirements, or the owner may choose another policy-consistent authorized delivery path.
Tier-B bounded investigation, 2026-10-30: current canonical
developis209f7d39f3ecebbd1b98b11d7c44c63192fe50a4; issue remains open with no native dependencies. The owner's direct current Kilo instruction authorizes at most #11 and #12 for one future specific Tier-B PR, but no PR exists, no exceptional ordinal was reserved or dispatched, and no Kilo transcription is treated as owner authority.Evidence:
control_server.py:221-222andgateway_server.py:1082-1085independently refuse non-loopback plaintext; the current Dockerfile uses a non-root process with no Docker socket or privileged network management. On Docker Desktop 29.9.2 / WSL2, an isolated test container on aninternalbridge with host publication127.0.0.1:18973:80was reachable from loopback and a peer on that bridge. Attaching that running container to a second temporary non-internal bridge immediately made its wildcard listener reachable from a peer on the new bridge while the original loopback port mapping stayed unchanged. All temporary containers/networks were removed. This demonstrates topology mutation, not LAN reachability or production acceptance. Docker's official port-publishing documentation states that host daemon direct-routing and network gateway options can expose a published container IP even when host publication names loopback: https://docs.docker.com/engine/network/port-publishing/ .Exact unresolved security-boundary decision: identify an owner-authorized, trustworthy host-side enforcement/attestation mechanism that establishes the effective published-port, network, daemon-routing and firewall boundary continuously, including later topology changes, without granting the Router container Docker control or weakening host security. An in-container opt-in flag/label,
internalnetwork, startup-only inspection or binding one container IP does not establish the host-side boundary; an isolated Docker smoke test and static Compose configuration do not enforce future changes. A socket shared through the host network remains existing tier A, not the required bridge-published tier B; a Unix socket alone changes the client interface and does not provide the required loopback HTTP publication. Host firewall/network-admin capabilities, a Docker-socket watcher/supervisor or a new forwarding proxy would introduce a security authority or infrastructure boundary not authorized by the current constraints, and startup-only checks have a time-of-check/time-of-use gap. No safe equivalent has been established within current authority. Owner disposition of that missing trust/enforcement mechanism or an explicitly revised supported topology is needed; absent it, fail closed and retain existing TLS for non-loopback binds. No implementation branch, PR, review, release, or deployment was created.Localhost UX investigation, 2026-10-30: inspected
develop209f7d39f3. No architecture decision, review invocation, production change, commit or PR. Local investigation branchissue-224-localhost-investigationcontains only uncommittedexamples/docker-compose.ymlbuild-context correctionbuild: .->build: ...docker compose configresolves the corrected context to repository root; current image built successfully, and installed worker_ca_trust.py, worker_client.py, control_server.py and tls_reload.py SHA-256 matched checkout.Environment: Engine 29.9.2, Docker Desktop 4.97.0 (244584), Compose 5.6.1, Docker context default /var/run/docker.sock backed by Desktop WSL engine; WSL 3.0.3, kernel 6.18.54.1, Windows 10.0.26300.9711. Desktop
HostNetworkingEnabled=False; WSL config has no networkingMode/localhostForwarding/firewall/dnsTunneling overrides. Windows firewall profiles enabled; Desktop backend has private allow and public block rules, WSL rule exists; portproxy lists no rule for 8787. These observations do not prove effective external isolation. Docker docs require opting into Desktop host networking and applying/restarting; that persistent change was not made.Temporary current image, loopback 127.0.0.1:8787,
--network host, tmpfs state: container started and became healthy. Another host-network container got /healthz 200 over 127.0.0.1, including after container restart. Same peer using http://localhost:8787/admin got 400 invalid_host: current listener requires Host matching bound 127.0.0.1. WSL 127.0.0.1 and localhost, Windows 127.0.0.1 and localhost, and bridge-container 127.0.0.1 and host.docker.internal all failed TCP; no HTTP response. Host-network driver being accepted by engine despite disabled Desktop forwarding does not prove the Desktop feature enabled. No actual separate LAN host was tested, no claim of LAN isolation. Desktop restart and persistence of real volume/configuration untested.Actual requests from host-network peer: administrator bootstrap 200; /admin/clients 200; client key issuance 200; authenticated /v1/models 200; anonymous /v1/models 401; client bearer on /control/state 401; admin cookie on /v1/models 401. No credentials recorded. Authenticated /v1/chat/completions on empty deployment returned 404 model_not_found, not successful inference. Existing synthetic local Ollama execution test
tests.test_e2e_execution.ServerDirectEndToEndTests.test_scenario_07_ollama_preset_direct_requires_no_credentialpassed in local process with test-injected observation, not in Docker and not Windows/WSL end-to-end. Exact missing acceptance: enable Desktop host networking with owner authorization and retest actual Windows/WSL connection, hostname guard, authentication and synthetic execution; configure a suitable supported local resource/observation without private credentials or fabricated readiness. Temporary container, tmpfs credentials and image removed; issue remains open.Follow-up: owner explicitly declined Docker Desktop setting changes or engine restart. Host networking enabled remains an optional UNVERIFIED variant, not a prerequisite imposed by this investigation.
As a separate supported, non-container alternative, ran current source directly in WSL at 127.0.0.1:18788 using temporary data and synthetic credentials. WSL and Windows each reached /healthz via 127.0.0.1 with HTTP 200, demonstrating Windows-to-WSL localhost forwarding in this environment. Both
http://localhost:18788/healthzrequests received HTTP 400 invalid_host because the listener is bound to 127.0.0.1 and validates Host exactly. A Docker bridge client targeting host.docker.internal:18788 established TCP and received HTTP 400; do not claim bridge or external network isolation from that HTTP rejection.On the native WSL listener: admin bootstrap 200, admin clients page 200, client issuance 200, authenticated /v1/models 200; anonymous /v1/models 401, inference key on admin state 401, admin session on inference 401. Authenticated generation on empty configuration returned 404 model_not_found: no native or Windows authenticated execution through a configured local resource was verified. The previous synthetic execution was a separate test harness, not installation acceptance. Temporary server stopped and its data removed. No Docker Desktop restart, global setting change, architecture decision or review.
Current owner triage, 2026-11-01: P2. Worker CA trust #233, origin credential containment #236 and certificate reload #237 are integrated; containment is not verified origin migration and reload is not certificate acquisition/renewal or live acceptance. D-085 is prospective and recommends verified TLS for bridge deployments; it does not formally retire accepted plaintext Tier B. Adrian must explicitly decide Tier-B retirement/amendment or an authorized enforceable topology; certificate lifecycle, authenticated verify-then-commit origin migration and applicable platform/operator acceptance remain open under Router ownership. Earliest independent activity is bounded read-only architecture/evidence disposition, not an unreviewable patch. All review ordinals #1–10 remain consumed; preserve the narrow future-specific Tier-B #11/#12 owner instruction and its exact D-069A authority/linked-PR verification conditions, with no automatic reservation, transfer or extension to other work. Further consequential implementation requires a policy-consistent owner disposition and fresh review capacity. No review, resumed development, closure, release or deployment is authorized.