Add remote instance management with mTLS agent and phone-home registration

Enables the CCP to manage CML instances on remote servers via a lightweight
HTTP agent. Key components:

- ExecutionDriver abstraction (local-driver.ts / remote-driver.ts) routes
  operations to local Docker or remote agent transparently
- Remote agent package (agent/) with mTLS authentication, Docker Compose
  operations, file management, backup/upgrade delegation
- Certificate service using openssl CLI for CA management and cert issuance
- Phone-home registration: remote agents register via invite code, CCP admin
  approves, agent receives mTLS cert bundle automatically
- config.sh integration with configure_control_panel() section
- ccp-agent Docker Compose service (profile-gated)
- Frontend: AgentRegistrationsPage, InviteCodesPage, Remote Agents sidebar menu
- Security hardened: cert bundle wiped after delivery, shell injection prevention
  via execFile, command allowlist with metachar rejection, rate-limited public
  endpoints, auto-populated fingerprint pinning

Also wires ENABLE_SOCIAL/PEOPLE/ANALYTICS through env.ts, seed.ts, and
docker-compose env passthrough (from previous session).

Bunker Admin
This commit is contained in:
2026-04-07 15:24:33 -06:00
parent d17e197a1b
commit 38ccaa8a5b
52 changed files with 4939 additions and 108 deletions

View File

@@ -1025,7 +1025,7 @@ model MapSettings {
qrCode2Label String?
qrCode3Url String?
qrCode3Label String?
publicMapEnabled Boolean @default(true)
publicMapEnabled Boolean @default(false)
publicShowLocations Boolean @default(true)
publicShowSupportLevels Boolean @default(true)
publicShowCuts Boolean @default(true)
@@ -1087,7 +1087,7 @@ model SiteSettings {
// Feature toggles
enableInfluence Boolean @default(true)
enableMap Boolean @default(true)
enableMap Boolean @default(false)
enableNewsletter Boolean @default(true)
enableLandingPages Boolean @default(true)
enableMediaFeatures Boolean @default(true) @map("enable_media_features")

View File

@@ -102,6 +102,17 @@ async function main() {
smtpActiveProvider: isMailhog ? 'mailhog' : 'production',
emailTestMode: env.EMAIL_TEST_MODE === 'true',
testEmailRecipient: env.TEST_EMAIL_RECIPIENT,
// Feature flags from .env (DB authoritative once admin saves settings)
enableMediaFeatures: env.ENABLE_MEDIA_FEATURES !== 'false',
enableChat: env.ENABLE_CHAT === 'true',
enableMeet: env.ENABLE_MEET === 'true',
enableSms: env.ENABLE_SMS === 'true',
enablePayments: env.ENABLE_PAYMENTS === 'true',
enableSocial: env.ENABLE_SOCIAL === 'true',
enablePeople: env.ENABLE_PEOPLE === 'true',
enableAnalytics: env.ENABLE_ANALYTICS === 'true',
enableEvents: env.GANCIO_SYNC_ENABLED === 'true',
enableNewsletter: env.LISTMONK_SYNC_ENABLED === 'true',
navConfig: {
items: [
{ id: 'home', label: 'Home', path: '/', icon: 'HomeOutlined', enabled: true, order: 0, type: 'builtin', external: true },

View File

@@ -207,6 +207,11 @@ const envSchema = z.object({
// SMS Campaigns (Termux Android bridge)
ENABLE_SMS: z.string().default('false'),
// Social, People, Analytics (initial defaults; DB authoritative once admin saves)
ENABLE_SOCIAL: z.string().default('false'),
ENABLE_PEOPLE: z.string().default('false'),
ENABLE_ANALYTICS: z.string().default('false'),
TERMUX_API_URL: z.string().default('http://10.0.0.193:5001'),
TERMUX_API_KEY: z.string().default(''),
SMS_DELAY_BETWEEN_MS: z.coerce.number().default(3000),