28 Commits

Author SHA1 Message Date
6e01d580b2 install: persist generated admin password + Pangolin credential smoke test
config.sh: two more pieces of first-time-user UX polish surfaced
during fresh-install testing.

- When configure_admin() auto-generates the admin password (no
  --admin-password given), also write a locked-down
  data/admin-credentials.txt (mode 0600) containing email + password
  + timestamp. Users who pipe config.sh output or miss the single
  stdout print no longer lose the password forever. The file is only
  written on the auto-generate path — explicit --admin-password
  leaves it alone.

- configure_pangolin() now smoke-tests --pangolin-api-key +
  --pangolin-org-id against /org/:id/resources before writing them to
  .env. Catches typos, revoked keys, or wrong org IDs while recovery
  is cheap (rather than later, when Newt fails to connect and
  symptoms look like a tunnel outage). New flag:
  --skip-pangolin-check for offline bootstrap scenarios.

Bunker Admin
2026-04-16 12:59:10 -06:00
dbbff8adc9 install: host-port preflight in install.sh + surface verify/teardown tools
scripts/install.sh: inline ss -Htln check before tarball download so
cockpit-on-9090 (and friends) fail early instead of breaking the stack
mid-compose-up. Culprit-specific hints for :9090 (cockpit.socket) and
:80/:443. Gracefully skipped if iproute2 not installed.

config.sh: Next Steps in release mode now surfaces
  - test-deployment.sh --wait 60 (verify step)
  - validate-env.sh (re-check ports/.env)
  - pangolin-teardown.sh (clean reset before reinstall)
Also documents the ~3min first-pull + ~90s stabilization window so
brief "unhealthy" statuses don't panic new users.

Bunker Admin
2026-04-16 12:56:55 -06:00
f9d566bd84 install: preflight + teardown tooling + CCP tunnel cleanup on delete
Fixes surfaced by three rounds of fresh-install testing on marcelle:

- config.sh: add host-port preflight check (ss -tln) to catch
  cockpit-on-9090 style collisions before compose up; add
  --skip-port-check escape hatch; add --install-watcher /
  --no-install-watcher / --install-backup-timer /
  --no-install-backup-timer flags; -y --enable-all now installs both
  systemd units by default (previously silently skipped); print
  resolved admin email in Configuration Complete block.

- scripts/validate-env.sh: new section 5b "Host Port Availability"
  using ss-based detection, with process-name surfacing when run as
  root.

- scripts/pangolin-teardown.sh: new wrapper. Reads credentials from
  .env or takes --api-url/--api-key/--org-id flags. Dry-run by
  default; --yes to execute. Deletes resources before sites (avoids
  orphans). --keep-site-ids for safety.

- scripts/build-release.sh: include validate-env.sh and
  pangolin-teardown.sh in release tarball whitelist.

- CCP instances.service.ts: deleteInstance() now calls
  teardownTunnel() before composeDown when pangolinSiteId is set.
  Previously an admin clicking "Delete Instance" orphaned the
  Pangolin site + all its resources. Best-effort with try/catch
  matching the existing Docker-cleanup tolerance pattern.

- CLAUDE.md: sync drift — 44 → 50 migrations, 186 → 192 models,
  40 → 44 modules.

Bunker Admin
2026-04-16 12:50:48 -06:00
26ec925d9b CCP restore/tunnel/upgrade + upgrade.sh release-mode fixes + volunteer dashboard polish
- Add instance restore model, routes, and agent backup/restore endpoints
- Add Pangolin tunnel service (subdomain prefix, teardown action, CCP client)
- Add slug mutex for concurrent operation safety in agent
- Expand upgrade service with remote driver orchestration
- Fix upgrade.sh to properly handle release-mode installs (no git operations)
- Add CCP registration flags to config.sh (--ccp-url, --ccp-invite-code, --ccp-agent-url)
- Auto-detect JVB advertise IP in non-interactive mode
- Polish volunteer dashboard ActionStepsList with highlighted step component
- Add ticketed event description field + volunteer dashboard query refinements

Bunker Admin
2026-04-12 11:09:46 -06:00
ca446136a1 Fix set -e crash in pangolin_create_resources arithmetic
((created++)) returns exit code 1 when created=0 (post-increment
evaluates to 0, which is falsy), killing the script under set -e.
Use x=$((x + 1)) instead.

Bunker Admin
2026-04-09 13:03:12 -06:00
0510420772 Fix pangolin_create_site blocking on read in non-interactive mode
The site name prompt used read -rp which blocks when stdin is piped.
Now uses default name automatically when NON_INTERACTIVE=true.

Bunker Admin
2026-04-09 12:57:54 -06:00
36b709b911 Automate Gitea init, NocoDB auto sign-in, and fix prod compose
- Add scripts/gitea-init.sh: runs migrations + creates admin user on
  first boot, replacing the manual installation wizard
- Set GITEA__security__INSTALL_LOCK=true in both compose files
- Add NocoDB auth bridge (nginx) + /api/services/nocodb-auth proxy
  endpoint so the admin iframe auto-authenticates
- Update NocoDBPage.tsx to fetch token and use auth bridge flow
- Fix docker-compose.prod.yml missing Gitea env vars for API container
  (GITEA_URL, GITEA_API_TOKEN, GITEA_ADMIN_PASSWORD, etc.)
- Pass NC_ADMIN_EMAIL/PASSWORD to API for NocoDB auth proxy
- Increase Gitea auto-setup retries from 3 to 6 with admin auth check
- Update config.sh non-interactive mode to set GITEA_ADMIN_USER
- Include gitea-init.sh in release tarball (build-release.sh)

Bunker Admin
2026-04-09 12:49:33 -06:00
f8c8a939d7 Add full non-interactive mode to config.sh
New CLI flags for scripted deployments:
  --smtp-host/port/user/pass   Production SMTP configuration
  --pangolin-api-url/key/org-id/endpoint/site  Full Pangolin tunnel setup
  --mapbox-key                 Mapbox API key
  --maxmind-account-id/license-key  MaxMind GeoIP credentials

With --pangolin-site=new, config.sh creates a Pangolin site, fetches
Newt credentials, and creates all resources+targets automatically.
With --pangolin-site=existing, it connects to the first available site.

Bunker Admin
2026-04-09 12:08:05 -06:00
bca4cb8227 Fix Pangolin site creation: omit address field from payload
The clientAddress from pickSiteDefaults lacks CIDR notation and gets
rejected by the Pangolin API. Omitting it lets Pangolin auto-assign.

Bunker Admin
2026-04-09 11:58:14 -06:00
849dea7ce2 Fix config.sh Pangolin setup and MongoDB init for fresh deployments
- Fix Pangolin endpoint: ask separately from API URL (different hostnames)
- Add pangolin_create_resources() to create resources + targets during setup
- Set all resources as public (no SSO/blockAccess) automatically
- Fix API health check URL to use actual org endpoint
- Fix MongoDB entrypoint: delegate to docker-entrypoint.sh so INITDB user
  creation works on fresh volumes (was bypassing Docker's init sequence)

Bunker Admin
2026-04-09 11:43:13 -06:00
38ccaa8a5b 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
2026-04-07 15:24:33 -06:00
530551f568 Fix deployment issues found during end-to-end testing
- install.sh: Use tar --strip-components=1 instead of mv for robust
  extraction when install dir partially exists (root-owned Docker
  artifacts)
- config.sh: Add --non-interactive mode (--domain, --admin-password,
  --enable-all flags) for CI/CD and automated deployments
- docker-entrypoint.sh: Validate critical env vars on startup, fail
  early with clear messages instead of silent failures
- docker-compose.yml: Change Redis eviction policy from allkeys-lru
  to noeviction (required by BullMQ job queues)
- Prisma: Add missing petitions.coverVideoId migration (schema had
  the column but migration omitted it, causing 500 on public endpoint)
- Add scripts/uninstall.sh for clean removal including root-owned files
- Add scripts/test-deployment.sh for automated post-install verification

Bunker Admin
2026-04-07 14:06:05 -06:00
08bd1f92b0 Add unified analytics system with GeoIP geo-tracking
Full analytics platform with MaxMind GeoLite2 IP-to-location resolution,
cross-module dashboard (docs, video, photo), user drill-down, volunteer
self-service stats, and ANALYTICS_ADMIN role with feature flag controls.

- ANALYTICS_ADMIN role + ANALYTICS_ROLES group across backend and frontend
- GeoIP service (MaxMind GeoLite2, lazy-loaded, graceful degradation)
- Geo fields (country, region, city, lat/lng) on DocsPageView, VideoView, PhotoView
- IP resolved to geo before SHA-256 hashing (privacy-preserving)
- Unified analytics module: overview, geo, content, user engagement endpoints
- 4 admin dashboard pages: Overview, Geography (Leaflet map), Content, Users
- Volunteer MyAnalyticsPage for self-service activity stats
- Settings UI: enableAnalytics, analyticsGeoEnabled, trackAuthenticatedUsers, retentionDays
- Scheduled cleanup job respecting configurable retention period
- config.sh: Analytics + MaxMind prompt in configure_features()
- Control panel: enableAnalytics flag, template, discovery, wizard, detail page
- Docker: geoip volume mount, MaxMind env vars, entrypoint auto-download
- Nginx: X-Forwarded-For fix ($proxy_add_x_forwarded_for) for real client IP
- Express trust proxy set to 2 for Pangolin/Newt tunnel chain
- CORS updated for docs origin (cmlite.org + docs.cmlite.org)
- Lander page: added docs-analytics tracking snippet
- Prisma migration: 20260402100000_add_analytics_system

Bunker Admin
2026-04-03 08:47:44 -06:00
c306e061ab Generate GITEA_SSO_SECRET and SERVICE_PASSWORD_SALT in config wizard
New installs now get dedicated secrets for Gitea SSO cookie signing and
service password derivation, rather than falling back to JWT_ACCESS_SECRET.
Existing installs are unaffected (update_env_var_if_empty preserves values).

Bunker Admin
2026-03-31 12:13:32 -06:00
8b9ab93856 Add docs CMS: blog authoring, access policies, sharing, version history, templates, metadata, search, Gitea auto-setup
7 documentation system features:
- Blog authoring: frontmatter panel, new post wizard, authors management
- Access policies: per-file/directory edit restrictions with role/user granularity
- Public sharing: share links with collaborative editing via dual JWT auth
- Version history: Gitea auto-commit on save, diff viewer, restore
- Document templates: 8 built-in templates (blog, guide, API ref, ADR, FAQ, etc.)
- Metadata dashboard: overview of all docs with warnings (no-tags, stale, etc.)
- Content search: in-file text search with line-level matches

Gitea auto-setup: one-click configuration of API token, repos, labels, OAuth app
- Backend service + startup hook (auto-configures if GITEA_ADMIN_PASSWORD set)
- Admin GUI wizard at /app/services/gitea/setup
- config.sh now prompts for Gitea admin password

Backend: 10 new files, 5 modified (3 models, 1 enum, 2 migrations, 30+ API endpoints)
Frontend: 13 new files, 3 modified (hooks, components, pages)

Bunker Admin
2026-03-27 13:28:52 -06:00
82a66a97d0 Add MONGO_ROOT_PASSWORD to docs, config wizard, CCP, and prod compose
Follow-up to security audit commit — propagates MongoDB auth
(--auth flag) across all deployment paths:

- mkdocs environment-variables.md: add MONGO_ROOT_PASSWORD + MONGO_ROOT_USER,
  update ENCRYPTION_KEY description (now required in all environments),
  add to secret generation and full-stack variable lists
- config.sh: generate MONGO_ROOT_PASSWORD alongside Rocket.Chat credentials
- docker-compose.prod.yml: add --auth + credentials to MongoDB, update
  Rocket.Chat MONGO_URL with auth params
- CCP env.hbs: add MONGO_ROOT_USER/PASSWORD to chat block
- CCP docker-compose.yml.hbs: same MongoDB auth + MONGO_URL changes
- CCP secret-generator.ts: add mongoRootPassword to InstanceSecrets

Bunker Admin
2026-03-27 08:57:48 -06:00
39d74e7b85 Add guided tour, media enhancements, error handling, and DevOps improvements
Major additions: onboarding tour system, correlation-id middleware, media
error handler, restore script, env validation script, Dockerignore files.
Updates across 70+ admin components for improved UX and error handling.

Bunker Admin
2026-03-26 10:31:51 -06:00
f2284a9cdf Fix curl|bash install: redirect stdin from /dev/tty for interactive prompts
When piped (curl | bash), stdin is the curl output, not the terminal.
All read prompts in config.sh were reading leftover pipe data or EOF,
causing infinite password validation loops and garbage domain values.

Bunker Admin
2026-03-25 19:45:29 -06:00
7287328148 Harden install pipeline: health checks, log rotation, backup timer
- install.sh: Add Docker daemon check, 10GB disk space pre-flight,
  error handling on pull/up, post-startup health polling with crash
  detection, cleanup trap on failure
- docker-compose: Fix nginx/listmonk depends_on to service_healthy,
  add x-logging anchor (10m/3 files) to all ~39 services
- config.sh: Preserve existing secrets on re-run (reconfigure mode),
  add automated daily backup timer (systemd, 02:00, 30-day retention)
- mirror-images.sh: Fix gotify source tag (2.9.0 not v2.9.0)
- build-release.sh: Ensure mkdocs/docs and mkdocs/overrides dirs exist
- .env.example: Add COMPOSE_PROFILES variable

Bunker Admin
2026-03-25 19:33:11 -06:00
204e90dd3b Fix config.sh: read embed ports from .env for Homepage services.yaml
Rocket.Chat and Jitsi embed ports were hardcoded in the Homepage
services.yaml generation. Now reads from .env so multi-instance
deployments with custom ports get correct Homepage dashboard links.

Bunker Admin
2026-03-25 15:32:53 -06:00
8e6f0996de Add pre-built image installer and release tarball system
New install method: curl one-liner downloads a lightweight release
tarball (~9 MB) and runs the config wizard. No git clone needed,
no TypeScript compilation — pulls pre-built images from Gitea registry.

- docker-compose.prod.yml: production compose without build blocks or
  source code volume mounts; IMAGE_TAG defaults to latest
- scripts/install.sh: curl-friendly installer (downloads tarball,
  extracts, runs config.sh)
- scripts/build-release.sh: creates release tarball from dev repo
  with only runtime files (configs, scripts, docs, empty data dirs)
- config.sh: release-mode detection (VERSION file + no .git dir),
  auto-sets IMAGE_TAG=latest and NODE_ENV=production
- upgrade.sh: release-mode upgrade path (downloads new tarball from
  Gitea Releases API instead of git pull, always uses registry mode)
- upgrade-check.sh: release-mode version check via Gitea API
- .gitignore: exclude releases/ and api/dist/
- Docs: updated getting-started with pre-built install instructions

Bunker Admin
2026-03-22 20:34:49 -06:00
admin
ef11f94e76 Add systemd install script and improve reset-site.sh resilience
- Add scripts/systemd/install.sh to handle placeholder substitution
  (__PROJECT_DIR__, __USER__) and systemd unit installation in one command
- Simplify manual install instructions in SettingsPage and config.sh to
  reference the new install script
- Preserve existing home.html and home.css in reset-site.sh instead of
  overwriting with templates
- Add comments/ and partials/ to preserved directories list
- Fix nav removal in mkdocs.yml using Python regex instead of fragile sed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 01:03:50 -06:00
da3e43fcf7 Add browser-based system upgrade UI with file-based IPC
API container writes trigger files to a shared volume (data/upgrade/),
and a systemd path watcher on the host detects them and runs the
upgrade scripts. This avoids giving the container Docker socket access.

- Add upgrade-check.sh (git fetch + compare + write status.json)
- Add upgrade-watcher.sh (systemd bridge, dispatches check/upgrade)
- Add systemd path/service units with placeholder substitution
- Modify upgrade.sh with --api-mode flag (progress.json + result.json)
- Add API upgrade module (service + routes, SUPER_ADMIN only)
- Add System tab to Settings page with version info, changelog,
  progress steps, and upgrade confirmation modal
- Add upgrade watcher installation to config.sh wizard
- Add data/upgrade/ shared volume to api service in docker-compose

Bunker Admin
2026-03-03 18:00:15 -07:00
f57a6d07f5 Fix poll vote submission failure and add pridecorner.ca nginx routing
Users could not submit scheduling poll votes when an invalid or partial
email was entered — Zod rejected empty strings and non-email text with a
generic validation error. Added client-side email validation in both
SchedulingPollPage and SchedulingPollWidget, plus z.preprocess() on the
backend to coerce empty strings to undefined. Also added pridecorner.ca
to all nginx server blocks and added generate_nginx_configs() to
config.sh so template-based configs are generated during setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:15:26 -07:00
9e51aac570 Okay Wish I could say I know exactly. Will do better next time promise lol 2026-02-26 17:47:04 -07:00
1a1f12c45b Tonne of updates 2026-02-18 17:15:31 -07:00
99a6abab06 Add video card insert feature + MkDocs video hydration + fixes
- New video card block for GrapesJS landing pages, email templates,
  MkDocs export, and documentation editor Insert dropdown
- Shared HTML generators in admin/src/utils/videoCardHtml.ts
- MkDocs video-player.js hydrates .video-card-block elements:
  thumbnail fix via MEDIA_API_URL, click-to-play inline, Gallery link
- Media API CORS: auto-add MkDocs + docs subdomain origins
- env_config_hook.py: smart Docker hostname detection, ADMIN_PORT
  resolution, pass env vars to MkDocs container
- Gallery URL uses /gallery?expanded=ID format
- VideoPickerModal: fix double /api prefix and Docker hostname thumbs
- Seed: default-video-card PageBlock
- Remove V1 legacy code (influence/, map/)

Bunker Admin
2026-02-17 15:42:32 -07:00
a77306fac2 Initial v2 commit: complete rebuild with unified API + React admin
Phase 1-14 complete:
- Unified Express.js API (TypeScript, Prisma ORM, PostgreSQL 16)
- React Admin GUI (Vite + Ant Design + Zustand)
- JWT auth with refresh tokens
- Influence: Campaigns, Representatives, Responses, Email Queue
- Map: Locations, Cuts, Shifts, Canvassing System
- NAR data import infrastructure (2025 format)
- Listmonk newsletter integration
- Landing page builder (GrapesJS)
- MkDocs + Code Server integration
- Volunteer portal with GPS tracking
- Monitoring stack (Prometheus, Grafana, Alertmanager)
- Pangolin tunnel integration

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 10:05:04 -07:00