NocoDB v2 stores auth tokens in-memory (Pinia store), not in cookies
accessible to external pages. The auth bridge approach can't inject
tokens into NocoDB's SPA state. Reverted to the original banner
approach ("sign in to NocoDB in a new tab").
Kept: CSP fix (frame-ancestors http://localhost:* instead of just
localhost, which only matched port 80).
Bunker Admin
- 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
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
- 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
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
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
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
Vaultwarden sends a restrictive Content-Security-Policy with frame-ancestors
that blocks iframe embedding. The embed proxy (port 8890) already stripped
this header, but the subdomain server block did not.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /api/ location blocks in both default.conf and services.conf templates
were missing Upgrade/Connection headers, preventing the Hocuspocus WebSocket
connection from establishing through nginx.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Resolve Pangolin site slug to numeric ID in sync route (fixes target creation 400 errors)
- Disable SSO on newly created Pangolin resources for public access
- Fix nginx media API proxy: use rewrite + set ordering for proper URI rewriting
- Upgrade script: clear skip-worktree flags, fix Docker-owned dir permissions, stash untracked files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace postMessage wildcard ('*') with explicit parent origin passed
via ?origin= parameter to prevent auth state disclosure to arbitrary
embedders
- Tighten frame-ancestors CSP: production restricts to self + DOMAIN,
dev restricts to localhost origins (was frame-ancestors *)
- Remove deprecated X-Frame-Options ALLOW-FROM header (CSP
frame-ancestors is the modern replacement)
- Validate targetOrigin with URL constructor before use
Bunker Admin
Remove V1 legacy configs (admin.conf, public.conf) and orphaned backup that
were never used by the container. Stop tracking generated .conf files (built
from *.template by envsubst at startup). Backport improvements to templates:
variable proxy_pass for media-api (fixes startup crash when container is down),
extended bot detection list, and mkdocs-proxy location for volunteer map docs.
Bunker Admin
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>