Clears the red main streak that began at 63a0adf9a:
- newTestConfigHandlers never stopped its alerts.Manager, leaking a
periodicSaveAlerts goroutine that logs through the global zerolog
logger and races with the authorization-refusal contract test's
logger swap under -race
- InfrastructureAgentDoctorPage used a raw select, tripping the
settings native-select guardrail; converted to the shared labelled
FormSelect primitive
- the metric-title residual pin still expected the removed -1 sentinel
copy; aligned with the Off-control wording from 16179dd0a
Contract-Neutral: test-only CI red fix: stops alerts.Manager goroutine leak in api test helper, converts agent doctor raw select to the canonical FormSelect primitive the frontend-primitives contract already mandates, updates a stale test pin; no public contract delta
Every in-product upgrade destination (gate CTAs, the business-estate card,
the public /pricing resolver for mapped features) routed to the bare billing
plan page, which renders plan comparison and selection only when the
intent=self_hosted_plan query parameter is present — so the surfaces asked
users to look at plans and then landed them on a page that showed none.
Route them all through the plan-selection href; checkout source attribution
composes with the intent param unchanged, and public /pricing arrivals stay
unsourced.
The Patrol page had the same dead end plus a context gap: plan-locked free
sessions saw only a lone "Plans & Billing" button with the mode selector
hidden, so the upsell never showed what upgrading unlocks. Render the four
Patrol modes with paid modes disabled and Pro-badged for plan-locked
sessions (the presentation already used for runtime-locked installs), keep
it fully suppressed when commercial surfaces are hidden, and relabel the
action "Unlock Patrol modes".
Route config-owned install commands and setup-script artifacts through the canonical trusted request-origin resolver. Preserve configured URL precedence and add endpoint-level adversarial coverage for token-bearing commands.
The Settings > System > Network field described the public URL as only
the address used in email alert links, but since 8e2858dac (refs #1692)
it is also the base URL advertised in copied agent install/update
commands. Rename the label to say both, describe both uses and the
reverse-proxy case, and suggest an https FQDN placeholder instead of a
LAN http address. Update the settings architecture copy pin to match.
Contract-Neutral: settings copy-only change: Public URL field label/description/placeholder wording; no payload, route, or contract surface change
Agent install and update commands advertised http://<LAN-IP>:7655 on
installs where the operator browses Pulse over an https FQDN, because
boot-time detection pre-fills config.PublicURL with an IP guess and
resolvePublicURL treated that guess as configuration. Track
auto-detected values (boot probe or first-request capture) separately:
explicit config from the env var or the settings UI still wins, but an
auto-detected guess now yields to the origin of the admin request that
is asking, so copied commands match how the instance is actually
reached.
Also stop boot detection from clobbering a settings-persisted public
URL on restart, which silently reverted the operator's saved value
whenever PULSE_PUBLIC_URL was unset.
Refs #1692
Contract-Neutral: behavioral fix to advertised-URL derivation: no API shape, field, or endpoint changes; PublicURLAutoDetected is internal (json:-)
The PBS poller called GET /nodes once per cycle just to relearn the
node hostname, which is stable for the life of the connection. On
tokens that cannot read /nodes, PBS logged a 403 every ten seconds
forever. Cache the name on the client after the first success and
defer retries for 30 minutes after a permission denial so a widened
ACL still heals without a restart. Transient failures keep retrying
each cycle.
Refs #1691
Two failures landed this morning:
- test_gitleaks_ignore.py's historical-fingerprint resolution (added in
d1fa7f38c) needs branch- and tag-reachable history, but the
scripts-and-build job used a depth-1 checkout, so all 37 fingerprints
failed to resolve in CI. Fetch full history like the gitleaks and
changes jobs already do.
- d1f687c0e routed frontend-modern/package.json and package-lock.json to
the new frontend-dependency-security path policy without updating the
manifest expectations pinned in test-hot-dev-bg.sh. Pin the effective
first-match policy per manifest instead of bare membership so the
routing stays asserted and shadowed entries cannot fake coverage.
Contract-Neutral: CI-only fix: full-history checkout for gitleaks fingerprint resolution test and re-pin hot-dev manifest policy expectations to the registry routing d1f687c0e already established; no contract delta