9 Commits

Author SHA1 Message Date
97444645cb chore(approach-c): Phase 0 complete - templates byte-equivalent to canonical
This commit completes Phase 0 of Approach C: the CCP template/env/static
files now produce output structurally byte-identical to canonical
docker-compose.prod.yml + .env.example. Verified by rendering against
marcelle, linda, and pia and diffing against their actual files — all
three show only the 30-line CCP-tenant header comment differing,
zero service/env-var structural differences.

Changes:

- templates/docker-compose.yml.hbs: reverted {{imageTag}} substitutions
  back to ${IMAGE_TAG:-latest} so the compose template is now byte-
  equivalent to docker-compose.prod.yml (modulo header). CCP controls
  per-instance image tag selection via the rendered .env's IMAGE_TAG,
  which compose-up picks up at runtime. This single-source-of-truth
  via env-substitution matches install.sh tenants exactly.

- templates/env.hbs: rewritten as a near-mirror of .env.example. Adds
  27 missing keys (IMAGE_TAG, GITEA_REGISTRY, COMPOSE_PROFILES,
  ENABLE_CCP_AGENT, GITEA_ADMIN_*, ENABLE_HLS_TRANSCODE, TZ, etc.)
  plus 15 CCP-specific extras (embed ports, dev-mode helpers, etc.).
  All 145 compose-template env-var references are now covered.

- templates/nginx/nginx.conf: synced from canonical. Includes recent
  security additions: redacted access-log format for token/secret
  query params, rate-limit zones (api_global, api_auth, upload),
  conditional HSTS via X-Forwarded-Proto map.

- api/scripts/render-for-instance.ts (new): one-off CLI that loads
  an Instance row, decrypts secrets if present (or uses empty object
  for isRegistered=true tenants), and calls renderAllTemplates() to
  a scratch dir. Used in Phase 0.4 to verify the template-vs-prod
  contract per tenant.

  Usage:
    docker compose exec ccp-api npx tsx scripts/render-for-instance.ts \
      --slug changemakerlite

Phase 0 acceptance gate met:
  - marcelle (release v2.10.2 install): 30-line diff, header-only
  - linda (release v2.9.14 install):    30-line diff, header-only
  - pia (release v2.9.10 install):      30-line diff, header-only
  - env.hbs key coverage: 0 missing vs marcelle's .env

Next phases unblocked:
  - Phase 1: add Instance.imageTag column (Prisma migration)
  - Phase 2: pre-flight diff endpoint
  - Phase 3: startReleaseUpgrade runner
  - Phase 4: routes + schemas
  - Phase 5: CCP UI "Upgrade to Release" button
  - Phase 6: E2E test on marcelle (v2.10.2 -> v2.10.3)

Bunker Admin
2026-05-22 09:35:30 -06:00
f34382ebdd chore(approach-c): Phase 0 initial template overlay + session handoff
This session shipped:
- Approach B end-to-end (commit 4a3d9d7): full rollout to all 7 tenants;
  marcelle E2E validated twice (121s + 100s).
- v2.10.2 surgical update applied to 6 remaining tenants.

This commit lands the kickoff for Approach C (template re-render path):

scripts/templates changes:
- docker-compose.yml.hbs.OLD-style-pre-approach-c: preserved old CCP
  template (Handlebars-heavy, dynamic container names, secrets rendered
  at template-time).
- docker-compose.yml.hbs: REWRITTEN as a near-mirror of canonical
  docker-compose.prod.yml. Minimal Handlebars overlay:
    - Header comment lists {{name}}, {{slug}}, {{composeProject}}.
    - 5 image refs: ${IMAGE_TAG:-latest} -> {{imageTag}}, so CCP can
      per-instance override once Phase 1 lands the Instance.imageTag column.
  All other variation flows through env-var substitution from tenant's
  .env. Container names are now hardcoded (matching prod), feature flags
  are deferred to COMPOSE_PROFILES gating (matching prod).

Why a rewrite: the old CCP template and prod compose used fundamentally
different conventions (dynamic vs hardcoded names, render-time vs
substitute-time secrets, Handlebars vs profiles gating). Sync-by-addition
couldn't reconcile them. The rewrite makes Approach C re-render safe for
the install.sh-installed fleet (marcelle, linda, pia and future).

docs/SESSION_HANDOFF_2026-05-21.md: full session handoff covering fleet
state, Approach B rollout, Approach C plan, and where to start next
session. force-added because /docs is gitignored (same precedent as
docs/SESSION_HANDOFF_2026-05-20.md from prior session).

Phase 0 remaining work (next session):
- Audit env.hbs against new compose env-var expectations
- Sync static config files (nginx/, configs/prometheus/, etc.)
- Build api/scripts/render-for-instance.ts harness
- Iterate template until rendered output is per-instance-only diff
  against marcelle/linda/pia actual compose.

Then Phases 1-6 per plan in subsequent sessions (~11-14 hours total).

Bunker Admin
2026-05-21 19:32:21 -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
2026-03-31 11:20:01 -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
bb1935027d Upgrade system finished 2026-03-22 21:47:09 -06:00
5642a24c8f Sync CCP templates with production configs for complete instance provisioning
Closes 12 template drift gaps between the Control Panel templates and
production configs. New instances now provision with full monitoring
(alerts fire properly), correct Gitea DB type (postgres not mysql),
social sharing previews (OG meta bot routes), Excalidraw subdomain
routing, docker-socket-proxy for Homepage, and complete Grafana/
Alertmanager/Prometheus config copying.

Key changes:
- Rewrite Prometheus template: add alerting, rule_files, 5 scrape jobs
- Add cAdvisor, node-exporter, redis-exporter, gotify, docker-socket-proxy
- Fix Gitea env from mysql to postgres to match docker-compose
- Add OG bot detection + rewrite routes for campaigns/pages/gallery
- Add Excalidraw nginx server block + Pangolin draw subdomain
- Add embed port to discovery portConfig + emailTestMode to registration
- Copy alerts.yml, alertmanager.yml, Grafana dashboards to templates
- Add Listmonk proxy port and upgrade volume to API service

Bunker Admin
2026-03-05 08:32:49 -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
2fa50b001c Merge changemaker-control-panel into v2 monorepo
Absorbs the separate control-panel git repo as a subdirectory.
Instances and backups directories excluded via .gitignore.

Bunker Admin
2026-02-21 11:51:45 -07:00