Breaking/2026 stack modernization round 2#661
Merged
datdamnzotz merged 47 commits intoOrcpub:developfrom Mar 13, 2026
Merged
Conversation
script-tag now passes through all attributes (was dropping anything besides :src and :nonce). integrations.clj is a stub with commented examples — configure via env vars to enable.
integrations.clj exports csp-domains (connect-src, frame-src lists) which csp.clj merges into the Content-Security-Policy header via pedestal.clj. Stub returns empty map — no behavior change until integrations are enabled via env vars.
- classes.cljc: "exhaustrion" → "exhaustion" (Barbarian Frenzy trait) - email.clj: "please do no click" → "please do NOT click" - views.cljs: remove `prn "FRAME?"` debug output from character-page
Centralizes app name, logos, copyright, email sender, and social links behind env vars with neutral defaults. Forks override via APP_NAME, APP_LOGO_PATH, etc. instead of find-and-replace across source files.
- routes.clj: default title/description/image read from branding vars, fix http→https for OG meta image URL - email.clj: all sender names, subjects, and greeting text use branding/app-name and branding/email-sender-name - views_2.cljc: logo path and copyright use branding vars (CLJ side), with neutral CLJS fallbacks for compilation
Replace ~60 hardcoded "OrcPub" and "Dungeon Master's Vault" references with branding/app-name across privacy policy, terms of use, community guidelines, and cookie policy sections. Logo path uses branding/logo-path. Legal uppercase sections use (.toUpperCase branding/app-name).
New integrations.cljs provides no-op hooks for page view tracking and ad banner placement. Forks override with real implementations. Wire track-page-view! into :route event handler (single choke point for all navigation). Document server→client config bridge pattern in integrations.clj.
Document all new APP_* branding vars and integration vars with examples and cross-reference to fork-customization KB doc.
System/getenv returns nil when PORT isn't in shell env, causing Jetty to fail with "HTTP was turned off with nil port". Now falls back to 8890 (matching dev config).
…ral integrations Phase B: public repo abstraction layer matching DMV overrides. New files: - branding.cljs: reads window.__BRANDING__ with OrcPub defaults - user_tier.cljs: :user-tier sub always returns :free - user_data.clj: pass-through enrich-response + empty registration-defaults Modified: - branding.clj: add support-email, help-url, email-from-address, client-config - index.clj: inject window.__BRANDING__ JSON via cheshire - integrations.cljs: rename ad-banner → content-slot, add on-app-mount!, strip ad/analytics example comments - integrations.clj: strip analytics/SDK example comments, simplify docs - views.cljs: wire branding (logo, social links, copyright, app-name), require user-tier + integrations - character_builder.cljs: patreon-link-props → supporter-link-props, wire to branding/social-links - routes.clj: wire user-data hooks (enrich-response, registration-defaults) - email.clj: emailfrom → branding/email-from-address - .env.example: add APP_SUPPORT_EMAIL, APP_HELP_URL, clean integration comments
…list! stub - views_2.cljc: remove CLJS reader conditionals, use branding on both sides - integrations.cljs: add track-character-list! no-op stub
Mirror DMV integration hook API on public branch:
- supporter-link: header supporter button (shows when URL configured)
- support-banner: no-op stub (fork overrides with announcements)
- content-slot: now accepts user-tier arg, returns nil by default
- pdf-options-slot: no-op stub below PDF sheet options
- share-links / share-link-www: email share with dynamic protocol
- track-character-list!: no-op stub
Add field-limits to branding config bridge ({:notes 50000 :text 255
:number 7}). Add current-year and raw-html generic helpers to views.cljs.
Social links section gets usage examples in comments.
Shared files (views.cljs, character_builder.cljs) now call integrations
hooks identically to DMV — fork-specific rendering decisions live in
the override file, not inline in shared code.
branding.clj: add app-url def, :bluesky social link, dynamic copyright-year email.clj: add error handling to send-email-change-verification, fix "Patron" greeting to use name/neutral, fix grammar integrations.clj: add client-config stub (empty map) index.clj: inject window.__INTEGRATIONS__ alongside __BRANDING__ privacy.clj: replace hardcoded "orcpub.com" with branding/app-name views.cljs: add bluesky inline SVG icon, add discord/bluesky to social links
- Add send-updates? to user-body API response - Add /unsubscribe GET endpoint with JWT-signed token verification - Add /unsubscribe-success SPA page (follows verify-success pattern) - Add PUT /user for update-user-preferences (toggle send-updates?) - Add :toggle-send-updates event, :send-updates? subscription - Add email updates checkbox to My Account page - Backport social-links-footer to email.clj (self-gating on empty config) - Add unsubscribe-url helper to email.clj - Add 4 new test suites (token roundtrip, handler, preferences, user-body) - 210 tests, 963 assertions, 0 failures / 0 CLJS warnings
Figwheel's default ws://localhost:3449 fails in remote environments where the browser connects through a forwarded hostname. start.sh now auto-detects GitHub Codespaces and passes --fw-opts to override the connect URL with the correct wss:// endpoint. FIGWHEEL_CONNECT_URL env var available for other remote setups (Gitpod, tunnels). - scripts/start.sh: Codespaces detection + --fw-opts EDN override - scripts/common.sh: FIGWHEEL_CONNECT_URL env var - .devcontainer/devcontainer.json: port 3449 public (WebSocket needs it) - .env.example: document FIGWHEEL_CONNECT_URL
- start.sh show_help(): FIGWHEEL_CONNECT_URL + FIGWHEEL_PORT in env vars list, Remote Dev section in notes - start.sh run_checks(): report remote dev detection status for figwheel and all targets (auto-detect / configured / local) - menu show_help(): Remote Dev section with FIGWHEEL_CONNECT_URL ref
characters, parties, and user subscriptions (reg-sub-raw) were firing HTTP requests even when no auth token existed in app-db, producing spurious 401s in the browser console on every page load. Added token check ([:user-data :token]) before the go block in each subscription — no token means no request, just return []. Also fixed :user sub which checked the wrong path ([:user :token] instead of [:user-data :token]) — worked by accident, now correct. Matches the existing guard pattern in equipment_subs.cljs.
- views.cljs content-page: read user-tier/username/email from app-db directly in componentDidMount (lifecycle is not a reactive context) - subs.cljs: add token guard to ::folder5e/folders (same pattern as characters/parties/user) - core.cljs: remove subscribe trace monkey-patch (served its purpose) - subs_test.cljs: add folders guard tests
Rewrites send-error-email with: - 5-minute throttle per error fingerprint (prevents email storms) - Request scrubbing (strips credentials, cookies, body params, Datomic objects) - Stack trace filtering (orcpub.* frames, falls back to deepest non-infra) - Full cause chain rendering - Pedestal interceptor metadata extraction - Fix missing closing paren that broke compilation
- pedestal.clj: replace bare prn with io.pedestal.log/error in ETag interceptor - routes.clj: remove dead commented-out oauth require - routes.clj: update-user-preferences re-reads DB after transact (authoritative response) - routes.clj: re-throw unrecognized ExceptionInfo in save-character-handler
Env vars are strings. (boolean "false") returns true because any non-nil, non-false value is truthy. Fixed to compare against the string "true". This caused CSP nonce-interceptor to be a no-op in prod (DEV_MODE=false was parsed as truthy), resulting in empty Content-Security-Policy headers. Also removes dead devmode? def from index.clj (decoupled since 15b6d2a).
- BRANDING-AND-INTEGRATIONS.md: all paths updated to fork/ subdirectory, added integrations config bridge note and pedestal.clj CSP row - ENVIRONMENT.md: DEV_MODE must be string "true", added FIGWHEEL_PORT and FIGWHEEL_CONNECT_URL, updated file-reads table for fork/ paths - .env.example: fork/ path comments, APP_PAGE_TITLE rename, FIGWHEEL_PORT - README.md: test count 74→210, assertions 237→963 - dev-tooling.md: dev-mode? description matches actual behavior - docs/README.md: link to new KB index - docs/TODO.md: Datomic transactor crash investigation entry - docs/kb/: agent knowledge base — crash analysis with log evidence - docs/error-email-improvements.md: analysis and handoff doc
…alling it on-click had #(swap! hovered? not) which creates a new function and discards it. Changed to (swap! hovered? not) which actually toggles. Also: guard mouseenter/mouseleave with when-not mobile? to prevent synthetic mouse events from immediately closing the flyout on touch. Menu items now stopPropagation + close flyout on tap.
route-to-login now sets :loading false in app-db. Prevents the loading overlay from covering the login page when multiple parallel 401 responses race to set/clear the boolean flag.
…er fight set-loading now increments/decrements a counter. Overlay shows when > 0. Multiple reg-sub-raw go blocks firing simultaneously (characters, parties, folders, items) each toggle loading independently without stomping each other. route-to-login resets counter to 0.
Three breaking PDFBox 2.x → 3.x API changes were crashing spell card generation silently (caught by bare catch in add-spell-cards!), leaving a blank page in exported PDFs: 1. setStrokingColor(225,225,225) — 3.x float overload requires 0.0-1.0 range, not 0-255. Reflection dispatched to float method → validation error. Fixed by normalizing to (/ 225.0 255.0). 2. drawLine(x1,y1,x2,y2) — removed in 3.x. Replaced with moveTo/lineTo/stroke sequence. 3. moveTextPositionByAmount → newLineAtOffset, drawString → showText. All setNonStrokingColor/setStrokingColor calls now use explicit (float) casts to prevent reflection from hitting the wrong overload.
…used loading flash :verify-user-session (startup auth check) tested (:token (:user db)) instead of (:token (:user-data db)). This meant it never fired, leaving expired tokens in app-db. When reg-sub-raw subs later hit 401s, the loading overlay flashed before redirect to login. Also reset loading counter on 401 in the check, and fixed duplicate comment.
Cherry-picked from dmv/hotfix-integrations (8627b598). fork/integrations.cljs conflict resolved: kept breaking/ version (stubs).
LocalDate/now defaults to JVM timezone (UTC in Codespaces). A build at 10 PM CST reports as the next day. Macro now reads TZ env var if set, falls back to JVM default. Added TZ=America/Chicago to .env, .env.example, and Dockerfile (build + runtime stages with tzdata package).
Modern Docker Compose supports build: and image: in the same service. Two-file split (from 2019) is dead weight — admin builds with bare docker build, swarm ignores build: directives, nobody uses the separate file. Single file now handles both pull and build-from-source.
docker build tags images as orcpub-app/orcpub-datomic, but compose defaults to Docker Hub names. Compose pulled old Datomic Free images, causing :unsupported-protocol :dev at runtime. Set ORCPUB_IMAGE and DATOMIC_IMAGE env vars so compose uses the locally-built Pro images.
- .gitattributes: merge=ours for fork/ files and devcontainer.json - .gitignore: untrack .claude/, newrelic*, deploy/transactor.properties - devcontainer.json: restore Docker-in-Docker feature (lost in cherry-pick)
…+ test suite File-copy from dmv/hotfix-integrations with DMV branding stripped: - docker-setup.sh: 372 → 1332 lines (--check, --build, --deploy, --upgrade, --secrets) - docker-compose.yaml: aligned env vars, Docker Secrets docs, variable comments - docker-user.sh: ANSI-C color quoting fix, tr -d '\r' for Windows line endings - .env.example: separate DATOMIC_PASSWORD, image tag vars, generic branding placeholders - test/docker/: 46-test suite (test-upgrade.sh) with 8 fixture .env scenarios - .gitignore: add generated secrets files
Mirror of dmv/hotfix-integrations fork extraction. Shared source files are now identical between branches — only fork/ files differ. New fork/ files (community/public stubs): - fork/auth.clj: 24h tokens, no login tracking - fork/splash.cljc: community label, no generators - fork/privacy_content.clj: standard privacy policy Extended fork/ files: - fork/branding.clj + .cljs: copyright-url (empty), registration-logo-class (h-55), restrict-print-to-owner? (false) Shared files updated to consume fork/ values: - routes.clj, views_2.cljc, views.cljs, privacy.clj, .gitattributes
Cherry-picked shared files from dmv/ — no merge commit, preserving clean merge path for breaking/ → dmv/ sync. Infrastructure: docker-setup.sh → run CLI redesign, Docker secrets, nginx dev config, transactor template, compose CI workflow updates. App: PDFBox 3.x migration, CSP extensibility, email error throttle, config.clj secrets support, session token path fix, cookie consent. Docs: DOCKER, ENVIRONMENT, ERROR_HANDLING, email-system, branding. Assets: 6 SVGs, favicon, SRD PDF → dnld/, 5e actions reference, build.bat, removed unreferenced logo variants.
12 files still referenced the old script name in comments, error messages, and documentation.
Suppress intentional SC2016 (literal '${' check), SC2001 (regex too
complex for parameter expansion), fix SC2129 (grouped redirects).
- Remove PR comment step from CI (fork PRs lack write access, always 403) - Update docker-integration password validation for new URL format (password no longer embedded in DATOMIC_URL, appended at runtime)
./run --auto (naked mode) now runs the full pipeline (setup→build→up). The CI --force step regenerated passwords against an existing H2 database created by the first run, causing "Unable to connect to embedded storage". Add docker compose down + rm -rf data/ between setup validation steps so CI's explicit build/start steps get a clean slate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings develop up to date with the 2026 stack modernization branch. Major areas:
Tests