You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(db): fail-closed withSourceScope + ALL_SOURCES sentinel (#3962 Task 1.1 WP-A)
Add ALL_SOURCES unique symbol and SourceScope type. Rewrite withSourceScope
to throw on missing/empty sourceId (fail-closed) and return undefined (no
WHERE clause) for ALL_SOURCES. Export from barrel index.ts.
Tests: unit Probe subclass tests all 5 cases; perSource integration test
seeds two sources and verifies isolation, ALL_SOURCES cross-source, and
fail-closed throw. @ts-expect-error proves omission is a Tier-2 compile error.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* feat(db): widen repo signatures to SourceScope, fix external omit-sites (#3962 WP-B)
Tier-1: widen sourceId params across 7 repos (channels, messages, neighbors,
nodes, notifications, telemetry, traceroutes) from string to SourceScope so
ALL_SOURCES threads through cleanly. Legacy *Sqlite sync twins updated to
handle ALL_SOURCES (treat as no-filter) in hand-rolled patterns.
Tier-2: make leading-param aggregates required (getAllNodes, getNodeCount,
getActiveNodeCount, getAllChannels, getChannelCount, getMessageCount,
getAllNeighborInfo) so omit-sites are compile errors.
External call sites (#1-#14 legit-cross-source): pass ALL_SOURCES + comment
in purgeRoutes, systemRoutes, webSocketService, mqttBridgeManager,
database.ts init cache warm-up, exportData, getAllNodesAsync, getAllNeighborInfo
facade, deviceBackupService, meshtasticManager, dbNodeMapper, autoDelete,
automation/meshNodeData, analysisRoutes, v1 routes, channelRoutes, server.ts.
Bug fix (#15): server.ts getNodeCount in /nodes/refresh now passes
refreshSourceId (matching the adjacent getChannelCount) instead of leaking
all-source count.
CLI fix: test-postgres.ts passes ALL_SOURCES to getAllNodes/getNodeCount/
getMessageCount.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* fix(task-1.1): normalize undefined→ALL_SOURCES in Tier-1 method bodies
Tier-1 optional sourceId methods (sourceId?: SourceScope) were passing
undefined directly to withSourceScope, which now throws fail-closed.
Fix: add ?? ALL_SOURCES before each withSourceScope call so omitting
sourceId silently falls back to cross-source behavior (preserving
backward compat for callers like purgeAllNodesAsync that call without
an explicit scope).
Also:
- Fix existing tests for Tier-2 required methods (getAllNodes,
getNodeCount, getAllChannels, getChannelCount, getAllNeighborInfo)
to pass ALL_SOURCES explicitly — these tests verify cross-source
counting/retrieval which is intentional.
- Add ALL_SOURCES: Symbol to the database.service.test.ts mock factory
so vitest does not raise "no such export" when database.ts imports it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* fix(task-1.1): revert ?? ALL_SOURCES from Tier-2 required method bodies
Tier-2 methods (getAllNodes, getNodeCount, getChannelCount, etc.) have
sourceId: SourceScope (required, no ?) — they must still throw fail-closed
when undefined reaches them via 'as any' or a programming error. The
previous commit incorrectly applied ?? ALL_SOURCES to these too, which
caused the WP-A perSource tests to resolve instead of reject.
Only Tier-1 optional methods (sourceId?: SourceScope) get ?? ALL_SOURCES
in their bodies so that callers like purgeAllNodesAsync that omit the
argument preserve the old all-source semantics without crashing.
Full Vitest suite: success=true, 0 failed, 0 suitesFailed, 8696 tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* fix(task-1.1): restore fail-closed semantics — revert repo-body defaulting, fix every omit-site explicitly
Orchestrator review found that commit 75ea1f7 defeated the fail-closed
mechanism by adding `sourceId ?? ALL_SOURCES` inside the 7 repository
files: an omitted sourceId silently became a cross-source query again.
This commit restores the spec's design:
1. All 48 internal `withSourceScope(table, sourceId ?? ALL_SOURCES)`
lines in the repos reverted to plain `withSourceScope(table, sourceId)`
so omission propagates to the helper and THROWS at runtime.
2. Every caller surfaced by the throw (full suite + a manual sweep of all
guarded Tier-1 methods' production callers) fixed explicitly at the
call site:
- Real sourceId where one is in scope (leak fixes):
* database.ts deleteNode() -> deleteNeighborInfoInvolvingNode now
scoped to the node's source (matches deleteNodeAsync)
* meshtasticManager pending-DM check -> this.sourceId
- Explicit ALL_SOURCES + comment where cross-source is by design:
* legacy/deprecated facades in database.ts with no sourceId param
(getMessagesAsync, getMessagesByChannel, getTelemetryByNodeAsync,
purgeNodeTraceroutes/Telemetry, clearNeighborInfoForNode, etc.)
* getRecentEstimatedPositions (est-pos pooled per #3271)
* purgeAllNodesAsync global purge -> deleteAllRouteSegments
* optional-source routes (server.ts unread/poll/active-nodes,
v1/*, tracerouteRoutes, routeSegmentRoutes, embedPublicRoutes,
telemetryRoutes) via `x ?? ALL_SOURCES`
3. Facade signatures that now carry the sentinel widened to SourceScope
(getAllTraceroutes, getUnreadCountsByChannelAsync,
getBatchUnreadDMCountsAsync); their raw-SQL SQLite twins normalize the
symbol back to undefined so it is never bound as a query parameter.
Same hazard fixed in the hand-rolled getNodeTelemetryTypes filter.
4. Test call sites updated to pass ALL_SOURCES (or a concrete id)
explicitly; two mock-assertion tests now expect the sentinel.
Gate: tsc clean; full Vitest suite success:true, 0 failed, 0 suites
failed (8696 tests); §6 grep sweep clean (remaining bare calls are
MeshCore manager methods outside the guarded hierarchy).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* test(db): pass ALL_SOURCES in PG-gated averaged-telemetry test (fail-closed compliance)
The PostgreSQL-only test path passed undefined sourceId, which now throws
under the fail-closed guard; it only runs in CI where PG is available.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
* ci: raise Quick Tests timeout to 25 min — suite outgrew the 15-min cap again (#3385 redux)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AphLfgUJWaFNAgU5UXdJ4n
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments