mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
Consolidate shared contracts and retire obsolete obligations (#2904)
Shared rules were repeated across subsystem contracts, and some still required the deleted Discovery scanner or superseded proofs. Keep each shared rule at its canonical owner with scoped consumer links, retain local differences, and remove obligations whose runtime or verification path no longer exists. Correct the stale temperature-padding expectation, trusted-command producer description, telemetry adoption fields and proof names against current source. Qualification stays with the existing customer-journey document. Assistant, all four Patrol modes, paid entitlements, VM backup precautions and installer/native qualification limits are preserved. Runtime code, registry ownership and proof routing are unchanged. Validation: focused monitoring, API, identity, telemetry and server tests, contract/registry/status audits, scoped-link and ownership checks, and normal commit hooks. The two slices remove 466 net lines across 13 contracts and consolidate 16 shared rule families without moving the bulk into another catalog.
This commit is contained in:
@@ -3813,10 +3813,8 @@ approval/identity checks, output bounds and fresh config admission.
|
||||
|
||||
`TestCommandClientGuestOutcomeContract` covers status/output projection,
|
||||
truncation, ambiguity and independent subsequent admission.
|
||||
`TestGuestExecRealServerAgentDiscoveryAdmission` must carry decoded healthy
|
||||
evidence, exclude failed guest output, and resume on an explicit healthy scan
|
||||
over the real registered server/agent WebSocket boundary. Fake provider/config
|
||||
fixtures do not establish native PVE/HAOS safety or delivered behaviour.
|
||||
Command-result source controls do not establish native PVE/HAOS safety or
|
||||
delivered behaviour.
|
||||
|
||||
### Docker update readback is not mutation history
|
||||
|
||||
@@ -4292,10 +4290,8 @@ overlap, thaw, writes, liveness and resumption are verified. Do not unlock,
|
||||
thaw or automatically restart from this guard. Raw host-shell commands and
|
||||
typed VM lifecycle operations are not relabelled as guarded guest reads.
|
||||
|
||||
`TestCommandClientGuestExecutionAdmissionContract` pins no unverified handoff;
|
||||
`TestGuestExecRealServerAgentDiscoveryAdmission` connects real registration,
|
||||
server/agent WebSockets and VM/nested-Docker Discovery with fake config/provider
|
||||
boundaries. `TestVMGuestExecCapabilityBoundToRegisteredSession` pins old/unknown
|
||||
`TestCommandClientGuestExecutionAdmissionContract` pins no unverified handoff.
|
||||
`TestVMGuestExecCapabilityBoundToRegisteredSession` pins old/unknown
|
||||
agent rejection and retained deferral. Config ambiguity, cancellation,
|
||||
serialization/capacity and explicit-resumption controls are source proofs, not
|
||||
native PVE/HAOS-QGA, thaw, installed-agent or release acceptance.
|
||||
@@ -7205,9 +7201,10 @@ identifier before executing any `PolicyRequireApproval` command so a missed
|
||||
control-plane gate cannot silently turn into host-level RCE. The single
|
||||
exception is commands marked `Trusted` in the wire payload: those originate
|
||||
from a vetted Pulse-internal subsystem whose command catalog is hardcoded
|
||||
in Pulse source (today only the servicediscovery deep scanner, which wraps
|
||||
read-only inspections in `docker exec`). `PolicyBlock` still applies to
|
||||
trusted payloads. The `Trusted` field must never be set by a code path that
|
||||
in Pulse source. The Proxmox guest Docker checker and inventory collector use
|
||||
the fixed read-only catalog in `internal/monitoring/docker_detection.go`, wired
|
||||
through the authenticated executor in `internal/api/router.go`.
|
||||
`PolicyBlock` still applies to trusted payloads. The `Trusted` field must never be set by a code path that
|
||||
deserialises user input or accepts a caller-supplied command string.
|
||||
That same copied install transport must also normalize canonical base URLs
|
||||
before composing installer asset paths: when operators enter a trailing-slash
|
||||
@@ -8323,17 +8320,9 @@ workload liveness or containment in installed software.
|
||||
|
||||
### Per-tenant resource stores are released on offboarding and shutdown
|
||||
|
||||
`ResourceHandlers.getStore` opens a SQLite handle per org and caches it for the
|
||||
process lifetime. `CloseTenantStore` releases and evicts one org's handle and is
|
||||
called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
`CloseStores`, exposed as `Router.ShutdownResourceStores`, releases all of them.
|
||||
Without this an offboarded tenant kept its file descriptors and its
|
||||
`unified_resources.db-wal`/`-shm` files alive and its directory could not be
|
||||
fully removed. Closed stores are evicted from the cache so a later request opens
|
||||
a fresh handle rather than using a closed one
|
||||
(`TestResourceHandlers_CloseTenantStoreReleasesTheHandle`), and both entry points
|
||||
are idempotent and nil-safe
|
||||
(`TestResourceHandlers_CloseIsIdempotentAndNilSafe`).
|
||||
Tenant offboarding and process shutdown use the [API store-lifecycle contract](api-contracts.md#per-tenant-resource-stores-are-released-on-offboarding-and-shutdown),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Server upgrades nudge agent self-update within one report cycle
|
||||
|
||||
The unified-agent report ack now carries the server's version
|
||||
@@ -9244,14 +9233,8 @@ sampling only, not report schemas, identity, enrollment or command authority.
|
||||
|
||||
### Asymmetric bridge evidence regression coverage
|
||||
|
||||
`TestApplyHostReportBridgeIdentity` verifies two consecutive reports through
|
||||
host ingestion and checks both host-to-node and reciprocal node-to-agent links.
|
||||
Custom management bridges, private IPv4 and ULA addresses retain association
|
||||
when names differ and the provider endpoint is DNS-based. A Docker or generated
|
||||
bridge on either side alone must not supply inferred identity: testing only
|
||||
symmetric bridges would miss removal of filtering from one inventory.
|
||||
This proof does not establish safety for arbitrarily renamed Docker bridges
|
||||
or repair persisted links, and is not reporter or installed-release validation.
|
||||
Host report ingestion preserves the [monitoring bridge-evidence controls](monitoring.md#asymmetric-bridge-evidence-regression-coverage),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Durable host/node association intent (6 September 2026)
|
||||
|
||||
@@ -9299,20 +9282,8 @@ the alert manager and canonical resource timeline.
|
||||
|
||||
### Node setup action v7 compatibility
|
||||
|
||||
Workflow consumers pin `actions/setup-node` to
|
||||
`820762786026740c76f36085b0efc47a31fe5020` (v7.0.0). The action manifest
|
||||
retains the Node 24 execution runtime, setup/cache-save entry points and existing
|
||||
inputs. Its internal ESM/toolkit upgrade does not change the requested Node 24
|
||||
application toolchain. Consumers do not supply `registry-url` or depend on the
|
||||
removed dummy `NODE_AUTH_TOKEN` export. Explicit npm lockfile caching for test
|
||||
jobs and disabled automatic package-manager caching for privileged release jobs
|
||||
remain unchanged; no permission, dispatch input or signing backend changes.
|
||||
|
||||
`test_setup_node_upgrade_preserves_consumer_contract` in the existing workflow
|
||||
trust suite verifies every consumer pin, absence of the affected auth assumptions,
|
||||
workflow trust controls and the retained native Windows command/lifecycle proof
|
||||
steps. Native Windows execution remains a hosted check, not a local Linux claim.
|
||||
This upgrade is independent of the grouped signing/Docker/Tailscale updates.
|
||||
Workflow consumers and their trust controls follow the [deployment toolchain contract](deployment-installability.md#node-setup-action-v7-compatibility),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Command-channel registration frame ordering
|
||||
|
||||
@@ -9339,20 +9310,8 @@ an explicit timeout, and the original server still fails the ordering assertion.
|
||||
|
||||
### Physical-disk provider identity round trip
|
||||
|
||||
The monitor's disk readback preserves the Proxmox source ID separately from
|
||||
its canonical resource ID. Skipped physical-disk polls may refresh SMART data
|
||||
but must not feed canonical hashes into source inventory, changing identity at
|
||||
each subsequent projection. Views without Proxmox source metadata retain the
|
||||
legacy ID fallback. This does not relax cross-host/device correlation, migrate
|
||||
old duplicates, change agent authority, or redefine serial-less disk matching.
|
||||
|
||||
`TestPhysicalDiskSkippedPollPreservesSourceIdentity` in
|
||||
`internal/monitoring/physical_disk_roundtrip_test.go` drives eight real skipped
|
||||
polls and adapter rebuilds for both path-shaped and bare device names, checking
|
||||
provider keys, canonical IDs, JSON projection, temperature/size/cadence, separate
|
||||
nodes/controller members, and confirmed inventory removal.
|
||||
`TestPhysicalDiskReadbackSourceIDFallback` covers missing source metadata.
|
||||
This is synthetic runtime evidence, not USB hardware or reporter acceptance.
|
||||
Disk ingest and readback follow the [unified source-identity contract](unified-resources.md#physical-disk-provider-identity-round-trip),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Coalesced host readings follow configured source freshness
|
||||
|
||||
@@ -9668,16 +9627,6 @@ registration, enrolment, install, update or removal path changed.
|
||||
|
||||
### Mock-mode read views fold linked fixture agents
|
||||
|
||||
`internal/monitoring/monitor.go` changed only so the mock-mode unified view
|
||||
applies the operator's manual links (unified-resources contract, "Mock-mode
|
||||
unified view applies operator links"). A fixture agent the operator linked
|
||||
into a guest now folds into that guest in mock read views, as a linked agent
|
||||
already does in live mode, so host snapshots built from them
|
||||
(`HostsSnapshot`) stop listing it while the guest carries its facet. Agent
|
||||
registration, enrolment, report admission, removal, continuity and the
|
||||
fixture agent set itself are unchanged, and the view writes nothing to the
|
||||
resource store.
|
||||
|
||||
### Demo write guard ignores websocket upgrade headers
|
||||
|
||||
`internal/api/demo_middleware.go` changed only so a `POST`, `PUT`, `PATCH` or
|
||||
@@ -9728,39 +9677,13 @@ continuity are unchanged.
|
||||
|
||||
### Windows installer acceptance engine and absence (8 October 2026)
|
||||
|
||||
Native installer parsing, service-removal failure controls and actual lifecycle
|
||||
execution use Windows PowerShell 5.1, never a PowerShell 7 substitute. A missing
|
||||
or mismatched engine on Windows fails rather than skips. The dedicated runner
|
||||
rejects pre-existing or unknown service/state instead of deleting it before the
|
||||
proof. Both first and repeated uninstall require independent SCM, binary, state
|
||||
and listener absence; only the exact SCM not-found identity/category proves
|
||||
absence. Failed listener enumeration remains a failure. This changes validation,
|
||||
not installer authority, transport, enrolment or host containment.
|
||||
|
||||
`TestWindowsAgentLifecycleRequiresExactEngineAndIndependentAbsence` rejects the
|
||||
complete supplied parent and fourteen removed/changed controls. Native
|
||||
`TestWindowsAgentLifecycleObservationRuntime` executes the actual harness
|
||||
functions with fourteen no-mutation absence/failure/repeated-uninstall/owned-cleanup controls;
|
||||
the existing real lifecycle job then uses real SCM. Linux skips are explicit and
|
||||
do not establish a Windows parser, native runtime, reboot or installed result.
|
||||
|
||||
Clean-runner admission checks service, binary, state and listener absence before
|
||||
machine-environment mutation. A rejected admission cannot clear a pre-existing
|
||||
machine setting. Cleanup restores only the captured prior setting, even when
|
||||
owned server teardown fails; an unconfirmed stop fails and retains the handle
|
||||
rather than reporting clean teardown. Real Windows execution and full terminal
|
||||
cleanup evidence still have to be returned by the existing native CI job.
|
||||
Installer lifecycle qualification follows the [deployment Windows acceptance contract](deployment-installability.md#windows-installer-acceptance-engine-and-absence-8-october-2026),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Reconciled node-agent relink fold bookkeeping
|
||||
|
||||
A declared node-agent join can consume one split row before its newer
|
||||
operator relink is applied. The relink records that side's ID and source in
|
||||
the current holder-bound `ManualLinkFold` index, so identity-pin succession
|
||||
keeps the operator decision and the resources API seed retains the same fold
|
||||
for report-merge. No synthetic telemetry, identity key, enrollment or service
|
||||
link is added. `TestOperatorSplitOverridesProxmoxNodeAgentLink` checks that
|
||||
the monitor and its re-ingested API seed retain the fold across all split
|
||||
shapes, then survive pin persistence and a repeated split.
|
||||
Relink consumers preserve the [unified fold-bookkeeping contract](unified-resources.md#reconciled-node-agent-relink-fold-bookkeeping),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Mock-mode metrics-target lookups ride the fixture structure revision
|
||||
|
||||
|
||||
@@ -2201,7 +2201,7 @@ tool-result payloads must project through
|
||||
`OrchestratorToolResultInfo.ProviderToolResult` so the public investigation
|
||||
handoff contract inherits the same `agentcapabilities` input-map,
|
||||
thought-signature, and provider-result normalization as Assistant and MCP —
|
||||
`TestOrchestratorAndChatAdaptersMapTheSameMessageFields` enforces it.
|
||||
`TestOrchestratorAndChatAdaptersMapTheirMessageContracts` enforces it.
|
||||
|
||||
Assistant frontend presentation changes under
|
||||
`frontend-modern/src/components/AI/Chat/` must keep live tool activity aligned
|
||||
@@ -8647,11 +8647,9 @@ recompute digest counts from run history, findings, or cost events, and must
|
||||
not call the endpoint through any other client. Proof:
|
||||
`frontend-modern/src/api/__tests__/patrol.test.ts`.
|
||||
|
||||
The explicit issue explanation journey is qualified separately from provider
|
||||
reasoning and real remediation in
|
||||
`docs/qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md`. The repeatable browser
|
||||
proof is `scripts/check-patrol-assistant-journey.mjs`. A passing scripted
|
||||
response does not establish a useful customer outcome or model qualification.
|
||||
Issue explanation follows the [customer-journey qualification boundary](../../../../qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md#real-outcome-qualification-still-required),
|
||||
which separates scripted interaction proof from provider reasoning, remediation
|
||||
and repeatable customer outcomes.
|
||||
|
||||
### Subscription routing content boundary
|
||||
|
||||
|
||||
@@ -4337,11 +4337,9 @@ populated inventory and checks incident access on desktop and the 390px mobile
|
||||
rail. Enabled acknowledgement controls prove access only, not persisted
|
||||
acknowledgement or external notification receipt.
|
||||
|
||||
The explicit issue explanation journey is qualified separately from provider
|
||||
reasoning and real remediation in
|
||||
`docs/qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md`. The repeatable browser
|
||||
proof is `scripts/check-patrol-assistant-journey.mjs`. A passing scripted
|
||||
response does not establish a useful customer outcome or model qualification.
|
||||
Issue explanation follows the [customer-journey qualification boundary](../../../../qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md#real-outcome-qualification-still-required),
|
||||
which separates scripted interaction proof from provider reasoning, remediation
|
||||
and repeatable customer outcomes.
|
||||
|
||||
### Delivery health requests have latest-started ownership
|
||||
|
||||
@@ -4570,10 +4568,6 @@ Unknown values still fall back to all. The email adapter round-trip matrix and
|
||||
webhook edit/save regression cover issue #2069 without altering delivery filters
|
||||
or sending provider notifications. Component proof is not installed delivery.
|
||||
|
||||
Formatting-only follow-up retains this warning-level contract. The production-component
|
||||
browser matrix was rerun after formatting at desktop and narrow widths, including
|
||||
all/critical/warning save/reload, cancel, and warning webhook creation.
|
||||
|
||||
### SMTP rate-limit preference persistence
|
||||
|
||||
The existing SMTP editor's rate limit is included by
|
||||
|
||||
@@ -284,22 +284,6 @@ warming consumers. The connected browser fixture verifies actual History
|
||||
components/CSS on desktop Chromium and phone WebKit, not native identity,
|
||||
appliance history, workload safety or released availability.
|
||||
|
||||
### Discovery detail reads preserve final access status
|
||||
|
||||
`getDiscovery` retains final HTTP401/403 in a typed client error before any
|
||||
response-body read. The fixed message exposes no denied body. This applies to
|
||||
the typed resource detail, agent collection and resolved agent detail paths.
|
||||
A body or transport message claiming an access status is not that status, and
|
||||
ordinary transient failures retain their existing error behaviour. Successful
|
||||
absent-record semantics (detail HTTP404 or an empty agent list) are unchanged.
|
||||
Retained query consumers can therefore withdraw a denied service/endpoint
|
||||
rather than treating it as a transient read or a successful empty discovery.
|
||||
No endpoint, server permission, wire schema or mutation policy changes.
|
||||
`src/api/__tests__/discovery.test.ts` exercises all three paths with actual
|
||||
Response status/body objects, denied-body non-read and a misleading 503 body.
|
||||
The production guest browser fixture verifies the connected final HTTP403
|
||||
withdrawal, pending retry, transient retention and successful HTTP404 recovery.
|
||||
|
||||
### TrueNAS saved probes do not rewrite runtime evidence — issue #2382
|
||||
|
||||
The saved connection test uses stored server-owned secrets, or merges an edited
|
||||
@@ -11407,9 +11391,9 @@ fields.
|
||||
|
||||
### Per-tenant resource stores are released on offboarding and shutdown
|
||||
|
||||
`ResourceHandlers.getStore` opens a SQLite handle per org and caches it for the
|
||||
process lifetime. `CloseTenantStore` releases and evicts one org's handle and is
|
||||
called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
The API `resourceapi.QueryService` owns and caches SQLite handles per org.
|
||||
`ResourceHandlers.getStore` delegates to that owner. `CloseTenantStore` releases
|
||||
and evicts one org's handle and is called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
`CloseStores`, exposed as `Router.ShutdownResourceStores`, releases all of them.
|
||||
Without this an offboarded tenant kept its file descriptors and its
|
||||
`unified_resources.db-wal`/`-shm` files alive and its directory could not be
|
||||
@@ -11970,11 +11954,9 @@ disk. The advanced-reporting entitlement gates both kinds. Proofs:
|
||||
`internal/api/report_schedules_test.go`, `internal/api/patrol_digest_email_test.go`,
|
||||
`internal/api/ai_handlers_more_test.go`.
|
||||
|
||||
The explicit issue explanation journey is qualified separately from provider
|
||||
reasoning and real remediation in
|
||||
`docs/qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md`. The repeatable browser
|
||||
proof is `scripts/check-patrol-assistant-journey.mjs`. A passing scripted
|
||||
response does not establish a useful customer outcome or model qualification.
|
||||
Issue explanation follows the [customer-journey qualification boundary](../../../../qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md#real-outcome-qualification-still-required),
|
||||
which separates scripted interaction proof from provider reasoning, remediation
|
||||
and repeatable customer outcomes.
|
||||
|
||||
### Report email shares the canonical SMTP retry verdict
|
||||
|
||||
@@ -12024,10 +12006,6 @@ repairs a dropped supported value without introducing a new wire enum or changin
|
||||
backend routing. The notification adapter save/reload matrix verifies each
|
||||
supported severity in frontend-modern/src/api/__tests__/notifications.test.ts.
|
||||
|
||||
Formatting-only follow-up retains this warning-level contract. The production-component
|
||||
browser matrix was rerun after formatting at desktop and narrow widths, including
|
||||
all/critical/warning save/reload, cancel, and warning webhook creation.
|
||||
|
||||
### Quick security setup preserves unrelated settings
|
||||
|
||||
Authenticated force setup in `internal/api/security_setup_fix.go` retains the
|
||||
|
||||
@@ -392,41 +392,8 @@ thaw, safe writes, installed acceptance or a containing published release.
|
||||
|
||||
### Backup inventory ownership is source-scoped and unambiguous
|
||||
|
||||
The existing Backups Coverage and By date views do not select a workload from
|
||||
an arbitrary substring, display label or first matching row when VMIDs repeat.
|
||||
PVE files, guest snapshots and task evidence use the supplied connection scope
|
||||
before native node names or aliases. One VMID inside a matching PVE connection
|
||||
stays associated after node migration; a known conflicting connection cannot be
|
||||
rescued by a reused node name or a singleton fallback. With no connection scope,
|
||||
an exact native node/alias must identify one candidate; wholly unscoped singleton
|
||||
observations retain their existing compatibility behaviour.
|
||||
|
||||
PBS instance and datastore identify a repository, not a PVE workload. A PBS
|
||||
namespace disambiguates repeated VMIDs only with a unique exact native node,
|
||||
alias or PVE connection label. Unique type/VMID PBS inventory retains the
|
||||
existing root-namespace association. This bounded presentation fix does not
|
||||
implement the runtime PBS source learner or alter server-owned protection policy.
|
||||
|
||||
Unresolved artifacts remain listed once and keep complete, collision-safe source
|
||||
keys (PVE connection/node or PBS instance/datastore/namespace), including host
|
||||
backup labels. Equal VMIDs, repository labels or host names cannot pool them
|
||||
across unproven sources. Untyped PVE tasks may join only PVE-scoped rows, not a
|
||||
PBS-only unresolved row with a lookalike namespace. The existing collapsed group
|
||||
and count say **unmatched**, not that the guest necessarily ceased to exist;
|
||||
its explanation wraps on phones. These rows remain **not evaluated**, separate
|
||||
from canonical provider-owned protection posture and live workload counts.
|
||||
|
||||
Verification: `proxmoxBackupRecoveryModel.identity.test.ts` reproduces prefix
|
||||
and reused-node collisions, order independence, migration/alias controls,
|
||||
conflicting scope, ambiguous type/namespace and separated unresolved sources.
|
||||
Mounted `ProxmoxBackupsTable.test.tsx` backup-identity cases cover both views,
|
||||
artifact preservation, reorder/display rename, expansion identity and no extra
|
||||
inventory read. `browser-tests/backup-identity.cjs` uses production tables,
|
||||
router, inventory readers and CSS with synthetic responses on desktop Chromium
|
||||
and touch WebKit at 390px/320px, including keyboard/touch disclosure, ambiguity,
|
||||
readable unmatched explanation and same-resource recovery. No native backup
|
||||
identity, restore, guest thaw or containing-release acceptance follows from
|
||||
these source/render observations.
|
||||
Both Backups views follow the [storage source-association contract](storage-recovery.md#backup-inventory-ownership-is-source-scoped-and-unambiguous),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Diagnostics are live checks; downloads require a privacy review
|
||||
|
||||
@@ -8829,11 +8796,9 @@ App.architecture.test.ts protects the CSS scope and scroll ownership;
|
||||
non-scrolling wrapper. Browser receipts do not establish physical Android touch
|
||||
behaviour or every asynchronous update state.
|
||||
|
||||
The explicit issue explanation journey is qualified separately from provider
|
||||
reasoning and real remediation in
|
||||
`docs/qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md`. The repeatable browser
|
||||
proof is `scripts/check-patrol-assistant-journey.mjs`. A passing scripted
|
||||
response does not establish a useful customer outcome or model qualification.
|
||||
Issue explanation follows the [customer-journey qualification boundary](../../../../qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md#real-outcome-qualification-still-required),
|
||||
which separates scripted interaction proof from provider reasoning, remediation
|
||||
and repeatable customer outcomes.
|
||||
|
||||
### Alert health attention preserves asynchronous ownership
|
||||
|
||||
@@ -8849,20 +8814,8 @@ queue-action responses, without claiming backend notification delivery.
|
||||
|
||||
### Alert status distinguishes dispatch from destination evidence
|
||||
|
||||
The active alert card renders a valid diagnosis `lastNotified` timestamp as
|
||||
“Dispatch requested”, never “Notified”: the alert manager records this field
|
||||
before invoking delivery callbacks. A cooldown's `nextEligibleAt` is labelled
|
||||
“next eligible”, not a promised send time. Neither field proves destination
|
||||
acceptance or recipient receipt; that evidence must not be inferred from the
|
||||
muted presentation tone. Missing or invalid timestamps retain the existing
|
||||
pending/cooldown fallback; acknowledged alerts retain their badge without a
|
||||
second status line. No API field, notification policy or shared primitive changes.
|
||||
|
||||
The existing wrapping status text must remain readable at desktop and phone
|
||||
widths despite the longer labels. The presentation and Overview delivery-status
|
||||
tests cover the evidence boundary; `scripts/check-alert-dispatch-copy.mjs`
|
||||
qualifies the real Overview with scripted API data in Chromium, not installed
|
||||
notification delivery.
|
||||
Shared presentation preserves the [alerts dispatch-evidence contract](alerts.md#alert-status-distinguishes-dispatch-from-destination-evidence),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Resource incident reads retain lifecycle ownership
|
||||
|
||||
|
||||
@@ -1520,23 +1520,6 @@ live/collapsed/expanded/History acceptance.
|
||||
|
||||
|
||||
|
||||
**Availability backfill preserves concurrent discovery changes (7 September 2026)**
|
||||
|
||||
The backfill List snapshot is a work list, not an authoritative record to save.
|
||||
Read the current discovery, derive a missing suggestion from its current identity,
|
||||
and persist under one store write lock. State-provider reads stay outside that
|
||||
lock. Preserve newer identity, URL, engine version, user notes and existing
|
||||
(including dismissed) proposals; never resurrect a discovery deleted after List.
|
||||
A failed persistence attempt remains an error without installing the proposed
|
||||
change in cache. `TestService_BackfillPreservesConcurrentManualRepair` in `service_test.go`
|
||||
deterministically pauses SetReadState
|
||||
backfill after List, completes manual ESPHome repair, then resumes backfill and
|
||||
checks both cache and encrypted restart.
|
||||
`TestStore_BackfillAvailabilitySuggestionUsesCurrentRecord` in `store_test.go`
|
||||
covers current-identity
|
||||
inference, dismissal, deletion, unsupported identity and persistence failure.
|
||||
This is discovery state-integrity proof, not incident or notification acceptance.
|
||||
|
||||
**Correlated VM memory fallback — issue #1962 (7 September 2026)**
|
||||
|
||||
The next Proxmox guest poll indexes live agent memory embedded in VM read views,
|
||||
@@ -2790,10 +2773,9 @@ alerts, 5 vSphere incidents and 137 backup-age alerts in live mode, and counted
|
||||
a mock-mode observation toward a live connection's three-observation
|
||||
confirmation. `TestLeavingMockModeWaitsForAnInFlightEvaluation` holds an
|
||||
evaluation in its CPU window read, outside the alert manager's lock, and fails
|
||||
if the switch returns first; `TestLiveRefreshIgnoresARegistryRepublishedFromMockMode`
|
||||
lets a mock-mode rebuild republish while a live refresh is held before reading
|
||||
the registry back, then checks the next live refresh evaluates live records.
|
||||
Each of those two fails against a fence without its wait or its overlap check.
|
||||
if the switch returns first; `TestLiveRefreshRejectsCollectedRecordsFromMockMode`
|
||||
holds collected fixture records across a mode switch and checks that a live
|
||||
refresh publishes and evaluates live provider records without fixture leakage.
|
||||
`TestDockerPruneIgnoresTheRegistryMockModeLeft` raises a live Docker alert
|
||||
before any live rebuild and fails if pruning reads the fixture registry, and
|
||||
`TestPreviousStateCarryIgnoresTheRegistryMockModeLeft` fails if the
|
||||
@@ -3509,26 +3491,9 @@ service-history reads plus denial/recovery without fabricated samples.
|
||||
|
||||
`internal/monitoring/monitor_host_agents_test.go` and `pkg/agents/host/proxmox_lxc_test.go` must prove JSON wire-report ingestion through `ApplyHostReport`, partial/complete-empty recovery, contradictory IDs, unchanged node/agent/name/TTL protection, and no invalid-list-to-healthy-empty conversion. Omitted telemetry is never zero. Source proofs are distinct from native PVE and released availability.
|
||||
|
||||
### Discovery accepts successful command evidence only
|
||||
|
||||
Only stdout from a successful result with zero exit status and no error enters
|
||||
Discovery analysis or saved observations. Stderr, failed/partial output, a nil
|
||||
result and contradictory success/status cannot identify a service. Independent
|
||||
healthy output survives optional probe failures. When an attempted scan has
|
||||
failures and no successful stdout evidence, return a fixed no-evidence error
|
||||
and truthful terminal progress; manual metadata fallback and background
|
||||
enhancement must not replace saved results, notes or observation times. An
|
||||
explicit later healthy scan resumes normally; no failed command is replayed.
|
||||
|
||||
`TestDiscoveryFailedCommandEvidenceContract` covers VM/nested-Docker/LXC/host/
|
||||
Docker output admission, optional partial evidence, saved manual/background
|
||||
results and explicit recovery. Registered server/agent controls cover actual
|
||||
guest result propagation, with fake config/provider boundaries. This is source
|
||||
truthfulness, not native thaw, containing-release or workload acceptance.
|
||||
|
||||
1. Update this contract when monitoring truth ownership changes
|
||||
2. Tighten guardrails when `GetState()`-centric paths are removed
|
||||
3. Keep discovery-provider, host-agent ingest, guest-memory trust, metrics-history, storage-risk, Docker/Podman container collection, Docker report/model payloads, Proxmox Ceph and ZFS compatibility, Docker Swarm collection, mock runtime fixtures, and container bootstrap proof routes explicit in `registry.json`
|
||||
3. Keep network-discovery, host-agent ingest, guest-memory trust, metrics-history, storage-risk, Docker/Podman container collection, Docker report/model payloads, Proxmox Ceph and ZFS compatibility, Docker Swarm collection, mock runtime fixtures, and container bootstrap proof routes explicit in `registry.json`
|
||||
4. Update related read-state or monitor tests when new collector paths land
|
||||
5. Keep platform ingestion semantics aligned with
|
||||
`docs/release-control/v6/internal/PLATFORM_SUPPORT_MODEL.md`: hybrid is a
|
||||
@@ -3753,41 +3718,6 @@ existing reader behaviour and the real authenticated/scoped Pulse route.
|
||||
|
||||
V2 partial inventories preserve usable filesystem readings while leaving typed-helper health degraded. Global inventory failure still yields no inventory. No host-network exception, guest mutation, database/retention change or temperature substitution accompanies this repair.
|
||||
|
||||
### Discovery observes VM guest execution pauses
|
||||
|
||||
Verified VM results describe the guest's terminal status and decoded output,
|
||||
not successful CLI delivery. Discovery admits only successful stdout as command
|
||||
evidence for every resource type; stderr and failed/partial output are not
|
||||
observations. An attempted scan with failures but no successful stdout returns
|
||||
an error without replacing saved results or invoking analysis. Normal empty
|
||||
successful probes and independent healthy output alongside optional failures
|
||||
retain their existing semantics.
|
||||
|
||||
Manual, automatic and nested-Docker VM scans use the existing agent execution
|
||||
boundary; they cannot infer safety from the Web drawer's snapshot. VM routing
|
||||
requires an exact connected agent ID or a unique owning-node hostname, never a
|
||||
sole unrelated agent or guest-name hint. The agent independently requires its
|
||||
current local VM config and checks the operation lock. Discovery runs VM probes
|
||||
serially and stops on any explicit guest safety deferral, including optional
|
||||
probes. Deferred in-flight output is not fresh discovery evidence; progress
|
||||
retains an error and actual partial completion rather than 100% success.
|
||||
|
||||
A manual deferral is returned as an error without replacing saved discoveries,
|
||||
notes or raw observations with metadata fallback. Background enhancement keeps
|
||||
its existing evidence rather than analysing partial deferred output. Clearing
|
||||
a pause triggers no scan or retry by itself; an existing normal trigger or
|
||||
explicit request starts a new, guarded attempt. Healthy catalogue commands,
|
||||
non-VM parallelism, permissions, feature gates and saved-result access remain.
|
||||
|
||||
`TestDiscoveryGuestSafetyStopsAndPreservesSavedEvidence` covers both VM/nested
|
||||
Docker scans, first/later optional-command deferral, manual error and automatic
|
||||
saved-evidence preservation. Node ambiguity controls exclude misrouting. These
|
||||
source-connected controls and the agent protocol guard do not reserve QGA
|
||||
against PVE backup start, establish native thaw, or satisfy the existing native
|
||||
overlap/covered-write/liveness/resumption dependency. Preserve the monitoring
|
||||
and alert outage precaution until that operational outcome is verified.
|
||||
|
||||
|
||||
### Mock-mode unified view applies operator links
|
||||
|
||||
The mock branch of currentUnifiedStateView serves the fixture graph to the
|
||||
@@ -5345,12 +5275,12 @@ temperature, so a retained standby or silent-agent reading never reappears as a
|
||||
point at the current time.
|
||||
The SMART history writers in `internal/monitoring/monitor.go` and
|
||||
`monitor_agents.go` call that helper rather than a private copy of the rule,
|
||||
and `GetPhysicalDiskTemperatureCharts` pads a short disk temperature series out
|
||||
to now only with a collected reading: with a retained one the stored samples
|
||||
stay as they are, and a disk with none gets no series. Mock mode can still
|
||||
substitute its generic demo series for that disk ID before this step; that
|
||||
series is not derived from the disk's reading. Proof:
|
||||
`TestDiskTemperatureChartsPadOnlyWithCollectedReading` in
|
||||
and `GetPhysicalDiskTemperatureCharts` returns observed history samples without
|
||||
padding a short series to now, even when the current reading was collected.
|
||||
Retained readings never manufacture history. A live disk with no history keeps
|
||||
its metadata without a fabricated series. Mock mode may use its seeded demo
|
||||
history, which is separate from a disk reading. Proof:
|
||||
`TestDiskTemperatureChartsRetainOnlyObservedSamples` in
|
||||
`internal/monitoring/monitor_metrics_slo_test.go`.
|
||||
Unified-resource physical-disk round trips must retain named
|
||||
`StorageGroup` membership rather than degrading it to the generic `Used`
|
||||
@@ -6890,20 +6820,8 @@ that already admitted or provider-accepted deliveries can be recalled.
|
||||
|
||||
### Physical-disk provider identity round trip
|
||||
|
||||
The monitor's disk readback preserves the Proxmox source ID separately from
|
||||
its canonical resource ID. Skipped physical-disk polls may refresh SMART data
|
||||
but must not feed canonical hashes into source inventory, changing identity at
|
||||
each subsequent projection. Views without Proxmox source metadata retain the
|
||||
legacy ID fallback. This does not relax cross-host/device correlation, migrate
|
||||
old duplicates, change agent authority, or redefine serial-less disk matching.
|
||||
|
||||
`TestPhysicalDiskSkippedPollPreservesSourceIdentity` in
|
||||
`internal/monitoring/physical_disk_roundtrip_test.go` drives eight real skipped
|
||||
polls and adapter rebuilds for both path-shaped and bare device names, checking
|
||||
provider keys, canonical IDs, JSON projection, temperature/size/cadence, separate
|
||||
nodes/controller members, and confirmed inventory removal.
|
||||
`TestPhysicalDiskReadbackSourceIDFallback` covers missing source metadata.
|
||||
This is synthetic runtime evidence, not USB hardware or reporter acceptance.
|
||||
Disk ingest and readback follow the [unified source-identity contract](unified-resources.md#physical-disk-provider-identity-round-trip),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Unified metric replay guard bounds registry-rebuild writes
|
||||
|
||||
@@ -7186,14 +7104,7 @@ for a mock-style view.
|
||||
|
||||
### Reconciled node-agent relink fold bookkeeping
|
||||
|
||||
A declared node-agent join can consume one split row before its newer
|
||||
operator relink is applied. The relink records that side's ID and source in
|
||||
the current holder-bound `ManualLinkFold` index, so identity-pin succession
|
||||
keeps the operator decision and the resources API seed retains the same fold
|
||||
for report-merge. No synthetic telemetry, identity key, enrollment or service
|
||||
link is added. `TestOperatorSplitOverridesProxmoxNodeAgentLink` checks that
|
||||
the monitor and its re-ingested API seed retain the fold across all split
|
||||
shapes, then survive pin persistence and a repeated split.
|
||||
Relink consumers preserve the [unified fold-bookkeeping contract](unified-resources.md#reconciled-node-agent-relink-fold-bookkeeping).
|
||||
|
||||
Mock-link lifecycle validation drives the owning ingest/rebuild boundary
|
||||
after unlink and relink: read hydration intentionally reuses a registry
|
||||
|
||||
@@ -1335,10 +1335,6 @@ normalization. Existing backend severity admission and delivery queues remain
|
||||
unchanged. The notification API adapter round trips and WebhookConfig edit/save
|
||||
regression establish frontend control preservation, not provider delivery.
|
||||
|
||||
Formatting-only follow-up retains this warning-level contract. The production-component
|
||||
browser matrix was rerun after formatting at desktop and narrow widths, including
|
||||
all/critical/warning save/reload, cancel, and warning webhook creation.
|
||||
|
||||
### Resolution cancellation is occurrence-qualified
|
||||
|
||||
The monitor's delayed recovery path calls `CancelResolvedAlert` with the
|
||||
|
||||
@@ -2889,11 +2889,9 @@ is unavailable rather than showing zeros. Proofs:
|
||||
`frontend-modern/src/pages/__tests__/AIIntelligence.test.tsx` (card ordering),
|
||||
and the browser receipt in `frontend-modern/browser-verification.json`.
|
||||
|
||||
The explicit issue explanation journey is qualified separately from provider
|
||||
reasoning and real remediation in
|
||||
`docs/qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md`. The repeatable browser
|
||||
proof is `scripts/check-patrol-assistant-journey.mjs`. A passing scripted
|
||||
response does not establish a useful customer outcome or model qualification.
|
||||
Issue explanation follows the [customer-journey qualification boundary](../../../../qualification/PATROL_ASSISTANT_CUSTOMER_JOURNEY.md#real-outcome-qualification-still-required),
|
||||
which separates scripted interaction proof from provider reasoning, remediation
|
||||
and repeatable customer outcomes.
|
||||
|
||||
### Expired action continuity (2026-09-07)
|
||||
|
||||
|
||||
@@ -366,22 +366,8 @@ metric tracks at narrow width; this is readability, not a throughput claim.
|
||||
|
||||
### Bounded confidence/priority work in broadcast grouping — issue #2199
|
||||
|
||||
The general identity matcher retains every confidence, reason, ordering and
|
||||
review flag. Top-level grouping requests only its existing high-confidence
|
||||
floor (0.90), so hostname-only and IP-only peer sets are not built when no
|
||||
eligible composite signal exists. High-confidence results are identical to
|
||||
filtering the full general matcher; machine ID, UUID and hostname+MAC still
|
||||
keep their existing precedence. Host/IP fallback still requires exactly one
|
||||
strictly better-priority owner. Equal/worse-priority peers are discarded before
|
||||
allocating/sorting fallback candidates, and a best-priority group has no possible
|
||||
attachment target. No identity, ambiguity, count, group ID or explanation rule
|
||||
changes, and no cached output hides live transitions.
|
||||
|
||||
Independent pre-repair matching/grouping oracles, candidate-floor differential
|
||||
cases/fuzzing, a discarded-peer allocation bound, mixed grouping records and the
|
||||
complete existing identity/topology suites protect these constraints. The
|
||||
residual synthetic broadcast profile identified discarded matching/grouping as
|
||||
the dominant cost; it is not a profile of the reporter's installed agent fleet.
|
||||
Broadcast performance work preserves the [unified grouping semantics and allocation bounds](unified-resources.md#bounded-confidencepriority-work-in-broadcast-grouping--issue-2199),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Connected-dashboard snapshot ownership — issue #2199
|
||||
|
||||
@@ -3601,17 +3587,9 @@ nothing at all when workload rows are present.
|
||||
|
||||
### Per-tenant resource stores are released on offboarding and shutdown
|
||||
|
||||
`ResourceHandlers.getStore` opens a SQLite handle per org and caches it for the
|
||||
process lifetime. `CloseTenantStore` releases and evicts one org's handle and is
|
||||
called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
`CloseStores`, exposed as `Router.ShutdownResourceStores`, releases all of them.
|
||||
Without this an offboarded tenant kept its file descriptors and its
|
||||
`unified_resources.db-wal`/`-shm` files alive and its directory could not be
|
||||
fully removed. Closed stores are evicted from the cache so a later request opens
|
||||
a fresh handle rather than using a closed one
|
||||
(`TestResourceHandlers_CloseTenantStoreReleasesTheHandle`), and both entry points
|
||||
are idempotent and nil-safe
|
||||
(`TestResourceHandlers_CloseIsIdempotentAndNilSafe`).
|
||||
Tenant offboarding and process shutdown use the [API store-lifecycle contract](api-contracts.md#per-tenant-resource-stores-are-released-on-offboarding-and-shutdown),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Report-ack version echo adds no steady-state work
|
||||
|
||||
The `serverVersion` field on unified-agent report acks is a constant string
|
||||
|
||||
@@ -2759,26 +2759,20 @@ capability is not treated as the authorization boundary.
|
||||
and image normalization.
|
||||
### Licensed-feature adoption telemetry stays count-only
|
||||
|
||||
Schema v6 of the outbound usage payload adds nine licensed-feature adoption
|
||||
signals so Pro feature usage is measurable at all: `alert_ai_enabled`,
|
||||
`rbac_custom_roles`, `rbac_user_assignments`, `audit_logging_persistent`,
|
||||
`audit_events_30d`, `report_schedules`, `report_schedules_enabled`,
|
||||
`report_schedules_run_30d`, and `agent_profiles`. Every one is a count or a
|
||||
coarse boolean. Role names, permission sets, usernames, schedule names,
|
||||
delivery recipients, report scope and contents, profile names, and every audit
|
||||
event field (type, actor, target, outcome, detail) stay on the install.
|
||||
`audit_logging_persistent` reports only that a persistent store is active
|
||||
rather than console logging, and `audit_events_30d` is a retained-row count
|
||||
inside the same 30-day window used by the other counters, so it cannot be
|
||||
linked to one pseudonymous identifier indefinitely. Config-sourced signals are
|
||||
read in `applyLicensedFeatureConfigSnapshot`
|
||||
(`pkg/server/telemetry_licensed_features.go`); RBAC and audit are read behind
|
||||
the router in `Router.ApplyLicensedFeatureTelemetrySnapshot`
|
||||
(`internal/api/telemetry_licensed_features.go`). Both are disclosed in
|
||||
`docs/PRIVACY.md` and its `frontend-modern/public/docs/` copy, pinned by
|
||||
`TestAllTelemetryFieldsAreDisclosed`, and the counts are pinned by
|
||||
Licensed-feature adoption telemetry exports only the coarse counts and booleans
|
||||
declared in `internal/telemetry/licensed_feature_fields.go`. Role names,
|
||||
permission sets, usernames, schedule names, delivery recipients, report scope
|
||||
and contents, profile names, and every audit event field stay on the install.
|
||||
Config signals come from `pkg/server/telemetry_licensed_features.go`; RBAC counts
|
||||
come from `internal/api/telemetry_licensed_features.go`, and licensed audit-read
|
||||
activity follows the gated recorder below.
|
||||
|
||||
`docs/PRIVACY.md` and its shipped copy disclose the current fields.
|
||||
`TestAllTelemetryFieldsAreDisclosed`,
|
||||
`TestApplyLicensedFeatureConfigSnapshot_CountsScheduledReportingAndProfiles`
|
||||
and `TestApplyLicensedFeatureTelemetrySnapshot_CountsOnlyOperatorAuthoredRBAC`.
|
||||
and `TestApplyLicensedFeatureTelemetrySnapshot_CountsOnlyOperatorAuthoredRBAC`
|
||||
pin disclosure and count semantics. Audit-store presence and background write
|
||||
volume are not adoption signals.
|
||||
|
||||
### Telemetry RBAC reads never provision an RBAC store
|
||||
|
||||
@@ -2791,17 +2785,11 @@ side effect of a background read. A store reporting a migration failure is
|
||||
skipped rather than counted, so a degraded store cannot silently understate
|
||||
adoption. `TestTenantRBACProvider_PeekManagerDoesNotProvision` and
|
||||
`TestTenantRBACProvider_PeekManagerNilProviderIsSafe` in
|
||||
`internal/api/rbac_tenant_provider_test.go` pin both properties, and
|
||||
`TestApplyLicensedFeatureTelemetrySnapshot_DoesNotCreateRBACStores` pins it
|
||||
through the router boundary.
|
||||
`internal/api/rbac_tenant_provider_test.go` pin both properties.
|
||||
`ApplyLicensedFeatureTelemetrySnapshot` uses that cached-only read boundary.
|
||||
### Audit adoption telemetry counts gated reads, never store presence
|
||||
|
||||
Schema v7 replaced `audit_logging_persistent` and `audit_events_30d` with
|
||||
`audit_reads_30d`. The first two did not discriminate: `pkg/server` installs the
|
||||
SQLite audit logger on every install for defense in depth and gates only the
|
||||
read and export endpoints, so the boolean was true on every install that
|
||||
reported it and the event count measured background write volume, saturating
|
||||
the receiver clamp on unlicensed community installs. `audit_reads_30d` counts
|
||||
`audit_reads_30d` counts
|
||||
requests that cleared `RequireLicenseFeature(featureAuditLoggingValue, ...)` on
|
||||
an audit read or export surface, which requires a human action and so cannot
|
||||
settle into a constant. The recorder in
|
||||
@@ -2937,17 +2925,9 @@ because it looks like data in the fleet aggregate.
|
||||
names.
|
||||
### Per-tenant resource stores are released on offboarding and shutdown
|
||||
|
||||
`ResourceHandlers.getStore` opens a SQLite handle per org and caches it for the
|
||||
process lifetime. `CloseTenantStore` releases and evicts one org's handle and is
|
||||
called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
`CloseStores`, exposed as `Router.ShutdownResourceStores`, releases all of them.
|
||||
Without this an offboarded tenant kept its file descriptors and its
|
||||
`unified_resources.db-wal`/`-shm` files alive and its directory could not be
|
||||
fully removed. Closed stores are evicted from the cache so a later request opens
|
||||
a fresh handle rather than using a closed one
|
||||
(`TestResourceHandlers_CloseTenantStoreReleasesTheHandle`), and both entry points
|
||||
are idempotent and nil-safe
|
||||
(`TestResourceHandlers_CloseIsIdempotentAndNilSafe`).
|
||||
Tenant offboarding and process shutdown use the [API store-lifecycle contract](api-contracts.md#per-tenant-resource-stores-are-released-on-offboarding-and-shutdown),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Report-ack server versions cannot steer agents beyond one validated check
|
||||
|
||||
The unified-agent report ack's `serverVersion` echo gives acks a version
|
||||
@@ -3218,20 +3198,8 @@ a CSRF-checked `POST`. No authentication, scope or session rule changed.
|
||||
|
||||
### Node setup action v7 compatibility
|
||||
|
||||
Workflow consumers pin `actions/setup-node` to
|
||||
`820762786026740c76f36085b0efc47a31fe5020` (v7.0.0). The action manifest
|
||||
retains the Node 24 execution runtime, setup/cache-save entry points and existing
|
||||
inputs. Its internal ESM/toolkit upgrade does not change the requested Node 24
|
||||
application toolchain. Consumers do not supply `registry-url` or depend on the
|
||||
removed dummy `NODE_AUTH_TOKEN` export. Explicit npm lockfile caching for test
|
||||
jobs and disabled automatic package-manager caching for privileged release jobs
|
||||
remain unchanged; no permission, dispatch input or signing backend changes.
|
||||
|
||||
`test_setup_node_upgrade_preserves_consumer_contract` in the existing workflow
|
||||
trust suite verifies every consumer pin, absence of the affected auth assumptions,
|
||||
workflow trust controls and the retained native Windows command/lifecycle proof
|
||||
steps. Native Windows execution remains a hosted check, not a local Linux claim.
|
||||
This upgrade is independent of the grouped signing/Docker/Tailscale updates.
|
||||
Workflow consumers and their trust controls follow the [deployment toolchain contract](deployment-installability.md#node-setup-action-v7-compatibility),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Updates settings copy rename
|
||||
|
||||
|
||||
@@ -6084,17 +6084,8 @@ than drifting into "has ever used"
|
||||
|
||||
### Per-tenant resource stores are released on offboarding and shutdown
|
||||
|
||||
`ResourceHandlers.getStore` opens a SQLite handle per org and caches it for the
|
||||
process lifetime. `CloseTenantStore` releases and evicts one org's handle and is
|
||||
called from `Router.CleanupTenant` alongside the other per-tenant teardown;
|
||||
`CloseStores`, exposed as `Router.ShutdownResourceStores`, releases all of them.
|
||||
Without this an offboarded tenant kept its file descriptors and its
|
||||
`unified_resources.db-wal`/`-shm` files alive and its directory could not be
|
||||
fully removed. Closed stores are evicted from the cache so a later request opens
|
||||
a fresh handle rather than using a closed one
|
||||
(`TestResourceHandlers_CloseTenantStoreReleasesTheHandle`), and both entry points
|
||||
are idempotent and nil-safe
|
||||
(`TestResourceHandlers_CloseIsIdempotentAndNilSafe`).
|
||||
Tenant offboarding and process shutdown use the [API store-lifecycle contract](api-contracts.md#per-tenant-resource-stores-are-released-on-offboarding-and-shutdown),
|
||||
including its source controls and qualification limits.
|
||||
|
||||
### Report-ack version echo persists nothing
|
||||
|
||||
|
||||
@@ -2989,7 +2989,7 @@ application resource-provider or WebSocket lifecycle.
|
||||
become a per-row store pattern.
|
||||
Regression coverage:
|
||||
`TestSQLiteStoreActionAuditOriginRoundTrip`,
|
||||
`TestSQLiteActionAuditOriginOperationalRecordReader`, and the matching
|
||||
`TestActionAuditOriginReaderReturnsLatestTransition`, and the matching
|
||||
memory/batch reader tests in `internal/unifiedresources/store_test.go`.
|
||||
Incident next-step fallback follows the same canonical resource boundary:
|
||||
storage guidance is reserved for storage, physical-disk, network-share,
|
||||
|
||||
Reference in New Issue
Block a user