Skip to content

fix(meshcore): filter empty channel slots + reconcile stale DB rows on sync#3040

Merged
Yeraze merged 4 commits into
mainfrom
fix/meshcore-empty-channel-slots
May 16, 2026
Merged

fix(meshcore): filter empty channel slots + reconcile stale DB rows on sync#3040
Yeraze merged 4 commits into
mainfrom
fix/meshcore-empty-channel-slots

Conversation

@Yeraze
Copy link
Copy Markdown
Owner

@Yeraze Yeraze commented May 16, 2026

Fixes the 40-channel issue reported after deploying the MeshCore channels feature: every freshly-connected Companion source was showing 38 empty placeholder rows alongside the real channels.

Root cause

MeshCore Companion firmware's `cmd_get_channel` does not error on an unused slot — it returns success with an empty name and a 16-byte all-zero secret. meshcore.js's `getChannels()` enumerates until the firmware errors, so it walks the whole slot table — MAX_CHANNELS, typically 40 on Companion builds. `syncChannelsFromDevice` was mirroring every slot it received into the `channels` DB table, including the 38 empty placeholders.

Fix

  • New helper `isConfiguredMeshCoreChannel(ch)` — a slot is configured iff it has a non-empty name OR a non-zero secret. The "OR" preserves the legit edge case where a user generated a real key but left the display name blank.
  • `syncChannelsFromDevice`:
    • Filters with that predicate before upserting → empty slots never reach the DB.
    • Reconciles after upserting: enumerates the existing DB rows for this source and deletes any whose idx isn't in the configured set. This covers both (a) one-time cleanup of legacy installs that already have the leaked rows and (b) reflecting an out-of-band delete via `meshcore-cli` on the next sync.

"Add channel" still works

Phase 3's `nextFreeIdx` walks 0..255 looking for the lowest unused index in the filtered channel list. After this fix, slot 1 (and 2, 3, … 39) are correctly recognised as free even though the firmware still reports them as empty in its 40-slot table. The PUT /api/channels/ route already accepts any idx 0..255 for MeshCore sources (phase 3).

Test plan

  • `npx vitest run` — 4959 PASS / 0 FAIL (+3 new cases over main)
  • `npm run build` — clean
  • `tsc --noEmit` — clean
  • Lint count unchanged from main (650)
  • Manual: redeploy, reconnect MeshCore source — DB should now show only configured channels; "Add channel" should suggest the lowest free slot.

New tests

`meshcoreManager.channels.test.ts` (+3):

  • `filters out empty/unconfigured slots (the MAX_CHANNELS leak)` — mixed configured + empty input → only the configured idx values get upserted.
  • `keeps a slot configured when the user blanks the name but keeps a real secret` — empty name with non-zero secret is preserved.
  • `reconciles: deletes DB rows for slots the device no longer treats as configured` — pre-existing stale rows get cleaned up on next sync.

🤖 Generated with Claude Code

…n sync

`syncChannelsFromDevice` was mirroring every slot meshcore.js reported,
including the all-zero placeholders the Companion firmware returns for
unconfigured slots. MeshCore Companion's `cmd_get_channel` does NOT
error on an unused idx — it returns success with an empty name and a
16-byte zero secret. meshcore.js's `getChannels()` enumerates until
the firmware errors, so the full slot table (MAX_CHANNELS, typically
40 on Companion builds) leaked into the channels view as 38 empty
"Channel N" placeholders alongside the user's real channels.

This patch:

- Adds `isConfiguredMeshCoreChannel(ch)` — a slot is configured iff
  it has a non-empty name OR a non-zero secret. That keeps the legit
  edge case where a user generated a real key but left the display
  name blank.
- `syncChannelsFromDevice` now filters with that predicate before
  upserting, so empty slots never reach the DB.
- After upserting the configured slots, it reconciles by enumerating
  the existing DB rows for this source and deleting any whose idx
  isn't in the configured set. This covers both (a) cleaning up
  legacy installs that already have the 38 leaked rows in their DB
  and (b) reflecting an out-of-band delete via meshcore-cli on the
  next sync.

Phase 3's "Add channel" UI is unaffected — `nextFreeIdx` walks 0..255
looking for the lowest unused slot in the *filtered* channel list, so
slot 1 stays available even after the firmware reports it as "empty"
in its 40-slot table.

Tests
- meshcoreManager.channels.test.ts: +3 cases — empty-slot filter,
  "name blank but real secret kept", and reconcile-deletes-stale-row.
- All previous tests still pass (existing fixtures had no empty slots
  and no pre-existing rows, so the reconcile path is a no-op for them).

Full suite: 4959 PASS / 0 FAIL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Claude finished @Yeraze's task —— View job


PR Review Complete ✅

This PR provides a solid fix for the MeshCore channel slots issue. Here's my comprehensive review:

Code Quality & Best Practices

Excellent implementation:

  • Well-documented helper function: isConfiguredMeshCoreChannel() on src/server/meshcoreManager.ts:54 has clear JSDoc explaining the business logic
  • Robust filtering logic: Uses both name and secret validation (hasName || hasSecret) to handle edge cases properly
  • Comprehensive reconciliation: syncChannelsFromDevice() now properly cleans up stale DB rows
  • Clean separation: Channel filtering logic is isolated and testable

Good practices followed:

  • Descriptive function/variable names (configuredIdxSet, isConfiguredMeshCoreChannel)
  • Proper error handling and logging
  • Maintains existing API contracts

Bug Prevention & Logic

Key fixes implemented correctly:

  • Primary issue resolved: Filters empty slots using isConfiguredMeshCoreChannel() before DB upsert
  • Edge case handled: Preserves channels with blank names but valid secrets (legitimate use case)
  • Reconciliation added: Cleans up existing empty slots and handles out-of-band deletions via meshcore-cli
  • Regex validation: hasSecret uses /[1-9a-f]/i.test() to detect non-zero hex strings

Potential edge cases considered:

  • Empty/null inputs handled gracefully
  • Maintains backward compatibility with existing channel configurations
  • Proper source scoping throughout

Performance Considerations

Efficient implementation:

  • Single device query: listChannels() called once, filtered in memory
  • Batch operations: Uses Set for O(1) lookups in reconciliation (configuredIdxSet)
  • Early filtering: Prevents unnecessary DB writes for empty slots
  • Minimal DB operations: Only deletes truly stale rows

No performance regressions:

  • Connect-time sync remains efficient
  • Channel CRUD operations maintain same performance profile

Security Assessment

No security concerns identified:

  • Input validation: Hex secret validation prevents malformed data
  • Proper scoping: All DB operations correctly use sourceId parameter
  • No injection risks: Uses parameterized queries via Drizzle ORM
  • Maintains data isolation: Source-specific channel management preserved

Test Coverage - Excellent

Comprehensive new tests in src/server/meshcoreManager.channels.test.ts:181-240:

  1. filters out empty/unconfigured slots - Tests the core fix with mixed configured/empty input
  2. keeps a slot configured when user blanks name but keeps real secret - Tests edge case preservation
  3. reconciles: deletes DB rows for slots the device no longer treats as configured - Tests cleanup of stale rows

Test quality:

  • Realistic scenarios: Tests actual firmware behavior (40-slot enumeration with empty slots)
  • Edge cases covered: Blank names with real secrets, reconciliation scenarios
  • Mocking strategy: Clean unit tests with proper stubbing
  • Assertions: Verify both positive and negative cases

📝 Minor Suggestions

  1. Consider bounds checking: The hex validation regex could be more explicit about 32-character length for 16-byte secrets
  2. Logging enhancement: Current debug log shows filtered count, could also show the specific indices that were filtered
  3. Documentation: Consider adding a code comment explaining why the "OR" logic is important for the edge case

🎯 Overall Assessment

Excellent PR - This is a well-researched, thoroughly tested fix that:

  • ✅ Solves the root cause (firmware behavior mismatch)
  • ✅ Handles edge cases gracefully
  • ✅ Includes proper reconciliation for existing installs
  • ✅ Maintains backward compatibility
  • ✅ Has comprehensive test coverage
  • ✅ Follows repository coding standards

Recommend approval - The fix is production-ready and the test coverage gives confidence in the implementation.


@github-actions
Copy link
Copy Markdown

System Test Results

MeshMonitor System Test Results

Test Run: 2026-05-15 22:01:42 EDT

Test Summary

Test Suite Result
Configuration Import ✅ PASSED
Quick Start Test ✅ PASSED
Security Test ✅ PASSED
V1 API Test ✅ PASSED
Reverse Proxy Test ✅ PASSED
Reverse Proxy + OIDC ✅ PASSED
Virtual Node CLI Test ✅ PASSED
Backup & Restore Test ✅ PASSED
Database Migration Test ✅ PASSED
DB Backing Consistency ✅ PASSED
API Exercise (3 DBs) ✅ PASSED

✅ Overall Result: PASSED

All deployment configurations are working correctly!

Test Details

Configuration Import:

  • Tests configuration import and device reboot cycle
  • Verifies channel roles, PSKs, and LoRa configuration
  • Note: Channel name verification skipped due to architectural limitation

Quick Start Test:

  • Zero-config deployment (no SESSION_SECRET or COOKIE_SECURE required)
  • HTTP access without HSTS
  • Auto-generated admin user with default credentials
  • Session cookies work over HTTP
  • Meshtastic node connection and message exchange verified

Security Test:

  • Verifies Node IP address hidden from anonymous users in API responses
  • Verifies MQTT configuration hidden from anonymous users
  • Verifies Node IP address visible to authenticated users
  • Verifies MQTT configuration visible to authenticated users
  • Verifies protected endpoints require authentication

V1 API Test:

  • Tests v1 REST API endpoints with Bearer token authentication
  • Verifies Bearer token requests bypass CSRF protection
  • Verifies POST/PUT/DELETE work without CSRF token when using Bearer auth
  • Verifies session-based requests still require CSRF token

Reverse Proxy Test:

  • Production deployment with COOKIE_SECURE=true
  • HTTPS-ready configuration
  • Trust proxy enabled for reverse proxy compatibility
  • CORS configured for HTTPS domain
  • Meshtastic node connection and message exchange verified

Reverse Proxy + OIDC Test:

  • OIDC authentication integration
  • Mock OIDC provider health checks
  • Authorization flow and session creation
  • Hybrid mode (OIDC + local auth)
  • Meshtastic node connection verified

Virtual Node CLI Test:

  • Virtual Node Server enabled on TCP port 4404
  • Meshtastic Python client successfully connects
  • Node data download and synchronization verified
  • Test message sent on gauntlet channel (index 3)
  • Message delivery confirmed via Web UI API
  • Virtual Node Server connection logging verified

Backup & Restore Test:

  • System backup created from running dev container
  • New container spun up with RESTORE_FROM_BACKUP env var
  • Data integrity verified (node count, message count, settings)
  • Restore event logged in audit log
  • Dev container unaffected by restore test

Database Migration Test:

  • SQLite to PostgreSQL migration verified
  • SQLite to MySQL migration verified
  • Data integrity confirmed for both target databases
  • Row counts match between source and target

DB Backing Consistency Test:

  • SQLite, PostgreSQL, and MySQL backends tested with same device
  • Node counts within ±10 across all three backends
  • Favorite counts identical across all backends
  • Key station verified as favorite on all backends

The phase-3 routes were calling `resolveSourceManager(sourceId)` for
MeshCore writes. That helper only knows about the Meshtastic
`sourceManagerRegistry` and silently falls back to the global
`meshtasticManager` singleton on a miss. The Meshtastic singleton has
no `setChannel` / `deleteChannel` methods, so the unsafe cast in the
route surfaced as a runtime TypeError ("mcManager.setChannel is not a
function") when the user clicked Save on the new Add-channel UI.

MeshCore managers live in their own `meshcoreManagerRegistry`
(src/server/meshcoreRegistry.ts), separate from the Meshtastic one.
Both PUT /api/channels/:id and DELETE /api/channels/:id now pull
their MeshCore manager from that registry. If the manager isn't
present (source not connected) the route returns 503 with a clear
message instead of silently invoking the Meshtastic fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

Phase 2 of the MeshCore channels feature tags every locally-sent
channel message with `toPublicKey = 'channel-${idx}'` so the per-
channel filter in MeshCoreChannelsView can group sent messages back
into the right tab. Those synthetic keys are NOT real DM peers, but
`MeshCoreDirectMessagesView` was harvesting every distinct
`toPublicKey` and listing them in the sidebar — so the DMs view was
showing fake "channel-0", "channel-1" peers alongside real contacts.

Adds an `isChannelPseudoKey` predicate that rejects keys starting
with `channel-`, and applies it in both `dmPeers` (sidebar list) and
the per-conversation `filtered` projection. The contacts loop is
also guarded so a stray channel-shaped contact key wouldn't slip
through.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Claude finished @Yeraze's task —— View job


PR Review: MeshCore Empty Channel Slots Fix

Reviewing this PR that addresses the 40-channel issue where MeshCore sources were showing empty placeholder rows.

Review Checklist

  • Analyze changed files and implementation approach
  • Review filtering logic and edge case handling
  • Evaluate test coverage and quality
  • Check for potential bugs or security concerns
  • Assess performance implications
  • Provide final recommendations

Excellent PR - Comprehensive Fix for MeshCore Channel Issue

This PR provides a well-engineered solution to the 40-channel leak problem. Here's my detailed analysis:

🔧 Implementation Quality - Outstanding

Clean Architecture (src/server/meshcoreManager.ts:54-58):

  • Well-documented helper function: isConfiguredMeshCoreChannel() with clear JSDoc explaining the business logic
  • Smart filtering logic: Uses both name and secret validation (hasName || hasSecret) to handle the edge case where users leave names blank but have valid secrets
  • Robust regex validation: /[1-9a-f]/i.test() properly detects non-zero hex strings

Excellent Reconciliation Logic (src/server/meshcoreManager.ts:688-702):

  • Set-based cleanup: Uses configuredIdxSet for O(1) lookups during reconciliation
  • Comprehensive cleanup: Handles both legacy empty slots AND out-of-band deletions via meshcore-cli
  • Clear logging: Debug output shows filtered vs configured counts for troubleshooting

🛡️ Edge Case Handling - Comprehensive

Primary Issue Resolved: Filters empty slots using hasName || hasSecret before DB upsert
Edge Cases Covered:

  • ✅ Empty names with valid secrets preserved (legitimate use case)
  • ✅ Graceful handling of null/empty inputs
  • ✅ Reconciliation cleans up existing stale rows from previous installs
  • ✅ Out-of-band deletions via meshcore-cli reflected on next sync

Channel Pseudo-Key Filtering (src/components/MeshCore/MeshCoreDirectMessagesView.tsx:84-85):

  • Prevents synthetic channel-N keys from appearing in DM view
  • Clean separation between channel and DM message handling

⚡ Performance Considerations - Efficient

Optimal Data Flow:

  • Single device query: listChannels() called once, filtered in memory
  • Batch operations: Set-based lookups for reconciliation (O(1) vs O(n))
  • Early filtering: Prevents unnecessary DB writes for 38+ empty slots
  • Minimal DB operations: Only deletes truly stale rows, not entire table

No Performance Regressions: Connect-time sync remains efficient, channel CRUD maintains same performance profile

🔒 Security Assessment - Clean

No Security Concerns:

  • Input validation: Hex secret validation prevents malformed data
  • Proper scoping: All DB operations correctly use sourceId parameter
  • No injection risks: Uses parameterized queries via Drizzle ORM
  • Data isolation: Source-specific channel management preserved

🧪 Test Coverage - Exceptional

Three comprehensive test cases (src/server/meshcoreManager.channels.test.ts:181-240):

  1. filters out empty/unconfigured slots: Tests the core fix with realistic 40-slot firmware behavior
  2. keeps a slot configured when user blanks name but keeps real secret: Tests critical edge case preservation
  3. reconciles: deletes DB rows for slots the device no longer treats as configured: Tests cleanup of legacy data

Test Quality Highlights:

  • Realistic scenarios: Mimics actual Companion firmware behavior (40 slots with empties)
  • Edge case coverage: Validates the OR logic for name vs secret
  • Clean mocking: Unit tests with proper stubbing, clear assertions
  • Both positive and negative cases: Verifies what gets included AND excluded

📋 Minor Enhancement Opportunities

  1. Hex validation refinement: Consider explicit 32-character length validation for 16-byte secrets
  2. Enhanced logging: Could log specific indices that were filtered out for troubleshooting
  3. Bounds validation: The current regex could be more explicit about exact secret length expectations

🎯 Overall Assessment

This is production-ready code that:

  • Solves root cause: Addresses firmware behavior mismatch correctly
  • Handles edge cases: Preserves legitimate configurations while filtering noise
  • Includes reconciliation: Cleans up existing problematic installs
  • Maintains compatibility: No breaking changes to existing functionality
  • Comprehensive testing: High-quality test coverage with realistic scenarios
  • Follows conventions: Adheres to repository patterns and coding standards

Recommendation: Approve and merge. This fix is well-researched, thoroughly tested, and addresses both the immediate issue and long-term data consistency.


@github-actions
Copy link
Copy Markdown

System Test Results

MeshMonitor System Test Results

Test Run: 2026-05-15 23:09:11 EDT

Test Summary

Test Suite Result
Configuration Import ✅ PASSED
Quick Start Test ✅ PASSED
Security Test ✅ PASSED
V1 API Test ✅ PASSED
Reverse Proxy Test ❌ FAILED
Reverse Proxy + OIDC ✅ PASSED
Virtual Node CLI Test ✅ PASSED
Backup & Restore Test ✅ PASSED
Database Migration Test ✅ PASSED
DB Backing Consistency ✅ PASSED
API Exercise (3 DBs) ✅ PASSED

❌ Overall Result: FAILED

Some tests failed. Please review the failures above and fix before creating/updating PR.

Failed Tests

  • Reverse Proxy Test: Production HTTPS deployment test failed

The local node was showing up as a DM peer in the MeshCore DMs view
sidebar — usually because MeshCore seeds the local node's own pubkey
into the contacts list, and the "Always include all contacts so the
user can start a new DM" loop in `dmPeers` was happily adding it. DMing
yourself is meaningless.

After computing the peer set, drop any entry whose key matches the
locally-connected node's pubkey (using the existing keysMatch helper
so a prefix-only match — the inbound `pubkey_prefix` case — is caught
too).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Claude finished @Yeraze's task —— View job


PR Review: MeshCore Empty Channel Slots Fix

Reviewing this PR that addresses the 40-channel issue where MeshCore sources were showing empty placeholder rows.

Review Checklist

  • Analyze changed files and implementation approach
  • Review filtering logic and edge case handling
  • Evaluate test coverage and quality
  • Check for potential bugs or security concerns
  • Assess performance implications
  • Provide final recommendations

Excellent PR - Comprehensive Fix for MeshCore Channel Issue

This PR provides a well-engineered solution to the 40-channel leak problem. Here's my detailed analysis:

🔧 Implementation Quality - Outstanding

Clean Architecture (src/server/meshcoreManager.ts:54-58):

  • Well-documented helper function: isConfiguredMeshCoreChannel() with clear JSDoc explaining the business logic
  • Smart filtering logic: Uses both name and secret validation (hasName || hasSecret) to handle the edge case where users leave names blank but have valid secrets
  • Robust regex validation: /[1-9a-f]/i.test() properly detects non-zero hex strings

Excellent Reconciliation Logic (src/server/meshcoreManager.ts:688-702):

  • Set-based cleanup: Uses configuredIdxSet for O(1) lookups during reconciliation
  • Comprehensive cleanup: Handles both legacy empty slots AND out-of-band deletions via meshcore-cli
  • Clear logging: Debug output shows filtered vs configured counts for troubleshooting

🛡️ Edge Case Handling - Comprehensive

Primary Issue Resolved: Filters empty slots using hasName || hasSecret before DB upsert
Edge Cases Covered:

  • ✅ Empty names with valid secrets preserved (legitimate use case)
  • ✅ Graceful handling of null/empty inputs
  • ✅ Reconciliation cleans up existing stale rows from previous installs
  • ✅ Out-of-band deletions via meshcore-cli reflected on next sync

Channel Pseudo-Key Filtering (src/components/MeshCore/MeshCoreDirectMessagesView.tsx:84-85):

  • Prevents synthetic channel-N keys from appearing in DM view
  • Clean separation between channel and DM message handling

⚡ Performance Considerations - Efficient

Optimal Data Flow:

  • Single device query: listChannels() called once, filtered in memory
  • Batch operations: Set-based lookups for reconciliation (O(1) vs O(n))
  • Early filtering: Prevents unnecessary DB writes for 38+ empty slots
  • Minimal DB operations: Only deletes truly stale rows, not entire table

No Performance Regressions: Connect-time sync remains efficient, channel CRUD maintains same performance profile

🔒 Security Assessment - Clean

No Security Concerns:

  • Input validation: Hex secret validation prevents malformed data
  • Proper scoping: All DB operations correctly use sourceId parameter
  • No injection risks: Uses parameterized queries via Drizzle ORM
  • Data isolation: Source-specific channel management preserved

🧪 Test Coverage - Exceptional

Three comprehensive test cases (src/server/meshcoreManager.channels.test.ts:181-240):

  1. filters out empty/unconfigured slots: Tests the core fix with realistic 40-slot firmware behavior
  2. keeps a slot configured when user blanks name but keeps real secret: Tests critical edge case preservation
  3. reconciles: deletes DB rows for slots the device no longer treats as configured: Tests cleanup of legacy data

Test Quality Highlights:

  • Realistic scenarios: Mimics actual Companion firmware behavior (40 slots with empties)
  • Edge case coverage: Validates the OR logic for name vs secret
  • Clean mocking: Unit tests with proper stubbing, clear assertions
  • Both positive and negative cases: Verifies what gets included AND excluded

📋 Minor Enhancement Opportunities

  1. Hex validation refinement: Consider explicit 32-character length validation for 16-byte secrets
  2. Enhanced logging: Could log specific indices that were filtered out for troubleshooting
  3. Bounds validation: The current regex could be more explicit about exact secret length expectations

🎯 Overall Assessment

This is production-ready code that:

  • Solves root cause: Addresses firmware behavior mismatch correctly
  • Handles edge cases: Preserves legitimate configurations while filtering noise
  • Includes reconciliation: Cleans up existing problematic installs
  • Maintains compatibility: No breaking changes to existing functionality
  • Comprehensive testing: High-quality test coverage with realistic scenarios
  • Follows conventions: Adheres to repository patterns and coding standards

Recommendation: Approve and merge. This fix is well-researched, thoroughly tested, and addresses both the immediate issue and long-term data consistency.


@Yeraze Yeraze merged commit 5a4cd36 into main May 16, 2026
16 of 17 checks passed
Yeraze added a commit that referenced this pull request May 16, 2026
Bumps the version across all five canonical files (package.json,
package-lock.json, helm/meshmonitor/Chart.yaml,
desktop/src-tauri/tauri.conf.json, desktop/package.json) for the
4.5.2 release.

Headline: MeshCore channel support is the major feature in this
release.

- Phase 1 (#3034) — MeshCoreManager exposes listChannels / setChannel
  / deleteChannel and mirrors the device's channel list into the
  shared `channels` table on connect.
- Phase 2 (#3038) — MeshCoreChannelsView renders one tab per channel
  from the synced list; the send path is channel-idx aware.
- Phase 3 (#3039) — Configuration UI adds, edits, regenerates the
  secret of, and deletes channels on the device; PUT/DELETE
  /api/channels/:id route writes through to MeshCore via the correct
  registry.
- Polish (#3040) — empty-slot filter (the MAX_CHANNELS=40 leak),
  DB reconcile for stale empty rows, DM-view filters out channel
  pseudo-pubkeys and the local node from the peer sidebar.

Also includes the per-node position-precision fix (#3033) from this
release window.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

System Test Results

MeshMonitor System Test Results

Test Run: 2026-05-15 23:43:04 EDT

Test Summary

Test Suite Result
Configuration Import ✅ PASSED
Quick Start Test ✅ PASSED
Security Test ✅ PASSED
V1 API Test ✅ PASSED
Reverse Proxy Test ❌ FAILED
Reverse Proxy + OIDC ✅ PASSED
Virtual Node CLI Test ✅ PASSED
Backup & Restore Test ✅ PASSED
Database Migration Test ✅ PASSED
DB Backing Consistency ❌ FAILED
API Exercise (3 DBs) ❌ FAILED

❌ Overall Result: FAILED

Some tests failed. Please review the failures above and fix before creating/updating PR.

Failed Tests

  • Reverse Proxy Test: Production HTTPS deployment test failed
  • DB Backing Consistency: Database backing consistency test failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant