fix: cell-network name, install error surfacing, health history cleanup
Unit Tests / test (push) Successful in 11m22s

- docker-compose.services.yml: change external network name from
  pic_cell-network to cell-network so store-service compose files can find
  it.  The project-prefixed name was overriding the explicit name: cell-network
  fix in docker-compose.yml when both files were merged by make start.

- service_store.py: normalize docker compose stderr into the error key in
  the 400 response so the Store page shows the actual failure reason instead
  of the generic fallback message.

- app.py: skip health checks for email/calendar/files managers when those
  optional store services are not installed — prevents false Down alerts and
  unnecessary noise in health history.

- Logs.jsx: remove Email/Calendar/Files columns from the health history table;
  they are optional store services, not core builtins that should always appear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 14:28:46 -04:00
parent 7d5c5421f1
commit e87022dc55
4 changed files with 17 additions and 7 deletions
+9
View File
@@ -520,8 +520,17 @@ def perform_health_check():
'alerts': []
}
# email/calendar/files are optional store services — only check them when installed
_installed_store_ids = set(config_manager.get_installed_services())
_OPTIONAL_STORE_MANAGERS = frozenset({'email_manager', 'calendar_manager', 'file_manager'})
# Get health from each service
for service_name in service_bus.list_services():
if service_name in _OPTIONAL_STORE_MANAGERS:
# Map manager name to store service id (strip _manager suffix)
store_id = service_name.replace('_manager', '')
if store_id not in _installed_store_ids:
continue
try:
service = service_bus.get_service(service_name)
if hasattr(service, 'health_check'):
+4
View File
@@ -62,6 +62,10 @@ def install_service(service_id: str):
result = _ssm().install(service_id)
if result.get('ok'):
return jsonify(result)
# Normalize docker compose stderr into the error key so the frontend
# can display the actual failure reason rather than a generic message.
if not result.get('error') and result.get('stderr'):
result = {**result, 'error': result['stderr']}
return jsonify(result), 400
except Exception as e:
logger.error(f'install_service({service_id}): {e}')
+1 -1
View File
@@ -3,4 +3,4 @@ services: {}
networks:
cell-network:
external: true
name: pic_cell-network
name: cell-network
+1 -4
View File
@@ -392,7 +392,7 @@ function HealthHistoryTab() {
<table className="min-w-full text-sm">
<thead>
<tr className="bg-gray-100">
{['Timestamp','Network','WireGuard','Email','Calendar','Files','Routing','Vault','Alerts'].map(h => (
{['Timestamp','Network','WireGuard','Routing','Vault','Alerts'].map(h => (
<th key={h} className="px-2 py-1 text-left">{h}</th>
))}
</tr>
@@ -403,9 +403,6 @@ function HealthHistoryTab() {
<td className="px-2 py-1 font-mono text-xs">{h.timestamp}</td>
<td className="px-2 py-1"><SvcCol data={h.network} /></td>
<td className="px-2 py-1"><SvcCol data={h.wireguard} /></td>
<td className="px-2 py-1"><SvcCol data={h.email} /></td>
<td className="px-2 py-1"><SvcCol data={h.calendar} /></td>
<td className="px-2 py-1"><SvcCol data={h.files} /></td>
<td className="px-2 py-1"><SvcCol data={h.routing} /></td>
<td className="px-2 py-1"><SvcCol data={h.vault} /></td>
<td className="px-2 py-1">