Phase 4: service store — manifest validation, install/remove, Store UI

- ServiceStoreManager: manifest allowlist (git.pic.ngo/roof/*), volume
  denylist, ACCEPT-only iptables rules, ${SERVICE_IP}-only dest_ip
- IP allocator: pool 172.20.0.20-254, skips CONTAINER_OFFSETS VIPs
- Compose overlay: docker-compose.services.yml auto-included via DCF
- Flask blueprint at /api/store: list, install, remove, refresh
- Store.jsx: full install/remove UI with spinners and toast notifications
- 95 new unit tests for ServiceStoreManager (all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-09 10:19:39 -04:00
parent f77d7fabcd
commit 0a21f22076
14 changed files with 2190 additions and 12 deletions
+13 -10
View File
@@ -17,6 +17,9 @@
# Detect docker compose command (v2 plugin preferred, fallback to v1 standalone)
DC := $(shell docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose")
# Full compose command: includes docker-compose.services.yml when it exists
DCF = $(DC) $(if $(wildcard docker-compose.services.yml),-f docker-compose.yml -f docker-compose.services.yml,-f docker-compose.yml)
# Default target
help:
@echo "Personal Internet Cell - Management Commands"
@@ -93,12 +96,12 @@ init-peers:
start:
@echo "Starting Personal Internet Cell..."
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full up -d --build
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full up -d --build
@echo "Services started. Check status with 'make status'"
stop:
@echo "Stopping Personal Internet Cell..."
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full down
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full down
@echo "Services stopped."
restart:
@@ -109,16 +112,16 @@ restart:
status:
@echo "Personal Internet Cell Status:"
@echo "================================"
$(DC) ps
$(DCF) ps
@echo ""
@echo "API Status:"
@curl -s http://localhost:3000/health || echo "API not responding"
logs:
$(DC) logs -f
$(DCF) logs -f
logs-%:
$(DC) logs -f $*
$(DCF) logs -f $*
shell-%:
docker exec -it cell-$* /bin/bash 2>/dev/null || docker exec -it cell-$* /bin/sh
@@ -135,12 +138,12 @@ update:
$(MAKE) setup; \
fi
@echo "Rebuilding and restarting services..."
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full up -d --build
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full up -d --build
@echo "Update complete. Run 'make status' to verify."
reinstall:
@echo "Reinstalling Personal Internet Cell from scratch..."
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full down -v 2>/dev/null || true
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full down -v 2>/dev/null || true
@sudo rm -rf config/ data/
@$(MAKE) setup
@$(MAKE) start
@@ -169,14 +172,14 @@ uninstall:
case "$$ans" in \
y|Y) \
echo "Stopping containers and removing images..."; \
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full down -v --rmi all 2>/dev/null || true; \
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full down -v --rmi all 2>/dev/null || true; \
echo "Deleting config/ and data/..."; \
sudo rm -rf config/ data/; \
echo "Uninstall complete. Git repo and scripts remain."; \
;; \
n|N|"") \
echo "Stopping and removing containers (keeping images and data)..."; \
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile full down 2>/dev/null || true; \
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile full down 2>/dev/null || true; \
echo "Done. Images, config/ and data/ are untouched. Run 'make start' to bring it back up."; \
;; \
*) \
@@ -208,7 +211,7 @@ build-webui:
start-core:
@echo "Starting core services (caddy, dns, wireguard, api, webui)..."
PUID=$$(id -u) PGID=$$(id -g) $(DC) --profile core up -d --build
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile core up -d --build
@echo "Core services started. Run 'make start' to also bring up optional services."
start-dns: