Commit Graph

8562 Commits

Author SHA1 Message Date
rcourtman d618fb8b74 Harden hypervisor guest CPU authority 2026-07-23 22:19:35 +01:00
rcourtman b8ea840f11 fix(monitoring): make Unraid task state freshness-safe 2026-07-23 22:17:25 +01:00
rcourtman d235aab3cf Fix RBAC assignment migration and loading 2026-07-23 22:11:48 +01:00
rcourtman 8c341753ae Normalize physical disk endurance evidence 2026-07-23 22:11:22 +01:00
rcourtman 13c4b57885 Fix VMware connection test degradation handling 2026-07-23 22:06:57 +01:00
rcourtman 50bac2ccf1 Ensure Docker lifecycle lab removes fixtures 2026-07-23 22:06:57 +01:00
rcourtman 615fa4418b Restore Docker agents to Hosts inventory 2026-07-23 22:06:56 +01:00
rcourtman 6a527ba9f2 Fix Proxmox physical disk inventory continuity 2026-07-23 22:05:09 +01:00
rcourtman b14cb376bc Prove resolved alert lock discipline
Route canonical cooldown refires through one resolved-state critical section and document the m.mu to resolvedMutex invariant. Exercise production refire, recovery, broadcast, alias repair, cleanup, and shutdown paths under the race detector while preserving cooldown history and start-time semantics.
2026-07-23 21:59:46 +01:00
rcourtman 5772589363 Prove TrueNAS alert threshold identity persistence 2026-07-23 21:54:57 +01:00
rcourtman 8580b48abc Fix Docker container update recreation lifecycle 2026-07-23 21:39:35 +01:00
rcourtman 2b7d202d8d Fix bounded Docker update checks
Keep manual check commands active until registry collection completes. Deduplicate replayed and concurrent commands, bound collection and acknowledgement retries, surface registry result counts, and prove timeout, rate-limit, and replay behavior.
2026-07-23 21:38:20 +01:00
rcourtman d7793a255d Fix TrueNAS boot and replication health classification 2026-07-23 21:37:26 +01:00
rcourtman e1a05104d9 Fix remote telemetry adoption reports 2026-07-23 20:38:09 +01:00
rcourtman e8bf181a57 Cover AI chat fixture abort path and licence presentation fallbacks
Two more frontend modules with a measured residue their existing specs never
reached. Deltas are uncovered counts, module scoped, existing specs versus
existing plus new.

- aiChatDevStreamFixture: branches 32 -> 2 uncovered; abortError and
  handleAbort, previously never called, are now covered. The abort tests
  assert the real cleanup lifecycle (timer cleared, listener removed, error
  shape) rather than only that a promise rejected, and the per-step pacing
  arms are exercised across their full cadence table.
- licensePresentation: branches 29 -> 24 uncovered, targeting the licence
  expiry, tier and seat-count fallbacks.

No source file is modified. Adversarial review found no rejects. One describe
block in the chat-fixture test was removed before committing: it duplicated
exact event sequences already asserted in aiChat.test.ts and its trailing
checks were tautological with the toEqual above them; re-measuring after the
removal gave an identical delta, confirming it contributed no coverage.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change

Contract-Neutral: test-only branch coverage, no source or contract change
2026-07-23 18:55:12 +01:00
rcourtman 1d96b918c2 Cover infrastructure operations, thresholds and chart API branch arms
Four more frontend modules with a measured residue their existing specs never
reached, including seven functions no test called at all. Deltas are uncovered
counts, module scoped, existing specs versus existing plus new.

- infrastructureOperationsModel: branches 38 -> 1 uncovered and
  createSurfaceScopedRow, previously never called, is now covered. This was
  the largest proportional branch gap left in the frontend.
- summaryTableFocus: branches 26 -> 11 uncovered and scheduleViewportRefresh,
  previously never called, is now covered.
- thresholdsResourceModel: hasThresholdDiff, dockerContainerOverrideIdCandidates,
  findOverrideByCandidates and buildAgentHeaderMeta were all uncalled; covered
  branches move 114 -> 130.
- api/charts: getStorageSummaryCharts and timeRangeToMinutes were uncalled;
  covered branches move 41 -> 55. The fetch mocking follows the existing specs
  and asserts parsed results, not that the mock was called.

No source file is modified. Adversarial review found no rejects; one subtest
duplicating an arm a sibling already covered was removed before committing and
the coverage was re-measured unchanged.

A fifth candidate, resourceBadgePresentation, was written and discarded rather
than landed: 263 tests moved the module by a single branch, because its
residual arms are unreachable defensive fallbacks.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change

Contract-Neutral: test-only branch coverage, no source or contract change
2026-07-23 18:24:21 +01:00
rcourtman e8740159cc Cover patrol handoff, resource adapters and TrueNAS page branch arms
Four frontend models whose existing specs called every exported function but
took only one arm of most conditionals. Deltas are uncovered counts, module
scoped, existing specs versus existing plus new.

- patrolInvestigationContextModel: branches 155 -> 19 uncovered, the largest
  single branch gap in the frontend. Covers the nullish-coalescing fallbacks,
  ternary alternates, singular and plural boundaries, the resource cap at
  MAX_ASSESSMENT_RESOURCES, and the identifier-label fallbacks.
- resourceStateAdapters: branches 51 -> 3 uncovered.
- truenasPageModel: branches 28 -> 7 uncovered.
- contextualFocus: all six previously uncalled DOM scroller helpers now
  covered, taking covered branches from 41 to 82. The uncovered count moves
  27 -> 29 only because those six dead functions bring their own branches into
  scope for the first time.

No source file is modified. Adversarial review found no rejects. Acted on its
findings before committing: a test claiming to cover an identifier-formatter
fallback actually passed through the formatter unchanged, so it is retitled to
say what it does, and the real fallback arm is covered separately by the
separator-only key case; a cross-field consistency assertion that compared two
fields the source assigns from the same local is replaced with the concrete
value; three subtests duplicating an arm a sibling already covered were
removed; and a comment describing the parent-chain walk was corrected, since
resolveScrollableAncestor uses parentElement and never sees the Document.
Re-measuring after the removals gave identical coverage.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change

Contract-Neutral: test-only branch coverage, no source or contract change
2026-07-23 17:51:41 +01:00
rcourtman 2ec5ef8d1a Record v6.1.1 release completion 2026-07-23 17:22:48 +01:00
rcourtman c46ce90484 Close remaining branch gaps in storage and discovery presentation
Four frontend modules had a small measured residue their existing specs never
reached, including four functions no test called at all. Deltas below are
uncovered counts, module-scoped, existing specs vs existing plus new.

- storagePageState: getActiveStorageNodeOptions was never called; branches
  5 -> 1 uncovered, functions 1 -> 0.
- discoveryPresentation: the three suggested-URL class helpers were never
  called; branches 3 -> 1 uncovered, functions 3 -> 0.
- infrastructureOnboardingPresentation:
  getInfrastructureSourcePickerItemForRouteStep was never called; functions
  1 -> 0.
- storageBarPresentation: branches 7 -> 0 uncovered, so the module is now
  fully branch-covered.

No source file is modified. Adversarial review found no rejects. Three
tautological assertions of the form f() equals f(), one test duplicating an
arm the existing spec already covered, and four cases re-exercising an already
covered arm of a two-arm selector were removed before committing; re-measuring
afterwards produced identical coverage, which confirms they contributed
nothing.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change

Contract-Neutral: test-only branch coverage, no source or contract change
2026-07-23 17:06:47 +01:00
rcourtman 5fde028276 Govern mobile Relay observability 2026-07-23 16:55:54 +01:00
rcourtman 0f938f8e9b Cover eval scenario catalog, control-plane printers and pure helpers
Adds branch-coverage tests for eight packages whose target functions were
measured at 0% before this change. Every named target was verified to move
by running each package's coverage with and without the new file.

- internal/ai/eval: all 36 Scenario constructors and the four PatrolScenario
  constructors 0% -> 100%. These are catalog-invariant tests, not literal
  echoes: unique names, populated required fields, runnable assertions, tool
  references checked against the agentcapabilities registry, and exact
  assertion-count deltas across the env-gated conditional appends. A parity
  test scans scenarios.go itself, so adding a constructor without registering
  it in the table now fails rather than silently going untested.
- cmd/pulse-control-plane: nine MSP and tenant-runtime print helpers
  0% -> 100%, covering the nil, empty-slice and optional-field arms.
- internal/ai/memory: RemediationLog GetByID, MarkRolledBack and
  GetRollbackable 0% -> 100%, pinning the overwrite-vs-preserve contract on
  RollbackInfo and each falsy arm of the rollbackable predicate.
- internal/alerts/config: AlertConfig.UnmarshalJSON 0% -> 90% and
  NormalizeAlertConfigAliases 52.9% -> 94.1%.
- internal/config: RunMigrationIfNeeded 0% -> 100%, copyFile 0% -> 88.9%.
- internal/mock: AvailabilityFixtures, FixtureGraph.SupplementalChanges and
  generateMockHostRate 0% -> 100%.
- internal/api: testProxmoxPlatformConnection 0% -> 100% through its injected
  connect func, so no network is involved.
- internal/servicediscovery: needsDeepScan 0% -> 100% across every return arm
  including the confidence boundary.

No source file is modified. Adversarial review found no rejects; two findings
were acted on before committing, replacing a circular catalog-count assertion
with the real source-parity scan and reducing an AllPatrolScenarios test that
compared the function against the same constructors it calls to the ordering
and completeness signal that is actually independent.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change

Contract-Neutral: test-only branch coverage, no source or contract change
2026-07-23 16:42:08 +01:00
rcourtman dc8a64b3b3 Update v6.1.1 release packet v6.1.1 2026-07-23 15:52:17 +01:00
rcourtman 20f9da541a Fix Proxmox backup posture identity 2026-07-23 14:55:44 +01:00
rcourtman 0cedde5f3d Resume v6.1.1 release after backend gate repair 2026-07-23 14:06:49 +01:00
rcourtman a45b568d79 Fix backend release gate failures 2026-07-23 14:03:44 +01:00
rcourtman 01a9bd2734 Fix stable patch workflow dispatch input types
Contract-Neutral: Correct workflow_dispatch JSON value encoding without changing the governed release contract.
2026-07-23 13:31:31 +01:00
rcourtman 781e168e34 Prepare v6.1.1 emergency patch release 2026-07-23 13:28:17 +01:00
rcourtman d2c268c0e5 Fix agent update triage and durable action recovery 2026-07-23 11:19:50 +01:00
rcourtman a082d5588f Add transparent telemetry payload update notice 2026-07-23 10:23:13 +01:00
rcourtman 2323c96385 Guard pseudonymous telemetry terminology 2026-07-23 09:38:50 +01:00
rcourtman 6e9fb01887 Cover eval CLI parsers, cloud audit predicates and vmware fixture fetching
Five new branch-coverage tests over the remaining pure vein, with no source or
existing test touched.

cmd/eval: twelve argument and environment parsers taken to full coverage,
including the two provider-filter variants driven so their differing default
behaviour is proved rather than assumed, the model list and exclude keyword
splitters over empty, whitespace and duplicate input, the selection reason
across every reason it can return, and the provider ordering proved
deterministic across repeated runs over the same map.

internal/actionlifecycle: the plan audit persistence asserted by reading the
record back through the store and by proving a store error is propagated rather
than swallowed, the policy mutation wrapper on both the success and error paths,
and the availability check error unwrapped through errors.Is.

internal/cloudcp: the audit failure accumulator including the monotonic OK flag
and the absence of deduplication, the container health predicate over each state
and health string it recognises with the case sensitivity of the state check
pinned, the tenant display name resolver against a real registry, and the
storage admission guard proved never to reach Docker when disabled.

internal/vmware: the fixture fetcher with independence asserted in both
directions and across consecutive calls, the refresh error wrapping asserted by
sentinel and message, the cached snapshot proved sorted, and the transport close
proved behaviourally by counting accepted connections on a loopback server
rather than by absence of error.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 08:07:35 +01:00
rcourtman fc6671b92e Cover action dispatch binding and in-memory store record keeping
Four new branch-coverage tests over internal/unifiedresources, taking the
dispatch binding helpers and the in-memory store's action, loop report and
change counting paths from zero to covered. No source or existing test touched.

The dispatch binding is exercised through every validation failure arm with its
concrete error, a successful bind asserted field by field, a re-bind over an
already bound attempt, and blank identifiers, alongside the operation binding
predicate and the empty policy posture summary proved to hand back independent
pointers.

The in-memory store paths are all write-then-read round trips rather than error
checks: expiry, dispatch receipt lookup, dispatch completion, execution refusal
and lifecycle event recording each assert the stored record afterwards, and the
audit expiry is driven with nothing eligible, a mix of eligible and ineligible
records proving the ineligible ones stay, and limits smaller than the eligible
count.

The loop report lookups pin the triple key exactly, with a window end differing
by a single nanosecond proved not to match, and the user outcome update asserted
through a subsequent read.

The six change counters each cover an empty store, a different resource that
must not be counted, the cutoff boundary on the real comparison, and for every
filtered variant a filter that selects a strict subset so the filtered and
unfiltered results are proved to differ.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 07:25:38 +01:00
rcourtman 610f9e0cb3 Cover telemetry classifiers, lifecycle records and install snapshot counts
Five new branch-coverage tests over the packages the telemetry lifecycle drop
touched, taking twenty-two functions to full coverage without touching any
source or existing test.

internal/telemetry: the deployment method precedence chain, the duration bucket
asserted one nanosecond either side of every boundary so the strict comparison
is pinned, every activation stage in its precedence order with the rank
ordering proved strictly increasing, the estate size bucket at each inclusive
boundary, the monitored resource count proved to draw on each counted field
individually, and the update failure classifier through every category arm
including the status short-circuit that wins over error text.

The lifecycle and install-id records are exercised as write-then-read round
trips under a temp directory and a frozen clock: a first-ever ping with nothing
on disk, a later ping against an existing record, an unreadable record, a
directory that cannot be written, and a reset proved to change the identifier
and persist the new one.

internal/monitoring: the alert outcome accumulation across the cutoff boundary
and each classification, and the install outcome accumulation over the arms
reachable without a live monitor.

internal/api: the read state snapshot mapping asserted field by field with
collection independence, both diagnostics collection normalizers, the in-memory
zip entry extraction across a missing entry, a non-zip payload and a zero-length
entry, and the trusted proxy check over IPv4, IPv6 and malformed input.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 07:15:13 +01:00
rcourtman c757a73382 Cover replay bundle loading, magic link expiry and subscription mapping
Three new branch-coverage tests taking six previously unreached functions from
zero to covered, with no source or existing test touched.

internal/ai/qualification: the replay bundle loader across a missing path, a
directory where a file is expected, invalid JSON, trailing JSON values and a
valid bundle round-tripped field by field, plus the artifact root creation
including the arm where the parent path is a regular file. Fixtures are written
into a temp directory so nothing outside it is read or created.

internal/api: the in-memory and SQLite magic link stores both deleting expired
entries, with the boundary case of a link expiring exactly at the passed instant
asserted on the real comparison, the valid entries proved still present, and
repeat deletion proved idempotent.

internal/cloudcp/stripe: the subscription mapper resolving a real customer over
the fallback, the fallback when no customer is present, item and price
extraction across empty and multiple item lists, and the two provisioner options
applied and overridden in order.

Reported for follow-up, not fixed here: mapStripeSubscription dereferences its
subscription pointer without a nil guard and is safe only because its single
caller skips nil subscriptions.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 06:59:05 +01:00
rcourtman 133a47d284 Cover agent policy, alias normalization and agent report helpers
Eight new branch-coverage tests taking thirty-one previously unreached
functions from zero to covered, with no source or existing test touched.

internal/kubernetesagent: twenty-one pure report helpers, including the pointer
converters proved non-aliasing in both directions, the ingress host and address
collectors across their trim, dedupe and insertion-order arms, the endpoint
slice readiness count where a nil Ready field counts as ready, and the target
role predicate.

internal/agentexec: the sudo long-option value gate over the real option list
including the inline equals form, and the approval grant verification error
unwrapped through errors.Is.

internal/alerts: the alert config alias normalization across the nil config
guard, the empty threshold early return, the blank type-key continue arm and
the legacy-delete versus supported-keep split, asserting both maps stay
independent.

internal/alerts/specs: the resource incident rollup evidence validation, each
failure arm asserted on its concrete error and the check order pinned when
several fields are invalid at once.

internal/cloudcp/docker: the not-found predicate through a wrapped error, the
route host label precedence, and the Traefik host rule parser across quoting
styles, combined matchers, multiple host clauses and malformed input.

internal/cloudcp/portal: the anonymous bootstrap builder, asserting no tenant
or user identity field is ever populated on the anonymous result.

internal/config: the legacy OIDC environment provider, including the arm where
an already-configured provider is present and the redirect derivation from a
public URL with a trailing slash.

internal/dockeragent: the update-all payload decode across wrong-typed and
missing fields, and the docker filter conversion.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 06:44:33 +01:00
rcourtman cba394e56b Cover control plane status helpers, patrol assertions and setup classifiers
Five new branch-coverage tests taking previously unreached functions from zero
to covered, with no source or existing test touched.

cmd/pulse-control-plane: the MSP status failure lookup across exact, absent,
case-differing and substring inputs, and the status state ordering proved
deterministic across repeated runs over the same map so a random map iteration
order cannot pass by luck.

internal/ai/eval: the signal coverage assertion driven through both the lazy
quality evaluation path and the supplied-quality path, at the minimum rate
boundary and either side of it, asserting the formatted message rather than
only the pass or fail outcome, plus the approval write command builder.

internal/api: the setup script server name derivation including the fallback
arm, the patrol autonomy level validator, the approval risk assessment across
every level it can return, and the two typed error messages.

internal/hostagent: the token already exists classifier over each phrase it
recognises, a wrapped error carrying the phrase, and near-miss messages that
must not match.

internal/monitoring: the limited temperature buffer including its truncation
boundary and its aliasing behaviour, and the mock series generators asserted on
determinism under a fixed seed and on their value bounds.

Reported for follow-up, not fixed here: the node escalation arm in the approval
risk assessment is unreachable for the current command set, generatePlateauSeries
panics on a negative point count and leaves its tail unclamped, and the limited
temperature buffer returns a slice that aliases its internal storage.

Contract-Neutral: test-only branch coverage, no contract surface touched
2026-07-23 06:34:03 +01:00
rcourtman dbca44937b Add privacy-safe telemetry lifecycle and outcome signals 2026-07-23 01:10:38 +01:00
rcourtman fe1e8dec24 Fix authenticated platform bootstrap for proxy and SSO 2026-07-23 00:18:21 +01:00
rcourtman 61a4c232bc Project PBS datastore alert overrides back onto the thresholds page
buildProjectedOverrides matched every pbs- prefixed override key
against the PBS instance map and returned even on a miss, so datastore
override keys (canonical <instance>/<name> and legacy
<instance>-<name>, both pbs- prefixed) were dropped from the
projection. Evaluation honoured the saved override but the thresholds
page rendered the alerts toggle as re-enabled after every reload. Fall
through to the storage lookup when the key is not a PBS instance.

Fixes #1591

Contract-Neutral: #1591 frontend projection fix for PBS datastore override keys; evaluation semantics unchanged
2026-07-22 23:27:25 +01:00
rcourtman 685c67cf3f Rename awk variable shadowing the exp builtin in the PVE setup script
pulse_pve_token_expire_label assigned a column to a variable named exp,
which mawk and BSD awk reject as a syntax error because exp is a
builtin function. The generated API setup script printed awk syntax
errors on every run and reported the token expiry as unknown.

Fixes #1604

Contract-Neutral: #1604 rename of a shell-template awk variable inside a rendered script; no API surface or contract change
2026-07-22 23:24:43 +01:00
rcourtman 24e7bf41c4 Route infrastructure workspace node edits to the update endpoint
The source-manager workspace retired the legacy per-type shells that set
the configured-nodes editingNode signal, so every save from the Manage
flow fell through to the add endpoint. Editing an existing PVE, PBS or
PMG connection then failed with "Authentication credentials required"
(or a duplicate-host conflict) and the editor closed anyway, discarding
the form. Pass the edited node along with the save call, report save
success, and keep the editor open when the save fails.

Fixes #1605

Contract-Neutral: #1605 frontend-only fix routing workspace node edits to the update endpoint; no subsystem boundary moved
2026-07-22 23:20:54 +01:00
rcourtman 8510243094 Fix platform navigation during stream reconnects 2026-07-22 22:54:49 +01:00
rcourtman 82083378a2 Cover cloud tenant registry queries, unified views and slowlog wrappers
Three new branch-coverage tests taking eighteen previously unreached functions
from 0.0% to covered.

internal/cloudcp/registry: the workspace limit error message on both the nil
and populated receiver, the active workspace count per account, the tenant
lookup across owning account, foreign account and missing rows, the invitation
listing by email including case and whitespace normalization, and the
invitation delete for both an existing pair and a pair that never existed.

internal/unifiedresources: the Docker container and Kubernetes node typed
views, the presentation listing and the metrics target, each asserted on the
nil receiver, the nil nested payload and the populated case, with returned
slices proven independent of the store.

pkg/db: the tracing wrappers around BeginTx, Query, QueryRow and their context
variants plus the pool setters, with exact histogram deltas proving the
observe wiring rather than that SQLite works.

All three files are new; no source or existing test was touched.

Contract-Neutral: test-only: new Go branch-coverage tests, no source or contract change
2026-07-22 21:41:02 +01:00
rcourtman bdebc0242f Sweep missing Patrol verdicts with a bounded follow-up pass
Smaller Patrol models (reported on Gemini 2.5 Flash-Lite, still failing
on 6.1.0 after the tolerant verdict-ID resolution shipped) end full runs
without calling patrol_assess_finding for the active findings, so every
run lands as 'Patrol needs attention' with the incomplete-assessment
error even though the infrastructure is fine. The main pass ran exactly
once with no enforcement when verdicts were missing.

When the pass completes cleanly but verdicts are missing, the run now
performs one bounded assessment sweep mirroring the signal evaluation
pass: a follow-up prompt listing exactly the missing findings with their
stored evidence, same executor so verdicts land through the shared
adapter and tolerant ID resolution, uncertain accepted as a complete
verdict, no investigation or new findings, capped at missing+2 turns
(max 12). Verdicts still missing after the sweep keep the existing
run-level error.
2026-07-22 21:09:23 +01:00
rcourtman f58073372c Record v6.1.0 release completion 2026-07-22 20:18:00 +01:00
rcourtman f8cdd76b79 Keep clusters that reuse node names apart in node state aggregation
Two PVE clusters whose nodes share hostnames (pve01/pve02 on different
subnets) collapsed into one: the agent-link hostname fallback bound the
second cluster's node to the first cluster's agent despite contradicting
IP evidence, and the shared LinkedAgentID then overrode the
cluster-scoped merge key, so the fresher node overwrote the first
cluster's slot and relabeled it. The endpoint-host merge alias had the
same hole when TLS settings degrade node endpoints to bare node names.

Hostname matches now reject candidate agents whose linked nodes live in
a different named cluster or whose reported IPs exclude the node's
endpoint IP, and neither a shared agent identity nor an endpoint alias
can merge two nodes whose named clusters contradict. Empty cluster
names still merge freely so standalone views keep folding into their
cluster node.

Reported via support by an MSP running two clusters plus a standalone
that reuse pve01/pve02 across sites.
2026-07-22 20:09:09 +01:00
rcourtman e1f33c1bad Fix release integration gate target v6.1.0 2026-07-22 18:15:19 +01:00
rcourtman 0b5763764c Cover API relay converters, request filters and AI approval helpers
Six new branch-coverage tests taking twenty-one previously unreached functions
from 0.0% to between 83.3% and 100.0%.

internal/api: the approval and context-confidence converters including a
round-trip inverse assertion, the handoff identity and safe-field merge, PBS
and PMG user normalization, the auto-register missing-fields message, the
magic link redactor, the metadata save message, shell quoting, the docker and
podman command count, the hosted entitlement backoff with its cap boundary,
the PVE backup and replication job filters, the ceph discovery target, the
metric point sampler, the install job status derivation, the ledger status
summary and validation error, the licensing bridge identity and retention
normalizers, the mock fixture env gate, and the AI to unified finding and
lifecycle converters.

internal/ai: the run command approval target resolver and record builder, the
provider catalog fallback merge with its case-insensitive dedup, the attention
alert recency comparison, the patrol run fact counter, and the patrol resource
metrics lookup.

Three suspected source issues were surfaced by this work and are recorded but
not fixed: metadataSaveErrorMessage and unifiedFindingFromAI both dereference
their argument without a nil guard, and unifiedLifecycleFromAI copies the
event metadata map by reference rather than cloning it.

All six files are new; no source or existing test was touched.
2026-07-22 16:29:44 +01:00
rcourtman b5d30649ee Cover SSO conversion, TrueNAS app mapping and config store round-trips
router_routes_auth_security: all seven SAML and OIDC conversion helpers, each
driven through both its nil-input and fully populated arms with field-by-field
assertions, from 0.0% to 100.0%.

truenas_app_providers: the four TrueNAS app-to-tool mappers for ports,
networks, volumes and containers, plus the log output formatter, each over
nil, empty, populated and partially populated input, from 0.0% to 100.0%.

config report_schedules and multi_tenant: the report schedule store path,
load and save, and the organization load, strict load, save, list and delete
operations, all over a temp directory. The pair contrast that matters is
covered explicitly: LoadOrganization defaults for a missing org where
LoadOrganizationStrict errors. Targets move from 0.0% to between 87.5% and
100.0%, with incidental lift on the surrounding normalize and parse helpers.

All four files are new; no source or existing test was touched.
2026-07-22 16:18:00 +01:00
rcourtman 8f32bdd396 Fix ping timeout ceiling expectation 2026-07-22 16:15:31 +01:00