Uh oh!
There was an error while loading. Please reload this page.
release-train: develop -> staging - #589
Conversation
#552) (#570) requests-proxy hardcoded `imagePullPolicy: Always` while its image line already read `images.requestsProxy.digest` — so a pinned digest was ignored for the pull policy and every restart re-pulled the image even when it was already cached. Make it digest-aware, matching jobs-manager / pods-monitor / resource-monitor: digest set -> repo@digest + IfNotPresent (restart-safe offline) digest empty -> repo:tag + Always (unchanged default) +2 helm-unittest cases (default -> Always; digest -> repo@digest + IfNotPresent). Chart 1.9.11 -> 1.9.12 (chart-content change requires a version bump). Scope: this is the narrow, unambiguous part of #552. The broader control-plane offline-restart update-model change (jobs-manager/pods-monitor rely on Always for the image-refresh CronJob; resource-monitor too) is a deliberate design decision tracked in #569. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…end#1497) (#580) Two unbounded external calls (Bugbot on the client#571 prod promotion) that can hang a CI job to the GitHub Actions cap with no useful failure — same class as the image-refresh CronJob fix (#572). - scripts/tests/e2e-seal-check.sh: add --request-timeout=10s to the point-in-time kubectl API calls (get/run/logs/delete/describe) so a wedged API server fails the seal-check fast. `kubectl wait` (L57) is deliberately left as-is: it is already bounded by --timeout=180s, and a --request-timeout on its underlying watch would truncate it and risk flakes. - .github/workflows/helm-ci.yaml: add --connect-timeout 15 --max-time 120 to the pinned kubeconform download so a stalled endpoint fails the template matrix instead of hanging. Retries/-f behaviour unchanged. Values mirror the repo's existing bounds (--request-timeout=5s/10s elsewhere; --connect-timeout/--max-time in install.sh / setup-linux.sh). Neither file is in the R8 signed manifest (test script + workflow), so no manifest bump. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…utput (#576) (#579) * fix(installer): stop leaking user PII + tracebloc internals in logs/output (#576) Root-caused from a client's shared install log, which exposed both her identity (Username/RunAs/Machine — the PowerShell transcript header) and our internals (the `& $cosign @cosignArgs` source line + internal codes) when cosign errored. Main installer (install-k8s.ps1): - Drop Start-Transcript entirely — its fixed header IS the PII, and it also captured PowerShell's raw error rendering (source lines, internal identifiers) into the log. The shareable install-*.log is now written only via the curated Log() writer, with a PII-free header. - Route the message helpers (Info/Ok/Warn/Err/Step/PromptHeader/Hint) through Log() so the log stays useful without the transcript — it mirrors the curated on-screen output: no user PII, no tracebloc internals. Drop the Stop-Transcript calls. Bootstrap (install.ps1): - Capture cosign's output (2>&1 | Out-Null under EAP=Continue) instead of letting a native-stderr NativeCommandError dump THIS script's source line + internal identifiers to the console / any user transcript. Sanitize the verification- failure messages to plain language (no RFC-0001 R8 / manifest.sha256 / $_). Bash (common.sh): drop the username from the HOST_DATASET_DIR "not writable" error (keep the uid number). Tests: +2 Pester (main: no transcript; helpers feed the curated log) and +3 Pester (bootstrap: cosign output captured, messages carry no internal codes, still fails closed). Both suites green (418/0/9). Manifest regenerated. Scope: the top-level error boundary that stops PowerShell rendering ANY unhandled throw raw is #577; a broader sweep of internal identifiers out of all remaining messages continues under #576. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): route preflight + summary failures to the curated log (Bugbot #579) Removing Start-Transcript (for #576) left Write-PfFail and a few summary failure headlines screen-only, so a forwarded install-*.log no longer showed the actual failing preflight checks (disk/virt/storage/connectivity/memory) — only the generic Err summary + hints. Route Write-PfFail and the bad_creds / image_pull_ca / diagnostics-archive failure headlines through Log(). +1 Pester (Write-PfFail reaches the log). Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): log the classified final state for every summary branch (Bugbot #579) The default Print-Summary branch (image_pull / crash / other non-ready) still printed its failure headline via Write-Host only, so those outcomes missed the curated log after the Start-Transcript removal — while bad_creds / image_pull_ca were routed. Add a central `Log "Final client state: <state>"` before the switch so EVERY branch is covered, and route the default headline too. +1 Pester (Print-Summary records the final state). Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(bootstrap): sanitize the bash cosign-failure message too (#576 review parity) Reviewer (saadqbal) on #579: install.ps1's cosign message was sanitized but the bash bootstrap still printed 'cosign signature verification FAILED for manifest.sha256 — refusing to install', leaking the same internals. Match the PowerShell wording: 'Couldn't confirm the installer download is authentic, so the install stopped before changing anything on your machine.' Same for the success line ('Download verified as published by tracebloc'). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bootstrap): expect the sanitized cosign-failure message (#576 review) install.sh's cosign-failure message was sanitized in 2aa35db (reviewer parity), so install-bootstrap.bats's 'cosign signature failure aborts' test — which pinned the old 'signature verification FAILED' string — must expect the new plain wording. Behaviour coverage (aborts + never degrades to a same-channel sha256) is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…rd (#586) (#587) House-style alignment (from the #576 review): the product name is lowercase `tracebloc` always, and the installers must feel one-to-one across platforms (bash is the gold standard). PowerShell had capital-T "Tracebloc" in two user-facing lines while the rest of the copy is lowercase. - install.ps1: "Downloading Tracebloc client installer" / "Running Tracebloc environment setup" -> lowercase `tracebloc`. - check-style.sh: new guard fails on capital-T `Tracebloc` in user-facing text so the casing can't drift again (same spirit as the #435 single-source facts guard). Exempts comments + PascalCase identifiers (Get-Tracebloc… , the TraceblocInstallerResume resume key); honours `# style-guard: allow`. Verified: check-style.sh clean; the guard flags a real "Tracebloc client" line and excludes identifiers/comments; shellcheck + PS parse clean. Closes#586. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Aug 4, 2026
bugbot run |
Uh oh!
There was an error while loading. Please reload this page.
Set-Content/Add-Content default to PS 5.1's ANSI encoding, corrupting non-ASCII host paths/messages in the -Diagnose log; every other writer in this file already pins -Encoding UTF8. (Bugbot on the staging promotion, backend#1497 sibling.)
…th a raw stack (#577) (#588) * fix(installer): top-level error boundary so PowerShell never crashes with a stack (#577) The main installer (install-k8s.ps1) had NO top-level try/catch, so any unhandled throw (or PS runtime error) rendered PowerShell's raw source line + stack and terminated the session — exactly Anubha's screen. Wrap the whole main run (inside the TB_PESTER guard) in a top-level try/catch that routes any crash through a new Show-FatalError: one clean "Installation stopped" line + the reason (the exception MESSAGE, curated at the throw sites per #576 — never the stack) + the log location + a safe-to-re-run hint, then exit 1. Intentional exits (fast-path, Err, final) pass straight through — verified exit-in-try is not caught while throw-in-try is. Stack traces are never shown OR logged (no internals). Bootstrap (install.ps1) already had a top-level try/catch; enhance its message to the same clean "Installation stopped … safe to re-run" shape. +3 Pester (main wrapped in try/catch -> Show-FatalError; clean render with reason + re-run hint and no stack/source; reason logged, stack never). Manifest regenerated. Built on #576 (needs its no-transcript / curated Log world); PR opens once #576 lands so it can target a clean develop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): guaranteed finally + trap for the PS error boundary (#577) Completes the PowerShell side of #577 to Lukas's acceptance. The top-level boundary now has a guaranteed `finally` + a last-resort `trap`, mirroring bash's exit-code-guarded install_cleanup: - $script:OutcomeReported is set on every terminal path (normal finish, Err, caught crash via Show-FatalError, fast-path, help/diagnose). - The finally shows a clean "interrupted" line (Show-Interrupted: log + re-run, no stack) ONLY when nothing reported an outcome — i.e. Ctrl-C / abnormal termination — so the window never just vanishes. - The trap catches anything that terminates OUTSIDE the try (defined inside the TB_PESTER guard so it never fires under the test dot-source). Verified: reported exits stay quiet, crashes route through Show-FatalError, an unreported exit fires Show-Interrupted; exit codes preserved. +3 Pester. Manifest regenerated. Bash symmetry (capture a failing tool's raw stderr -> curated line before the closer) is next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): bash graceful failure — capture direct native-call stderr (#577) Completes #577's bash symmetry. The big steps already curate (spin_cmd_bounded captures tool output to the log + shows a clean ✖ line) and install_cleanup is a clean conditional closer; the residual raw-stderr-before-the-closer leaks were a few DIRECT native calls under `set -euo pipefail`: - cluster.sh: `k3d cluster start` (reuse path) now redirects to the log + surfaces a curated error() on failure. - gpu-plugins.sh: `kubectl apply` (device-plugin manifest) and `kubectl rollout status` now redirect to the log, so only the caller's curated error/warn shows. A failing tool now surfaces our plain-language line, not its raw stderr, before the closer — bash graceful *failure*, not just a graceful closer. Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): GPU device-plugin failure is recoverable, not fatal (#577) Per #577's fatal-vs-recoverable acceptance (optional steps warn + continue): a GPU device-plugin download/apply failure was fatal on BOTH platforms — gpu-plugins.sh `error "Failed to enable GPU acceleration"` and install-k8s.ps1 `Err "Failed to enable GPU acceleration"` both exit — so a GPU hiccup aborted the whole install instead of falling back to CPU mode (which the client fully supports). Now both warn + continue in CPU mode: - bash: `_apply_remote_manifest` failure -> warn + return 0. - PS: wrap the download/apply in a catch so a failure can't reach the top-level boundary; warn + continue; also capture `kubectl apply` raw stderr (#577). Mirrors the NVIDIA-container-toolkit timeout, which already warns and carries on. +1 Pester. Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): gate GPU success message on kubectl exit code (#577) Bugbot (High): the GPU device-plugin apply/rollout discarded output into $null and never checked $LASTEXITCODE. Because a native kubectl non-zero exit does not throw, a failed apply fell through to Ok "GPU acceleration enabled." - a false success the operator would trust, and (unlike bash) the failure was neither warned nor logged. Capture each kubectl call's output to the install log and gate the success message on $LASTEXITCODE; on any non-zero exit, warn + continue in CPU mode (mirrors the bash gpu-plugins.sh path). Adds a regression test asserting the success message is exit-code-gated and the false-success $null-discard pattern is gone. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): reboot-pending stop marks outcome reported (#577) Bugbot (Medium): the reboot-pending path prints reboot/resume guidance and exits 2, but never set $script:OutcomeReported. The new top-level finally then treated that intentional stop as an interruption and appended Show-Interrupted, so on a common Step 1 path the operator saw a contradictory second outcome. Set $script:OutcomeReported before the reboot block's exits (covers both exit 2 paths and the Restart-Computer path), so the finally leaves the clean reboot guidance as the sole outcome. Adds a regression test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): bound k3d start + GPU apply so log-redirected calls can't hang (#577) Bugbot flagged two hang risks introduced by the #577 log redirects: piping a call's output to the log hides console progress, so an unbounded call now hangs silently instead of failing into the new curated error/warn paths. - cluster.sh: `k3d cluster start` waits for the server with no deadline by default; add `--wait --timeout 5m` (parity with the Windows installer's 5-minute start deadline) so a wedged Docker fails into the curated error instead of hanging. - gpu-plugins.sh: the shared `_apply_remote_manifest` (nvidia + amd) now bounds `kubectl apply` with `--request-timeout=30s`, mirroring the node-probe in the same file, so a wedged API server falls through to the recoverable CPU-mode warn. - install-k8s.ps1: same `--request-timeout=30s` on the PS GPU apply for parity (the PS `k3d cluster start` is already bounded by Wait-ProcessWithDeadline). Adds regression tests: cluster start is --timeout-bounded (bats), the GPU apply carries --request-timeout (bats + Pester). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): gate bash GPU success on rollout + fix -Diagnose interrupt gap (#577) Bugbot round 4: - gpu-plugins.sh (Medium): after a non-zero `kubectl rollout status`, bash still printed success "GPU acceleration enabled." while the failure went only to the log - the false-success bug already fixed on the PS side, still present in bash. Gate the success on the rollout exit code (nvidia AND amd paths); on failure warn + continue in CPU mode, matching the PS peer. - install-k8s.ps1 (Low): $script:OutcomeReported was set to $true BEFORE the long Invoke-DiagnoseBundle ran, so an interrupt mid-collection skipped Show-Interrupted - the silent death the boundary exists to prevent. Set the flag AFTER the bundle completes. Adds regression tests: nvidia success is rollout-gated (bats); the -Diagnose flag is set only after the bundle (Pester). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): skip GPU verify when the plugin deploy failed / CPU-mode (#577) Bugbot round 5 (Medium): making the GPU device-plugin step recoverable (#577) means a failed apply/download now continues the install - but the caller still ran the GPU verify step unconditionally. Operators saw "continuing in CPU mode", then waited ~90s and got a contradictory "still initializing" warning for a plugin never deployed. Have the deploy signal whether the plugin was actually deployed, and gate verify on it: - gpu-plugins.sh: _deploy_nvidia_plugin / _deploy_amd_plugin return non-zero on every CPU-mode path (apply failure, unconfirmed rollout, master-fallback failure); 0 when deployed/already-present. - install-k8s.sh: `if deploy_gpu_device_plugin; then verify_gpu; fi` (the `if` also keeps a non-zero deploy from tripping set -e). - install-k8s.ps1: Install-GpuDevicePlugin returns $true/$false (Invoke-WithRetry sunk to $null to avoid return-value pollution); caller runs Confirm-GpuNode only on $true. Adds regression tests: verify is gated (bats + Pester), and a functional bats test that _deploy_nvidia_plugin returns non-zero on a CPU-mode path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): close the GPU "can't hang" parity + gate the amd master fallback (#577) Review follow-ups (saadqbal) on the GPU path: - Bound the last unbounded kubectl probes so a wedged API server can't hang before the bounded apply is reached: the nvidia/amd existence checks (bash + PS) and PS Confirm-GpuNode's node probe now carry --request-timeout=5s, matching bash's verify_gpu. Closes the "can't hang" goal symmetrically. - Gate the amd master fallback on rollout like the primary paths: a master apply that never rolls out now warns + continues in CPU mode instead of returning a false success that made the caller's verify poll ~90s. - Extract the shared _gpu_rollout_gate helper (nvidia, amd-primary, amd-master) so the "no false enabled / no dead verify wait" behaviour is identical everywhere and not duplicated three times. Tests: adds _gpu_rollout_gate functional tests (rollout fail -> warn+non-zero; ok -> success+0), asserts the existence probes are --request-timeout-bounded, that both amd paths gate on rollout, and that the PS probes carry --request-timeout. Updates the in-branch nvidia-gating test to the refactored (helper-delegated) form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Resolves the install-k8s.ps1 + manifest.sha256 conflict from #588 (graceful error boundary). Re-applies the two -Encoding UTF8 edits to the log writers on top of develop and regenerates the R8 manifest hash.
…ead (#582) (#590) * feat(installer): preflight network profile — proxy + TLS-inspection read (#582) Child 1/4 of #578. On a restricted/corporate network the installer dove straight into the long work and only failed minutes in, with no up-front sense of what the network allows. Add a fast, bounded, non-fatal network probe that runs BEFORE the endpoint checks and prints a plain-language "network profile" line: - Explicit proxy detected from the environment (HTTPS preferred), announced as a bare host:port with any user:pass credentials stripped (PII-free, #576). - A configured corporate CA bundle (TRACEBLOC_CA_BUNDLE / CURL_CA_BUNDLE) announced. - TLS inspection detected affirmatively (best-effort): read the issuer of the cert served for a well-known public host (through the proxy when set); a non-public issuer means a corporate CA is re-signing TLS. Bounded and non-hanging — bash needs openssl + a timeout tool (else "unknown"); PowerShell uses .NET with an 8s timeout and a scoped, restored cert-validation callback. A plain direct connection stays silent (the reachability lines already confirm egress). The existing break-and-inspect hint keeps owning the actionable CA fix. Cross-platform with one-to-one copy (preflight.sh _pf_network_* / install-k8s.ps1 Show-NetworkProfile). preflight.sh + install-k8s.ps1 are manifested; manifest regenerated. Tests: 9 bats + 7 Pester covering credential stripping, proxy precedence, issuer classification, the silent-direct path, and the noteworthy line. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): TLS-inspection probe must connect through an authenticated proxy (#582) Bugbot (Medium): the network profile stripped proxy credentials for DISPLAY (correct, PII-safe) but reused that stripped host:port for the probe's own CONNECTION. On an authenticated corporate proxy the HEAD/CONNECT then 407s, issuer capture fails, and the profile returns "unknown" — so inspection is never reported on the exact TLS-inspecting networks the probe exists to detect. Connect with the real credentials; keep display stripped: - preflight.sh: add _pf_env_proxy_raw (verbatim env value). _pf_detect_tls_inspection passes -proxy host:port plus -proxy_user/-proxy_pass (openssl >= 3.0) when the proxy carries credentials. _pf_env_proxy / the profile line stay credential-stripped. - install-k8s.ps1: add Get-EnvProxyRaw. Get-TlsInspectionState builds the WebProxy from the raw URL and sets WebProxy.Credentials (NetworkCredential) when UserInfo is present; Show-NetworkProfile still uses the stripped Get-EnvProxy for the printed line. Credentials reach openssl / the WebProxy only — never printed or logged. Tests: bash + Pester assert the raw helper preserves creds while display strips, that the openssl CONNECT carries -proxy_user on an auth proxy (with the password absent from the result), and that the probe uses the credentialed proxy while the display path does not. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): harden the bash TLS-inspection auth-proxy path (#582) Four Bugbot follow-ups on the bash credential-passing added last commit: - [High] Password no longer sits in openssl argv (visible via ps / /proc/*/cmdline): pass it via env: — openssl reads $_TB_PROXY_PASS, exported ONLY inside the probe's command-substitution subshell, so it never reaches argv or the parent shell. - [Med] The issuer pipeline is guarded with `|| issuer=""`, so a failed/timed-out probe returns "unknown" instead of aborting _pf_detect_tls_inspection under `set -euo pipefail` (mirrors _pf_probe_url). The bats setup now stubs the probe by default (like _pf_probe_url) so connectivity tests never hit the real github.com; the real-probe tests source preflight.sh fresh in a subshell. - [Med] Username-only proxies (http://user@host, no password) no longer reuse the username as the password — split on ':' only when present. - [Med] Proxy credentials are URL-decoded (_pf_urldecode) before use, matching the PowerShell peer's Uri.UnescapeDataString, so %-encoded secrets authenticate the same on Linux and Windows. Tests: url-decode parity, env:-not-argv (password absent from openssl argv), username-only-not-reused, and the openssl-absent "unknown" guard — all sourcing the real probe in a hermetic subshell. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Re-resolves the recurring install-k8s.ps1 + manifest conflict; re-applies the two -Encoding UTF8 log-writer edits on develop's tip and regenerates the R8 manifest.
…591) Set-Content -Encoding UTF8 prepends a BOM on PowerShell 5.1, so the log started with EF BB BF. Use the file's own no-BOM writer ([System.IO.File]::WriteAllText with UTF8Encoding($false)); the Add-Content append path was already BOM-free. Regenerates the R8 manifest hash.
…s (Bugbot, #591) Start-InstallLog now writes the curated install log as UTF-8 without a BOM, but Edit-Redaction -- which -Diagnose runs over every collected file before zipping, including the copied install-*.log -- still read via `Get-Content -Raw` with no encoding. On Windows PowerShell 5.1 a bare read decodes a BOM-less file as ANSI, so it mangled every non-ASCII host path/message back into mojibake in the bundle operators send: the exact corruption this PR set out to fix. Pin `-Encoding UTF8` on that read. It reads the BOM-less log correctly and still reads the Out-File -Encoding utf8 outputs (which carry a BOM on 5.1) fine -- the BOM is detected and stripped. Regenerated scripts/manifest.sha256 for the new install-k8s.ps1 hash. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Aug 4, 2026
bugbot run |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
fix(installer): pin -Encoding UTF8 on install-log writes
… curl (#583) (#592) * feat(installer): wire the corporate CA into cosign/helm/git, not just curl (#583) Child 2/4 of #578 — the single biggest lever for TLS-inspecting corporate networks. A break-and-inspect proxy re-signs HTTPS with a corporate root CA; tools that don't trust that root fail x509. curl already honored CURL_CA_BUNDLE and the k3d NODES got the CA at cluster-create (#424), but cosign, helm and git got nothing — the class behind both field failures (the k3d-checksum and the cosign/sigstore x509 failures). Extend the SAME resolved CA to every host tool that doesn't inherit the system store: - Bootstrap (install.sh / install.ps1): export SSL_CERT_FILE from TRACEBLOC_CA_BUNDLE / CURL_CA_BUNDLE before cosign runs, so keyless verification's HTTPS calls trust the corporate CA (cosign's Go client reads SSL_CERT_FILE). Not manifested (trust root). - Main installer: wire_ca_trust (bash) / Set-ToolTrust (PS) export SSL_CERT_FILE + GIT_SSL_CAINFO (+ CURL_CA_BUNDLE) from the resolved bundle, run BEFORE preflight's probes and any download, so helm, git and curl all trust it. Plain-language line: "Trusting your company's certificate for cosign, helm, git and downloads." No-op when unconfigured; fails fast on a set-but-unreadable bundle. When no CA is provided, tools fall back to the system store (which enterprise IT usually populates) — no user knowledge of CAs required in that common case. Tests: bats (wire_ca_trust exports/no-op/hard-fail; bootstrap cosign sees SSL_CERT_FILE via a recording mock) + Pester (Set-ToolTrust exports/no-op; bootstrap sets SSL_CERT_FILE). cluster.sh / install-k8s.* are manifested; manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): don't re-export CURL_CA_BUNDLE when wiring the corporate CA (#583) Bugbot (Medium): _bootstrap_wire_ca / wire_ca_trust / Set-ToolTrust exported CURL_CA_BUNDLE derived from the resolved bundle. But CURL_CA_BUNDLE is replace-not- augment, and TRACEBLOC_CA_BUNDLE is typically a corp-root-ONLY PEM (its documented k3d-node use), so re-exporting it could REPLACE curl's working trust with a bundle missing the public roots — breaking the manifest/sig fetches that were succeeding via the system store. The PowerShell bootstrap already set only SSL_CERT_FILE. curl already honors the user's own CURL_CA_BUNDLE natively, so we never re-export it. We only wire the tools that had NO corporate trust before: cosign/helm/Go (SSL_CERT_FILE) and git (GIT_SSL_CAINFO). This also makes the bash and PS bootstraps symmetric (both set only SSL_CERT_FILE). Adds a regression test asserting wire_ca_trust leaves a pre-set CURL_CA_BUNDLE intact while still exporting SSL_CERT_FILE for the other tools. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): SSL_CERT_FILE is Linux-only for Go; be honest on Win/mac + fail fast (#583) Two Bugbot follow-ups: - [High] SSL_CERT_FILE is inert for cosign/helm on Windows AND macOS. cosign/helm are Go; Go reads SSL_CERT_FILE only on Linux — on Windows it uses the certificate store and on macOS the Keychain, ignoring the env var. My comment wrongly claimed modern Go honors it on Windows. Corrected: * Linux: keep SSL_CERT_FILE (effective) + GIT_SSL_CAINFO; announce cosign/helm/git. * macOS (wire_ca_trust): still set the vars but announce only git + downloads, and hint that cosign/helm read the Keychain (add the CA there, or use the offline path). * Windows (Set-ToolTrust): set GIT_SSL_CAINFO (Git-for-Windows is OpenSSL-backed); do NOT set SSL_CERT_FILE (inert/misleading); hint cosign/helm read the cert store. * Windows bootstrap (install.ps1): drop the inert SSL_CERT_FILE set entirely. The robust cross-platform cosign fix for a PEM-only CA is the offline bundle (#584). - [Med] A set-but-unreadable CA bundle now fails fast with a clear "can't be read" message in both bootstraps, instead of silently no-opping and surfacing later as a generic cosign authenticity error. Tests updated for the platform-accurate behavior: Linux vs macOS announce, Windows sets only GIT_SSL_CAINFO (not SSL_CERT_FILE) + store hint, and the bootstrap fail-fast on a bad CA path (bash + PS). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): don't clobber a pre-set SSL_CERT_FILE / GIT_SSL_CAINFO either (#583) Bugbot (Medium): wire_ca_trust / Set-ToolTrust set GIT_SSL_CAINFO unconditionally from the resolved (corp-root-only) bundle. GIT_SSL_CAINFO is replace-not-augment (same OpenSSL contract as CURL_CA_BUNDLE), so a fuller pre-set git CA bundle got overwritten and host git HTTPS could x509-fail on non-intercepted endpoints. The same applies to SSL_CERT_FILE. Apply the consistent rule everywhere we wire trust: only set a trust var the user hasn't already set — never override their existing bundle. Covers SSL_CERT_FILE (bash bootstrap + wire_ca_trust) and GIT_SSL_CAINFO (wire_ca_trust + Set-ToolTrust); curl's CURL_CA_BUNDLE was already left untouched. Adds regression tests (bash + Pester) that a pre-set SSL_CERT_FILE / GIT_SSL_CAINFO survives while an unset one is still wired. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): don't over-claim download trust; check CA readability on Windows (#583) Two Bugbot follow-ups: - [Med] Set-ToolTrust printed "…and downloads" trust the corporate CA, but on Windows downloads use the certificate store (Invoke-WebRequest/Schannel) which this path never configures — only GIT_SSL_CAINFO. Green message, still-failing fetch. The announce now names only what's actually wired (git), and the store hint covers cosign, helm AND the installer's downloads. Same over-claim dropped on Linux/macOS: curl "downloads" trust the user's own CURL_CA_BUNDLE (which we deliberately don't touch), so Linux announces "cosign, helm and git" and macOS "git" only. - [Med] The Windows bootstrap CA fail-fast only tested existence (Test-Path -PathType Leaf); a present-but-unreadable file slipped through to a generic cosign error. It now also opens the file (mirrors bash -r and Resolve-CaBundle) and fails fast with a clear "can't be read" message. Tests updated: Linux/macOS announce wording (no "downloads"), and the Windows success line names only git while the store hint covers downloads. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#583): make the new CA-wiring assertions enforce The 20 assertions this PR adds to cluster.bats and install-bootstrap.bats were written multi-assertion without `|| return 1`, so under bats only the last command decided each test -- a regression in the cosign/helm/git CA wiring would have passed silently. Same hardening #527 applies suite-wide; appending it here keeps this PR green under #527's bats-hygiene gate whichever lands first. Both suites pass with enforcement on. The Pester additions need nothing: Should throws, so every assertion already enforces. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#583): on macOS, wire nothing — Keychain guidance instead (Bugbot ×2) Two Darwin holes, same root: exporting trust vars the platform ignores. - SSL_CERT_FILE: Go reads the Keychain on macOS, so the export helped neither cosign nor helm — while OpenSSL-backed curl DOES honor it, replace-not- augment, so a corp-root-only bundle shrank download trust for zero gain. Dropped from wire_ca_trust and platform-gated in _bootstrap_wire_ca (readability fail-fast still runs everywhere). - GIT_SSL_CAINFO: Apple's system git (SecureTransport) ignores it, and the clone that matters most — Homebrew's own bootstrap — runs system git. The "Trusting your company's certificate for git" claim was false on Darwin. Darwin now exports neither var and prints one honest hint: add the CA to the login Keychain so git, cosign and helm trust it. Same decision, same reason as Windows (store-based trust; no inert claims). Tests: Darwin announce updated, Darwin exports-nothing pinned at both layers, and the Linux bootstrap test now stubs uname so it doesn't flip on a macOS dev machine. Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#583): say only what was actually wired (Bugbot) wire_ca_trust and Set-ToolTrust printed the green "Trusting your company's certificate…" even when every only-if-unset guard skipped its export -- claiming wiring that did not happen, and masking a pre-set bundle that may still lack the corporate CA. Both now track wired vs kept per variable: the success names only what was actually exported, and anything kept gets an explicit "make sure that bundle includes your company's CA" hint instead. Pinned on both layers: both-kept claims nothing, partial pre-set claims only the wired half (bats), skipped export claims nothing (Pester). Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Lukas Wuttke <lukas@tracebloc.io>
LukasWodka
commented
Aug 4, 2026
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
3 issues from previous reviews remain unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 6d16824. Configure here.
…0) (#595) Pin every third-party (non-tracebloc, non-actions) action ref to the full 40-char commit SHA it currently resolves to, with a trailing exact-version comment (D10, RFC-BACKEND-1405). Behaviour-preserving: no version changes, only removal of silent tag mutation. Part of tracebloc/backend#1490. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
LukasWodka
commented
Aug 4, 2026
bugbot run |
Uh oh!
There was an error while loading. Please reload this page.
LukasWodka
commented
Aug 5, 2026
bugbot run |
Uh oh!
There was an error while loading. Please reload this page.
…ce (backend#1526) (#596) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…able (#525) * fix(installer): make the absent-key path in _extract_yaml_value reachable `_extract_yaml_value` piped into `grep`. On an ABSENT key grep exits 1; under `set -o pipefail` that rc propagates out of the pipeline and out of the assignment, so under `set -e` the function aborts at the assignment — making the very next line, `[[ -z "$line" ]] && return`, unreachable in exactly the shape it exists to handle. Latent, not live: all three call sites (lines 209, 651, 652) use the `$( )` command-substitution form, which suspends errexit for the function body. But the documented contract is "empty when the key is absent", so a bare call is the natural next refactor — and it would abort the install mid-step. Fix is the house idiom already used in assess.sh and common.sh `_chart_version`: `|| line=""` on the assignment. Catching any non-zero also keeps the path reachable if `head -1` ever SIGPIPEs grep (141), the sibling shape fixed in #522. Contract written down above the function. Verified (bash 3.2.57, GNU grep): - bare call, absent key, errexit live -> before: exit 1 (aborts, `return` never runs) · after: exit 0, empty output, execution continues - `v="$(_extract_yaml_value …)"`, absent key -> exit 0, "" (unchanged) - found-key, quoting, and unreadable-file paths unchanged Adds a bats case pinning the BARE-statement call under `set -euo pipefail`. Mutation-tested: it fails against the unfixed function, so it cannot rot into a no-op. Regenerated scripts/manifest.sha256 (R8 gate). Fixes#523 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ci: re-trigger — no workflow fired on the PR-open event (empty commit) Actions dispatched nothing for this PR: 0 runs on the branch 10 minutes after open, while a sibling PR opened 3 minutes later got all 7. Not a paths/types filter (standard-checks + chart-version-guard have no paths filter and also did not fire), not a draft, not an incident (status green), and PR head == remote head == local head. GitHub-side miss on the open event; `synchronize` re-dispatches all six gating workflows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(installer): drop head from the pipeline — a duplicate key must keep its value (Bugbot, #525) The first fix (`grep | head -1 || line=""`) traded one failure for another: on a DUPLICATE key, head exits after the first line and SIGPIPEs grep (141); under pipefail the `|| line=""` fallback then wiped the successfully captured value, so detect_installed_client could miss a clientId and fail open toward overwrite. Capture every match and take the first line in the shell (`${line%%$'\n'*}`) — no downstream consumer, so grep's rc is 1 exactly when there is no match, which is the one case the fallback exists for. Regression test pins the duplicate-key bare-call shape; manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* test(bats): make every assertion enforce — 1240 were advisory Under Bats (verified 1.13.0) only the LAST command in a test body decides the result, so a failing assertion anywhere earlier is silently ignored: @test "middle failure ignored" { [[ "abc" == *"zzz"* ]] # FALSE [[ "abc" == *"abc"* ]] # TRUE (last) } # -> ok This suite is written multi-assertion throughout, so most assertions could not fail their test. Appending `|| return 1` makes them enforce. Scope is about twice what it first looked. It is not only `[[ ]]`: single-bracket `[ ... ]` has identical semantics and there are MORE of them (609 vs 574), plus 61 negated bare commands. 1240 assertions across 15 files — setup-linux.bats 296, cluster.bats 153, install-client-helm.bats 146, common.bats 118, preflight.bats 102, and the rest smaller. Only whole-line assertions INSIDE an @test body are touched. Helpers and setup/teardown are excluded (a bare `return` there means something different), as are the 9 control-flow `if/while` conditions and 18 lines already chained with && / ||. All files still parse (bats --count), no control-flow line was modified, and nothing was double-appended. TRIAGE RESULT: zero new failures. All 1240 were already true — the suite was accidentally correct, so there was no hidden-bug vs stale-assertion split to report. No assertion was deleted or weakened to reach green. That result only means something if the hardening has teeth, so it was proven rather than assumed. cluster.bats's "_augment_no_proxy: empty host NO_PROXY" asserts 7 substrings and only enforced the last. Deleting `localhost` from TB_NO_PROXY_DEFAULTS — the entry that keeps a corporate proxy from intercepting loopback — is a real regression, and: mutated source + ORIGINAL tests -> ok (invisible) mutated source + HARDENED tests -> not ok (caught) Guard, so the pattern cannot come back: scripts/tests/bats-hygiene.bats plus a shared scanner, scripts/tests/unenforced-assertions.awk (one implementation, used by the guard and by its own self-tests). Three tests: the suite is clean; the scanner flags an un-hardened assertion and spares a hardened one; and it ignores control flow, chained lines, helpers and HEREDOC BODIES. That last exclusion is not cosmetic — the first version flagged its own fixture, which would have made any future test embedding example bats source a false positive. The guard was mutation-tested against the real suite too: un-hardening one line in cluster.bats makes it fail, naming the exact file:line. Gates: bats scripts/tests/*.bats -> plan 693, ok 693, not ok 0 (complete TAP run, plan line checked — a truncated read can look green while half the suite never reports); shellcheck --severity=error over the CI file set -> rc=0; check-style clean; check-drift no drift; gen-manifest.sh --check current (only tests changed, and tests are not part of the hashed set). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(bats-hygiene): scanner sees internal-OR and negated-bare assertions (Bugbot #527) Two Bugbot findings on the hygiene guard this PR introduces. Both real: the guard could report "suite is clean" while assertions stayed advisory — the exact failure mode the PR exists to close. Measured semantics first (bats 1.13.0, bash 3.2 system bash), because the old header's "only the LAST command decides" was too broad. Bats does run bodies under errexit; exactly two classes escape it: [[ ... ]] bash 3.2 (macOS system bash) does not fire errexit for a failing conditional expression — a middle one is ignored ! cmd POSIX: a status inverted with '!' is never propagated, so this escapes on EVERY bash, CI included grep -q ... a plain bare command DOES fail the test — correctly not reported 1) Scanner skips internal-OR assertions — REAL. `[[ a || b ]]` is ONE assertion whose ||/&& is internal; it exits non-zero on failure like any other and needs `|| return 1` too. The scanner skipped every line merely CONTAINING ||/&&, and only matched `[`/`[[` that closed on the same line, so it missed both single-line internal-OR and multi-line forms. Rewritten to build a logical line (trailing backslash, or a newline inside the brackets) and to locate the closer that matches the opener, so only a TOP-level chain earns the exemption: `[[ a ]] || fail` still skipped, `[[ a || b ]]` flagged, and `||` appearing only inside a quoted grep pattern no longer hides an assertion. Multi-line offenders are reported joined, at their first line. Six offenders it now catches (Bugbot named two; four are the same class): install-bootstrap.bats:144 and :154 — mid-body, so genuinely advisory — common.bats:179, install-client-helm.bats:887, preflight.bats:542, summary.bats:73. All six now end in `|| return 1`. 2) Guard omits negated bare commands — REAL. The PR hardened 61 `! cmd` assertions but the guard did not cover the class, so a later unhardened one would pass unnoticed — and this is the class that is advisory on every bash, not just 3.2. The scanner now flags standalone `! cmd ...`, while sparing `! cmd || return 1`, `if ! cmd`, bare `cmd`, and `run ! cmd`. Zero live offenders: the 61 are all hardened. Failing-test-first evidence, both directions verified by flipping the change: - two new bats-hygiene tests (internal-OR incl. both continuation styles and a pattern-only `||`; negated bare commands) fail on the old scanner, pass on the new one, and assert the spared cases so the scanner cannot over-report - with the new scanner and the un-hardened files, the "suite is clean" test fails and names all six offenders - end to end on real code: blanking install.sh's "not an immutable release tag" message left install-bootstrap.bats's two path-traversal tests GREEN before the fix and fails both after — an R8 regression the suite had been ignoring Also made the scanner portable (\b and `close` are not safe in every awk) and corrected the guard's header to the measured semantics. Local: bats scripts/tests/*.bats 695/695, shellcheck --severity=error clean, bash -n clean, gen-manifest.sh --check up to date, check-style.sh clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(chart-guard): harden the 46 assertions #530 added in parallel CI went red on the merge commit, not on this branch. Diagnosis first, because the answer changes the fix: #530 ("chart-guard: cover every published chart") merged scripts/tests/ chart-version-guard.bats into develop at 2026-07-31T15:59Z — 40 minutes AFTER this branch's last green Installer-tests run (30642417378, head 91a5fdd, 15:19Z). The file was written before this convention existed, so all 46 of its standalone assertions are bare. GitHub tests refs/pull/527/merge, so the guard correctly reported them. NOT caused by the scanner rewrite. The OLD scanner, exactly as shipped in 91a5fdd, flags the same 46 lines on that file — byte-identical output: awk -f <91a5fdd's scanner> chart-version-guard.bats | wc -l -> 46 awk -f <new scanner> chart-version-guard.bats | wc -l -> 46 diff of the two -> identical They are all plain single-line `[ ... ]` / `[[ ... ]]`, none of the classes this PR's rewrite added. So the branch head would have gone red on the same merge commit with or without my commit — this is develop drift meeting a guard that only just started existing, which is the guard doing its job on the first file that arrived after it. Fix: merge develop and append `|| return 1` to the 46. No assertion reworded, deleted or weakened; the guard is not relaxed to accommodate the new file. Local, post-merge: bats scripts/tests/*.bats 718/718, scanner reports 0, shellcheck --severity=error clean (incl. the new chart-version-guard.sh), gen-manifest.sh --check up to date, check-style.sh clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(bats-hygiene): a quoted <<TAG or a herestring is not a heredoc (Bugbot #527) REAL, and the most serious of the three findings — it made the guard lie. The heredoc detector matched `<<TAG` anywhere on a line, including inside a quoted string. Once tripped, it looked for a BARE terminator line that never comes, so the scanner silently ignored every remaining line in that file while the "suite is clean" test still reported clean. Proven on the real file, not just in theory. Appending an unhardened assertion to the end of bats-hygiene.bats — after its own `printf " cat > f <<'EOF'\n"`: awk -f unenforced-assertions.awk bats-hygiene.bats -> NO OUTPUT (invisible) bats bats-hygiene.bats -> ok 1 ... assertion ... ends in '|| return 1' The guard reporting clean while a bare assertion sits in the file it is scanning is the worst failure this PR could ship, since every other claim in the PR rests on that scan. A SECOND live instance Bugbot did not name: `<<<` herestrings. The regex matched from the second `<` of `run guard_leftover_data <<< "r"`, taking tag `r`, so leftover-guard.bats was swallowed from line 131 onward — the same canary appended there was equally invisible. Bugbot's Additional Locations listed only bats-hygiene.bats#L135-138. Fix, three parts: - `quoted_at()` walks shell quoting state, so a `<<TAG` inside '...' or "..." is text, not a redirection - `<<` immediately preceded by `<` is a herestring, not an opener - safety valve: an @test at column 0 ends heredoc-skip mode, so no future mis-detection can ever hide more than one test's worth of lines Real heredocs still skip their bodies: 12 genuine openers across the suite are still detected, and the pre-existing "ignores ... heredoc bodies" test fails if the tracking is deleted rather than fixed — so "stop tracking heredocs" cannot pass as a fix. Verified by disabling it: that test flips to not ok. Worth recording that the suite-clean scan CANNOT catch that regression (no real heredoc body in the suite contains a bare bracket line), so the fixture test is the only guard on it. Two new tests, flipped in both directions: old scanner -> not ok 5 (expected line 3 to be flagged) not ok 6 (expected line 6 to be flagged) new scanner -> ok 5, ok 6 Each fixture carries several distinguishable entries and asserts the exact offender count plus the spared lines, so neither can pass by over-reporting or by a fixture too small to tell an anchored rule from a loosened one. Local: bats scripts/tests/*.bats 720/720, scanner reports 0, shellcheck --severity=error clean, gen-manifest.sh --check up to date, check-style.sh clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(bats): enforce assertions in develop's newly-merged tests (#527 hygiene) Merging develop brought in test files/tests added after this branch forked (check-facts.bats, index-invariants.bats, setup-macos-lifecycle.bats, and new preflight.bats cases) whose standalone assertions were written in the bare, advisory form. bats-hygiene.bats — the enforcing-assertion guard this PR adds — correctly flagged 134 of them. Append `|| return 1` to each so every assertion can fail its test, exactly as this PR does across the rest of the suite. Mechanical: `|| return 1` inserted before any trailing inline comment; negated bare commands (`! grep …`) get the same enforcing form. Verified by re-running the scanner to zero offenders and the full bats suite. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bats): scanner enforces on real `|| return 1`, not the substring (Bugbot) The enforcing check was a line-wide substring match for `|| return 1`, so an assertion that merely MENTIONED the marker was treated as hardened though it does not enforce: `[[ "$output" == *"|| return 1"* ]]` (marker inside a quoted pattern) or `[[ "$x" == y ]] # ... || return 1` (marker only in a trailing comment) slipped through the guard (Cursor Bugbot, Medium). Add `strip_comment` (drop an unquoted trailing comment) + `is_enforcing` (require a `|| return 1` that is outside quotes and outside the comment), reusing the existing quote walker. New bats-hygiene self-test proves both fooling shapes are flagged and a real top-level `|| return 1` is still spared. Whole-suite sweep still reports 0 offenders, so the 134 conversions in the prior commit remain correctly recognized. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bats): scanner catches compound-line assertions; harden the 107 it revealed (Bugbot) The unenforced-assertions scanner classified a line as a bracket assertion only when it OPENED with `[[`/`[`, so a mid-line assertion — `run x; [[ ... ]]`, the last command of a compound line — was invisible. On bash 3.2 that `[[` still cannot fail the test, so 107 such assertions across preflight/check-drift/setup-* were advisory: the exact failure mode this PR closes. - Scanner: check the last `;`-segment of a compound line for a standalone bracket assertion or negated bare command (`last_segment` + `classify`). Quote-aware; `bracket_tail` distinguishes an internal `||` from a real top-level chain. - Harden the 107 revealed assertions (append `|| return 1`, before any trailing comment). No test logic changed — 304 suite tests still pass, 0 failures. - bats-hygiene.bats: regression test for the compound-line case. The other Bugbot findings on this PR (internal-OR, negated-bare, substring, false-heredoc) were already handled by earlier commits; this closes the last one. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bats): scanner robust to nested braces, one-line tests, subshell semicolons (Bugbot) The hygiene scanner reported "clean" while missing real unhardened assertions in three shapes Bugbot flagged: - a nested `name() { ... }` stub's column-0 `}` ended the @test scan early (check-drift.bats had an unhardened `[ "$_drift" -ge 1 ]` after a helm() mock) -> track brace DEPTH, not the first `}`. - one-line `@test "x" { run ...; [ ... ]; }` bodies were consumed as a bare opener and never scanned (common.bats had two) -> scan the inline body after the opening `{`. - an assertion that is not the LAST statement of a compound/one-line body -> classify each `;`-separated statement (subsumes the earlier last_segment hack, more correctly); paren-aware so a `;` inside a `( )`/`$( )` does not split a hardened `! ( a; b ) || return 1`, and comment-aware so a `;` inside a trailing comment is not split either. Hardens the 26 assertions the improved scanner then surfaced: cluster.bats / assess.bats and the new #542/#547 check-facts tests (all pulled in by the develop merge), plus check-drift.bats and the two common.bats one-liners. Adds 3 regression tests (nested braces, one-line bodies, subshell `;`). Full suite 804/804; hygiene 12/12; scanner clean. * test(bats): top-level chain must ignore quotes/subshells; join mid-line multiline brackets (Bugbot) Two more scanner gaps Bugbot flagged on the rewrite, both real: - the `||`/`&&` "already chained" exemption matched the operator anywhere in the statement, including inside a quoted pattern (`! grep -q "a||b" f`) or a `( )` subshell -> an unhardened negated command was silently treated as chained. Now a quote- and paren-aware top-level scan (`has_toplevel_chain`). - `bracket_open` only saw a continued `[[`/`[` at the START of the logical line, so a bracket opening mid-line (`run x; [[ a ||` continued onto the next line) was never joined -> a multi-line compound bracket stayed invisible. Now also checks the last `;`-segment. Adds 2 regression tests. Full suite 806/806; hygiene 14/14; scanner clean. * test(bats): scan one-line bodies whose bracket abuts the group closer (Bugbot) A one-liner with no `;` before `}` (`{ … [ a ] }`, or the no-space `[ a ]}` / `[[ a ]]}` where the closer is not recognised) left a `}` in the assertion's post-closer tail, so it read as non-standalone and stayed invisible. Strip the one-liner's group-closing `}` before classifying. Valid bats needs a `;` before `}` (verified: `f() { [ 1 = 1 ] }` is a bash syntax error), which already splits the assertion off — so this is defensive for the degenerate shapes, not a live suite offender. Regression test 15. Full suite 807/807; hygiene 15/15; scanner clean. * test(bats): make the bracket-closer finder quote-aware (Bugbot) after_close matched a blank-delimited `]]`/`]` by a word-boundary heuristic but never walked quote state — the one structural walker that wasn't quote-aware. A closer inside a quoted pattern (`[[ "$x" == "a ]] b" ]]`, `[ "$x" = "] y" ]`) was mistaken for the real closer, so the assertion read as non-standalone and an unhardened offender could slip through. Require the closer position to be unquoted (reuses quoted_at), matching split_segments / has_toplevel_chain / brace_delta / after_first_brace / strip_group_close. Regression test 16. Full suite 808/808; hygiene 16/16; scanner clean. * test(bats): harden the 24 assertions that arrived via the develop merge The hygiene gate went red on its own merge commit: develop gained gpu-nvidia.bats (2 advisory assertions) and the #582 network-profile block in preflight.bats (22 more) after this branch's sweep. Same mechanical treatment -- append `|| return 1`, comments preserved in place. Scanner reports 0 offenders; gpu-nvidia, preflight and bats-hygiene suites pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bats): a || return 1 inside a subshell is not hardening (Bugbot) is_enforcing scanned for an unquoted `|| return 1` anywhere in the statement, so `! ( cmd || return 1 )` was spared — but that return only exits the subshell while the `!` still escapes errexit, leaving the statement advisory. Rewritten on the same quote+paren walker as has_toplevel_chain: only a top-level `|| return 1` counts. Fixture pins both subshell shapes (`( )` and `$( )`) flagged and both top-level shapes spared; the full-suite scan stays clean, so no real assertion was relying on the loophole. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(bats): a <<TAG in a comment is not a heredoc opener (Bugbot) heredoc_tag_of was quote-aware but not comment-aware, so a trailing comment DOCUMENTING heredocs opened skip mode with no terminator coming and the rest of the @test body was silently swallowed — live in this very suite, where bats-hygiene.bats comments mention <<TAG. Scan the comment-stripped line; strip_comment returns a prefix, so positions stay aligned for the quote and herestring look-arounds. Fixture pins: comment-mention doesn't skip, a real heredoc still does, and scanning resumes after its terminator. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: shujaat hasan <shujaat@tracebloc.io>
…eqs hang (#593) * fix(ci): bound the two unbounded network waits behind the ubuntu Prereqs hang Three times on 2026-08-04 (#525, #592) the "Prereqs — ubuntu:*" matrix jobs died at the 20-minute job timeout with nothing in the log but "Installing Docker…", and once more failed in 20 seconds with a registry-1.docker.io timeout (exit 125). Two unbounded waits, one per layer: - Workflow: `docker run` pulls the distro image implicitly with no timeout, so Hub connectivity trouble either failed fast (exit 125) or stalled the whole job. Both container-matrix jobs (distro-prereqs, path-persist) now pre-pull with three bounded attempts (timeout 300 + backoff) and an honest "runner-to-registry connectivity, not this PR" error. - setup-linux.sh: the get.docker.com convenience script's internal apt/download.docker.com fetches carry no timeout, so a stalled connection hung silently behind the spinner. The run is now bounded at 10 minutes (healthy installs take 1-3) and fails with a clear stalled-download message telling the operator to re-run; the fetch of the script itself already had retry + curl_secure timeouts. Same shape as the existing dpkg-lock and kubectl-fetch bounds. New bats test pins the timeout bound on the get.docker.com branch (hardened with || return 1 for the incoming #527 hygiene gate). Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ci): distinguish a stall from a real failure; keep the pull budget small (Bugbot ×2) - setup-linux.sh: `if ! spin_cmd …; then error "stalled 10 minutes"` fired on ANY failure, mislabelling a fast real apt/script error as a stall — and it bypassed the existing spin_cmd_bounded helper, which returns 124 only on the deadline and tails the log on every failure. Switched to it: rc 124 gets the stalled-download message, any other rc gets an honest install-failed message pointing at the log tail. Harness gains a default spin_cmd_bounded mock; the bats test now pins the helper + its 600s bound. - installer-tests.yaml: three timeout-300 attempts + backoff could eat ~16 of the job's 20 minutes, so a late-succeeding pull just moved the death from the pull to the install. Bounds resized (3 × timeout 90, 10/20s backoff, ~5.5 min worst case) so the job keeps most of its budget; a healthy pull takes seconds. Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(installer): prepare-host gets prepare-host re-run advice (Bugbot) The new get.docker.com stall/failure errors always said "re-run the installer" — but with TB_PREPARE_HOST_MODE set that points an admin at a full provision as themselves, the exact outcome prepare-host exists to prevent. Pick the re-run verb by mode, matching the daemon-check errors later in the same function. Manifest regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… PVC mounts (RFC-0003 D9 Track B, client-runtime#203) (#594) Companion to client-runtime#261: flag-gated ClusterRole grants for the PV provisioning/GC path (persistentvolumes create/get/list/patch/delete, persistentvolumeclaims create/list/delete) + PER_DATASET_PVCS=1 into jobs-manager. Default off: byte-identical rendering. clusterScope: false + perDatasetPvcs fails the render (PVs are not namespace-grantable). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
LukasWodka
commented
Aug 5, 2026
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
4 issues from previous reviews remain unresolved.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit d6c4c2e. Configure here.
LukasWodka
commented
Aug 5, 2026
@shujaatTracebloc — Bugbot flagged 4 issues on the preflight/proxy code (from #590/#582) as this hits the staging mirror, so client is deferred from today's staging hop until they're addressed on develop:
|
…#589) (#600) Bugbot on the staging mirror flagged 4 issues in the corporate-proxy / TLS- inspection probe (from #590/#582): - HIGH: the TLS probe cleared an already-captured issuer via `|| issuer=""`; openssl s_client often exits non-zero (SIGPIPE after x509) even on a good handshake, so MITM networks read as 'unknown'. Use `|| true` (empty capture is still caught below). - proxy password url-decode ran the whole string through printf '%b', mangling literal backslashes; escape them first so only percent-escapes expand (PS parity). - `openssl -help | grep -q` under pipefail dropped -proxy_user on authenticated proxies (grep -q closes the pipe, openssl gets SIGPIPE); capture then match. - PS Get-TlsInspectionState: [System.Uri] rejected schemeless proxy.corp:8080; prepend a scheme like the display path already does. Regenerated the R8 manifest for the install-k8s.ps1 change.
LukasWodka
commented
Aug 5, 2026
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c7aed81. Configure here.
Uh oh!
There was an error while loading. Please reload this page.

Automated promotion by the release train (RFC-0008 D14). Head is the train-managed
release-train/to-stagingbranch (a mirror ofdevelop), so it never collides with a human PR. Merged only when the fr-gate is green.Note
Medium Risk
New optional chart RBAC grants cluster-scoped PV/PVC powers when
perDatasetPvcsis flipped on, and installer changes affect real customer install paths (TLS, logging, GPU, cluster start)—mitigated by defaults-off flags and extensive tests, but staging should validate enabled knobs and installer smoke on restricted networks.Overview
Automated develop → staging promotion carrying a broad client/installer/CI slice.
Helm (1.9.12 → 1.9.13): Adds opt-in
perDatasetPvcs(RFC-0003 D9 Track B): when enabled, jobs-manager getsPER_DATASET_PVCS=1, flag-gated ClusterRole PV/PVC provision/GC verbs, a render-time fail if combined withclusterScope: false, plus schema/values docs and unittest coverage. Default installs stay unchanged. requests-proxy now picksIfNotPresent+repo@digestwhenimages.requestsProxy.digestis set (was alwaysAlways, #552).Installers (bash + PowerShell): Corporate CA trust wiring before preflight/downloads (#583), network profile (proxy/TLS inspection/CA) ahead of connectivity probes (#582), curated UTF-8 logs (no
Start-TranscriptPII/leaks, #576), top-level fatal/interrupted messaging (#577), GPU plugin failures downgrade to CPU mode with boundedkubectltimeouts, k3d cluster start bounded wait, Docker install 10m cap on Linux, YAML extract pipefail fix, and lowercase tracebloc copy + style guard.CI:
azure/setup-helmpinned to commit SHA; bounded retrieddocker pullfor distro matrix jobs; curl timeouts on kubeconform download. BUGBOT notes secretlesscode-qualitycallers.Tests: New
bats-hygiene+unenforced-assertions.awk; widespread|| return 1on Bats assertions. Regeneratedscripts/manifest.sha256for touched bootstrap scripts.Reviewed by Cursor Bugbot for commit c7aed81. Bugbot is set up for automated code reviews on this repo. Configure here.