124 Commits

Author SHA1 Message Date
513b8cfea5 Add openssl to CCP API container for certificate generation
The certificate service uses openssl CLI to generate CA and agent certs.
Alpine base image doesn't include it by default.

Bunker Admin
2026-04-07 15:41:17 -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
d17e197a1b Fix Vite allowedHosts blocking production domains
Set allowedHosts to true since nginx handles Host header
validation. The previous `.${domain}` pattern used the
build-time DOMAIN value, which breaks when the same image
is deployed to a different domain.

Bunker Admin
2026-04-07 14:21:16 -06:00
cbfa4f9e28 Add uninstall.sh and test-deployment.sh to release tarball
Bunker Admin
2026-04-07 14:14:45 -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
74e5fa6475 Clean up obsolete files and refresh MkDocs site
Remove unused planning docs (FEDERATION_PLAN.md, SERVICE_INTEGRATIONS.md),
temporary screenshots, update .gitignore for Playwright MCP logs, and
refresh MkDocs site build with updated repo data.

Bunker Admin
v2.7.0 v2.7.1
2026-04-03 08:52:15 -06:00
72622671a2 Add petition/action pages with signature collection, CRM integration, and campaign linking
New influence submodule for public petitions with configurable sign forms,
email verification, GeoIP tracking, dedup, CSV export, admin moderation,
and post-sign CTA linking to advocacy campaigns. Includes competitive
analysis document covering 30+ campaign tech platforms.

Bunker Admin
2026-04-03 08:49:49 -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
0a20444a74 Archive addition 2026-04-02 15:14:27 -06:00
610f547dbf Fix dashboard mobile layout: header overflow, welcome banner, and stats grid
Hide nav icon bar and volunteer button on mobile (accessible via drawer),
stack welcome banner vertically with proper nowrap, replace status bar
flex row with 3-column CSS grid using MobileQuickStat component.

Bunker Admin
2026-04-02 15:12:27 -06:00
6db44eadc6 Fix mobile layout shift from typewriter text wrapping in hero section
Bunker Admin
2026-04-02 15:12:25 -06:00
5a0c4641a1 Security audit fixes, mobile responsiveness across 40+ admin pages
Security hardening from Mar 31 audit:
- Separate login rate limit (10/15min) from general auth budget (15/15min)
- Timing-safe webhook secret comparison (Listmonk)
- Docs file creation ACL check (matches PUT/DELETE guards)
- Key separation warnings for GITEA_SSO_SECRET and SERVICE_PASSWORD_SALT
- Clear GITEA_ADMIN_PASSWORD from .env after auto-setup
- SQL injection prevention in effectiveness groupBy (pre-validated map)
- Token hashing for password reset and verification tokens

Mobile responsiveness (Phase 2C):
- Add MobilePageHeader component and useMobile hook
- Responsive table columns (hide secondary cols on mobile)
- scroll={{ x: 'max-content' }} across all data tables
- Mobile-adapted layouts for Dashboard, Settings, Calendar, SMS, Social pages
- Conditional toolbar buttons on mobile viewports

Infrastructure:
- Updated docker-compose and nginx templates
- Build script and mirror script updates

Bunker Admin
2026-03-31 18:30:17 -06:00
d7ab8f0d99 Add file move capabilities to docs editor file tree
Drag-and-drop tree nodes to move files/folders between directories (desktop),
and right-click "Move to..." with searchable directory picker modal (desktop + mobile).

Bunker Admin
2026-03-31 13:44:03 -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
f378db89b5 Separate local vs remote Gitea API tokens to prevent credential collision
GITEA_API_TOKEN is for the local platform Gitea (docs comments, user
provisioning, SSO). New GITEA_REGISTRY_API_TOKEN is for the remote
registry at gitea.bnkops.com (release uploads via build-release.sh).

Previously both contexts shared one variable, causing auth failures
when the token for one instance was used against the other.

Bunker Admin
2026-03-31 11:53:20 -06:00
91db29402c Add Gitea SSO, fix security audit findings, harden production defaults
Gitea SSO: cookie-based single sign-on via nginx auth_request — sets
cml_session cookie on login/refresh, validates via /api/auth/gitea-sso-validate,
injects X-WEBAUTH-USER header for reverse proxy auth. Dedicated GITEA_SSO_SECRET
and SERVICE_PASSWORD_SALT env vars isolate secret rotation.

Security fixes from March 30 audit: IDOR on ticketed events (requireEventOwnership
middleware), IDOR on action items (admin/assignee/creator check), path traversal
on photos (resolve-based validation), CSV upload size limit (5MB), shared calendar
email exposure removed.

Gitea provisioner: auto-sync docs repo collaborator access based on role
(CONTENT_ROLES get write, SUPER_ADMIN gets admin). Gitea client extended
with collaborator management API methods.

Production hardening: NODE_ENV defaults to production in docker-compose.prod.yml,
Grafana anonymous auth disabled, install.sh branch ref updated to main.

Admin UI: moved docs reset from toolbar to MkDocs Settings danger zone,
improved collab Ctrl+S to explicitly save + cache-bust preview.

MkDocs site rebuild with updated repo data, upgrade screenshots, and content.

Bunker Admin
v2.4.0
2026-03-31 11:20:01 -06:00
9321aeb263 Move SMS phone bridge from campaign_connector submodule into main repo
Consolidates the Termux SMS server code (previously in a separate
campaign_connector git submodule) into termux-sms/ at repo root.
Updates phone clone commands to use sparse checkout so only the
termux-sms/ directory is downloaded onto the Android device.

Bunker Admin
2026-03-31 11:04:14 -06:00
5d15b4cffa Add engagement scoring and homepage stats EventBus listeners
- Engagement scoring listener: 11 event subscriptions, weighted scoring
  (donation=50, subscription=40, shift=20, canvass=15, email=10, video=3),
  Redis sorted set leaderboard, per-contact score + last-activity tracking
- Homepage stats listener: 12 subscriptions, incremental Redis counters
  (emails, signups, donations, responses, canvass, videos), capped recent
  activity lists (last 20 per type), cache invalidation on data changes
- GET /api/homepage/live-stats — public real-time counters + recent activity
- GET /api/observability/engagement-leaderboard — admin top-N contacts
- Total: 8 listeners, 70 subscriptions across all modules

Bunker Admin
2026-03-31 10:21:05 -06:00
902adce646 Add Straw Polls feature: quick opinion polling with public landers, MkDocs widgets, and social integration
Full-stack implementation across 7 sprints:
- Backend: 5 Prisma models (StrawPoll, Option, Vote, Comment, Challenge), 4 enums, POLLS_ADMIN role,
  admin CRUD routes, public voting/SSE/widget endpoints, BullMQ auto-close queue, rate limiting
- Admin: StrawPollsPage with inline drawers (campaigns pattern), PollResults bar chart, sidebar under Advocacy
- Public: dedicated poll lander with real-time SSE updates, browse page, anonymous voting with token dedup
- MkDocs: straw-poll-widget.js hydration (inline vote + card link modes), GrapesJS block types
- Social: feed activity (poll_voted), friend badge integration, challenge notifications, notification preferences
- Feature flag: enablePolls toggle in Settings, FeatureGate, Zod schema

Bunker Admin
2026-03-31 10:16:56 -06:00
68434c51a6 Extend EventBus: RC notifications, CRM activity, Gancio migration, calendar source types
- Add 7 new RC notification types: campaign published, donations, subscriptions,
  SMS escalations, user approved, video published, ticketed events
- Add CRM activity entries for subscription activated and email bounced
- Migrate ticketed-events Gancio sync from inline calls to EventBus listener
- Add meeting.created/deleted events from jitsi.routes.ts
- Add SHIFT, MEETING, TICKETED_EVENT to CalendarItemSource enum (Prisma migration)
- Update calendar-sync listener to use proper source types instead of MANUAL
- Total: 45 listener subscriptions across 6 modules, zero inline sync calls remaining

Bunker Admin
2026-03-31 10:04:44 -06:00
075a7c8c4a Redesign hero section: two-column layout, showcase cards, animations
- Two-column desktop layout (left: text/CTAs, right: feature showcase)
- Typewriter rotating words animation cycling through 8 platform capabilities
- Feature showcase with 4 auto-rotating screenshot cards (campaigns, canvassing, media, shifts)
- Staggered feature pill badges linking to corresponding sections below
- Terminal quick-deploy snippet with copy-to-clipboard
- Canvas particle drift background animation
- Count-up stats with IntersectionObserver
- Real screenshots replace mock data in showcase cards
- Light/dark theme support for all new elements
- Mobile responsive: single-column stack, overflow containment, scaled typography
- prefers-reduced-motion respected across all animations

Bunker Admin
2026-03-31 10:01:48 -06:00
0c2ffe754e Harden Stripe payment integration: 15 security fixes from audit
Addresses 11 original findings (1 critical, 3 high, 4 medium, 3 low)
plus 4 additional findings from security review:

- Mask secrets in PUT /settings response (was leaking decrypted keys)
- Add paymentCheckoutRateLimit (10/hr/IP) to all 5 checkout endpoints
- Implement durable audit logging to payment_audit_log table
- Pin Stripe API version to 2026-01-28.clover (SDK v20.3.1)
- Add charge.dispute.created/closed webhook handlers with DISPUTED status
- Restore tickets on dispute won, handle charge_refunded closure
- Guard against sentinel passthrough corrupting stored Stripe keys
- Wrap refund DB updates in try/catch with webhook reconciliation fallback
- Add $transaction for product maxPurchases race condition
- Remove dead Payment model lookup from handleChargeRefunded
- Cap donation amount at $100k in both schemas
- Add requirePaymentsEnabled middleware on all checkout routes
- Remove Stripe internal IDs from CSV exports
- Add Cache-Control: no-store on admin settings responses

Bunker Admin
2026-03-31 08:34:23 -06:00
3de1d3fca5 Rewrite README as visual explainer with screenshots and docs link
Bunker Admin
v2.5.0 v2.6.0
2026-03-30 11:44:25 -06:00
a436c494fd Add duplication guard in collab onChange to detect and auto-fix doubled content
Y.js CRDT merges can duplicate content when a client reconnects after
external file modifications (e.g., API PUT while collab is active).
The guard detects when content is exactly doubled and auto-trims it.

Bunker Admin
2026-03-27 13:46:35 -06:00
078bb6e313 Fix collab preview refresh: use src reassignment with cache-buster instead of contentWindow.reload
Cross-origin iframes may silently fail on contentWindow.location.reload().
Use src reassignment with cache-buster query param to force fresh load.
Increased debounce to 2.5s to give MkDocs more time to rebuild.

Bunker Admin
2026-03-27 13:41:02 -06:00
eb16815f91 Fix blog hooks: unwrap API response envelope for authors and categories
The API returns { authors: {...} } and { categories: [...] } but hooks
were expecting the unwrapped values directly. Also add defensive guards
in components for undefined props during initial render.

Bunker Admin
2026-03-27 13:33:47 -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
0fc9ea80bf Fix cookie Secure flag for HTTP dev, un-track generated nginx confs
- Cookie Secure flag now uses req.secure (respects trust proxy +
  X-Forwarded-Proto) instead of NODE_ENV. Works correctly over both
  HTTP (local dev) and HTTPS (production tunnel).
- SameSite=Strict over HTTPS, SameSite=Lax over HTTP (browsers reject
  Strict cookies over plain HTTP).
- Un-track generated nginx/conf.d/api.conf and services.conf (gitignored,
  regenerated from templates at startup).
- Update CLAUDE.md: ENCRYPTION_KEY now required in all environments.

Bunker Admin
v2.3.1
2026-03-27 10:06:38 -06:00
776aa6fbac Fix nginx templates (source of truth) + add reservedCount migration
The generated api.conf and services.conf we edited earlier were overwritten
at container startup by envsubst from *.template files. Fix the actual
templates:
- api.conf.template: X-Forwarded-For → $remote_addr, add limit_req
- services.conf.template: add frame-ancestors CSP after proxy_hide_header
- Add Prisma migration file for ticket_tiers.reserved_count

Bunker Admin
2026-03-27 09:55:27 -06:00
b215cda018 Security audit follow-up: httpOnly cookies, ticket reservations, MongoDB keyfile
Deferred findings from the March 27 security audit, plus a bug fix:

MongoDB keyfile (bug fix):
- Generate replica.key on first boot via entrypoint script
- Fixes crash from --auth + --keyFile without an existing keyfile
- Applied to docker-compose.yml, docker-compose.prod.yml, CCP template

I7 — Ticket overselling prevention (reservation pattern):
- Add reservedCount field to TicketTier schema
- Atomically increment reservedCount inside transaction on checkout
- Release reservation on checkout.session.completed (webhook)
- Release reservation on checkout.session.expired (webhook)
- Include reservedCount in availability calculations

I17 — Move refresh token to httpOnly cookie:
- Server sets httpOnly SameSite=Strict cookie on login/register/refresh
- Cookie scoped to /api/auth path, secure in production
- Refresh/logout endpoints read from cookie (with body fallback for compat)
- Frontend no longer stores refreshToken in localStorage
- Auth store simplified: removed refreshToken from state + persistence
- API interceptor uses withCredentials:true for automatic cookie sending
- Updated media-api, media-public-api, QuickJoinPage, volunteer-invite
- Renamed getTokens → getAccessToken across all media components
- Install cookie-parser middleware

L2 — FeatureGate loading state:
- Show Skeleton instead of children while settings are loading
- Prevents briefly exposing disabled feature pages

Bunker Admin
2026-03-27 09:20:26 -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
1bf19fff0e Security audit: fix 30 findings across auth, IDOR, XSS, path traversal, infrastructure
Comprehensive 6-domain security audit addressing 8 Critical, 17 Important,
and 5 Low findings. Key fixes:

Critical:
- Strip PII from unauthenticated ticket lookup (IDOR)
- Add role+permission checks to event check-in routes
- Validate tier-to-event ownership on update/delete (IDOR)
- Fix path traversal in video replace (resolve + prefix check)
- Enable MongoDB authentication for Rocket.Chat
- Disable Grafana anonymous access
- Sanitize CSV exports against formula injection (payments)
- Apply DOMPurify to richDescription on public event page (XSS)

Important:
- Require current password for self-service password changes
- Atomic password reset token consumption (race condition fix)
- Scope postMessage to specific origin (not wildcard)
- Validate redirect parameter against open redirect
- Replace weak temp passwords (5760 values → crypto.randomBytes)
- Move shift capacity check inside transaction (TOCTOU fix)
- Fix EVENTS_ADMIN privilege inversion in ticketed events
- Make ENCRYPTION_KEY required (remove optional fallback)
- Add internal Prometheus metrics endpoint for Docker scraping
- Add nginx-level rate limiting (limit_req_zone)
- Fix X-Forwarded-For to use $remote_addr (prevents spoofing)
- Replace CSP stripping with frame-ancestors in embed proxies
- Remove error.message from Fastify 500 responses
- Strip PII from volunteer canvass address data
- Wrap GrapesJS output in {% raw %} to prevent Jinja2 SSTI
- Scope SSE token query param to /sse path only
- Sanitize Listmonk email query against injection

Bunker Admin
2026-03-27 08:47:24 -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
0c634e100f Replace custom code-server (9GB) with upstream LinuxServer image (~1GB)
Drop the custom Dockerfile.code-server that bundled Claude Code CLI,
Python/MkDocs tooling, and build-essential on top of codercom base.
Switch to the already-mirrored linuxserver/code-server image instead.

- Both compose files: use code-server:latest, LinuxServer env vars
  (PUID/PGID/DEFAULT_WORKSPACE), port 8443, /config mount layout
- Nginx configs + templates: proxy to :8443 instead of :8080
- API env default: CODE_SERVER_URL updated to :8443
- build-and-push.sh: remove --include-code-server flag
- upgrade.sh: remove code-server conditional rebuild + registry fallback
- install.sh: add --ignore-pull-failures for optional missing images
- .env.example, CCP templates, bunker-ops template: updated

Bunker Admin
2026-03-25 20:10:36 -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
3262d92065 Remove hardcoded container names for multi-instance deployment support
- Dashboard: auto-discovers containers from Docker network via socket
  proxy API instead of hardcoded 30-name list. Labels derived from
  docker compose service metadata.
- Email/Settings: mailhog host read from env.SMTP_HOST instead of
  hardcoded 'mailhog-changemaker' string
- Pangolin: grafana container derived from env.GRAFANA_URL hostname;
  newt container/service names from NEWT_CONTAINER_NAME/NEWT_COMPOSE_SERVICE
- SSRF blocklist: built dynamically from all service URL env vars
  instead of hardcoded hostname list
- New env vars: DOCKER_NETWORK_NAME, DOCKER_PROXY_URL,
  NEWT_CONTAINER_NAME, NEWT_COMPOSE_SERVICE

Bunker Admin
2026-03-25 17:35:05 -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
81026b38db Remove stale granular admin roles migration (subsumed by baseline)
Bunker Admin
2026-03-25 15:26:39 -06:00
abdfd50cb8 Make embed proxy ports configurable via env vars for multi-instance deployments
All 13 nginx embed proxy ports (8881-8895) are now driven by environment
variables instead of being hardcoded. This prevents port conflicts when
running multiple Changemaker instances on the same host.

Chain: .env → docker-compose port mappings → nginx container env →
entrypoint.sh envsubst → services.conf.template listen directives →
API /services/config endpoint → frontend buildServiceUrl().

Existing deployments are unaffected (all vars default to current values).

Bunker Admin
2026-03-25 15:25:00 -06:00
63e05adcee Bunch more stability fixes 2026-03-23 22:12:24 -06:00
a56f8446f7 Fix Pangolin setup: root domain support + disable SSO auth on resources
- Omit subdomain field for root domain resources (Pangolin rejects empty
  string but accepts absent field)
- Set sso:false + blockAccess:false after resource creation so resources
  are publicly accessible without Pangolin auth redirects
- Make subdomain optional in CreateHttpResourcePayload type
- Applied to both /setup and /sync endpoints

Bunker Admin
2026-03-23 15:47:57 -06:00
a5a83f2d04 Whitespace: trigger upgrade test
Bunker Admin
2026-03-23 14:58:16 -06:00
c701f77237 Add :latest fallback to registry image pull in upgrade.sh
When --use-registry is set, the upgrade script tries to pull images
tagged with the current HEAD SHA. If images were built at an earlier
commit, that SHA tag won't exist. Now tries :latest before falling
back to a full source build. Also applies to nginx and code-server.

Bunker Admin
2026-03-23 14:50:16 -06:00
44931260c4 Fix build-release.sh Gitea URL for host-side uploads
GITEA_URL points to the internal Docker hostname (gitea-changemaker:3000),
which is unreachable from the host. Derive external URL from GITEA_REGISTRY
instead, which already contains the external hostname.

Bunker Admin
2026-03-23 14:07:36 -06:00
e0fd4fd7b7 Update CLAUDE.md with consolidated architecture docs
Bunker Admin
v2.2.0
2026-03-23 13:48:18 -06:00
0090bd2f54 some random png stuff 2026-03-23 13:07:05 -06:00
68ba45a689 Documentation editorial: Material theme hardening, metadata, and content polish
- Enable navigation.instant, prefetch, progress, content.code.select, content.tabs.link
- Fix edit_uri (main→v2), copyright year (2024→2024-2026), consent banner config
- Add abbreviations glossary (47 acronyms with hover tooltips via snippets auto-append)
- Add tags to all 72 doc pages with consistent taxonomy (audience/module/type)
- Add status:new badges to 16 recent feature pages, search:boost to 7 entry pages
- Rewrite Architecture page with 5 Mermaid diagrams and full component documentation
- Rewrite Troubleshooting page from 5 to 13 sections with actionable checklists
- Fix broken links (Monitoring/Contributing pointed to blog placeholder)
- Expand Admin Guide roles table from 5 to 11 roles
- Create custom 404 page, blog with authors and inaugural v2 announcement post
- Fresh Playwright screenshots for login, dashboard, campaigns, users, settings, locations, shifts
- Remove 5 test/dev files and orphan template override
- Add planning document (DOCS_NEXT_STEPS.md) for future editorial reference

Bunker Admin
2026-03-23 12:36:10 -06:00
bb1935027d Upgrade system finished 2026-03-22 21:47:09 -06:00
a71ba20176 Update CLAUDE.md with installer and release workflow documentation
- Quick Start: add pre-built install section with curl one-liner
- Directory Structure: expand scripts/ with all deployment scripts
- Registry Operations: add build-release, install commands, two-compose note
- V2 Gotchas: document release vs source detection, api/dist gitignore,
  api/.dockerignore purpose
- Key Config Files: add docker-compose.prod.yml and config.sh

Bunker Admin
2026-03-22 20:38:36 -06:00