Repository navigation
Conversation
codeGlaze
added a commit
that referenced
this pull request
Sep 27, 2026
…lt here The owner has paused the agent on PR #34 so that this session builds the one authoritative fix for homebrew keys. The work branch is port/save-gate, cut from integration (a0d9e1d) and now pushed; #34's homebrew commits are inputs to the fix, not a competing version. plan-next.md §0a becomes that fix: three inputs (integration's key model, this branch's save gate, #34's load/import repair and link-stranding probes) merged into one model rather than stacked; the scope widened to everything that points at a key -- including other library items, the side the save rework never touched and where #34 had got to; owner checkpoints after the map and after the design; and the landing path through integration, #32 to develop, and #34 pulling integration and dropping what this supersedes. The stopgap question is resolved: nothing lands on its own. BRANCH.md carries the ownership, the branch table and the three open PRs that touch this, and states that this branch's own purpose is still grants. Also corrects a core fact committed two days ago: "homebrew never touches the server" is true of the library only. Custom content entered on a character travels with the character, and custom magic items are server-backed.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
codeGlaze
added a commit
that referenced
this pull request
Oct 6, 2026
The card's width already left a 16px gutter, but its padding was added on top, so it ran 12px past the right edge of a 390px screen. srd_reference_e2e now checks the card stays on screen.
A5 was added because of a misreading: the question was which A size is
closest to Letter, and the answer is A4. Letter is the default and A4 the
second layout to design around; a half sheet is a pamphlet format nobody
asked for.
It cost more than it was worth. It needed sheet-page-sizes and a gate in
fit-sheet-to-page!, because re-papering a 612x792 template onto A5 cut off
159 of its 335 fields. It produced the A5-only running-head overflow. And an
A5 export mixed paper sizes in one file.
valid-page-sizes is #{:letter :a4}. A request for :a5 now falls back to
Letter like any unknown option, rather than erroring. sheet-page-sizes and
its gate go: every offered paper now fits the sheet. The clipping test
iterates draw/page-sizes, so a paper added later that cuts the sheet fails
it.
No baseline moved; there was never an A5 baseline.
normalize-text treated WinAnsi as Unicode U+0000-U+00FF and refused the
rest. WinAnsi is a byte encoding: its 0x80-0x9F slots hold the curly
quotes, en and em dash, ellipsis, bullet, oe, OE and the euro sign, and
Helvetica draws all of them (asserted in winansi_test, not assumed).
So the sheet flattened punctuation and printed French oe as `?`, and the
spellbook did the same to 135 characters of SRD text in a font that draws
them. The earlier coverage table blamed Helvetica for the French loss; it
was this.
winansi? reads PDFBox's own WinAnsiEncoding table, so it is not a
hand-maintained list. normalize-text keeps a character when keep? says the
font draws it, falls back to the old ASCII substitutions only when it
cannot, and prints `?` last. C1 controls (U+0080-U+009F), which it used to
pass through to a font with no glyph for them, are now refused.
The sheet's per-field switch now changes font only when the other font
refuses FEWER characters. Before, a value whose one odd character neither
font has -- CJK beside Latin text -- switched font and gained nothing.
Two tests pinned the bug ("smart quotes/dash downgraded"); reversed, with
the reason recorded in place. Spellbook baselines re-seeded: 6 pages per
paper moved, ONLY their :sha and :text -- operator counts, geometry and
colour are unchanged, so characters changed and layout did not.
1121 tests, 7413 assertions green under the default locale, tr_TR and
es_ES. Lint 0 errors.
The per-field switch printed those fields in Vollkorn, a serif, beside Helvetica neighbours. Compared side by side, rendered from the sheet: Vollkorn prints, but serif among sans 505,744 bytes Nimbus Sans indistinguishable from Helvetica 388,172 bytes FreeSans close, looser leading 1,104,746 bytes TeX Gyre Heros PDFBox cannot embed CFF outlines Nimbus Sans is URW's metric clone of Helvetica: all 190 Latin-1 advance widths are identical to the AFM's, so a switched field fits exactly as it would have in Helvetica. It covers Polish, Turkish, Czech, Cyrillic and Greek. It has no Vietnamese, which prints `?` on the sheet; the spellbook and cards still print it, in Vollkorn. It lives in resources/fonts, not resources/public. Its licence is AGPL-3.0 with an exception for embedding in a PDF, which does not extend to serving the file. Licence text and provenance (source URL, SHA-256) are alongside it in resources/fonts/README.md. A test pins the width match, so swapping in a lookalike that is not metric-compatible fails rather than silently changing how fields fit. Latin-1 sheets keep Helvetica; no baseline moved. 1123 tests, 7416 assertions green under the default locale, tr_TR and es_ES. Lint 0 errors.
Two findings from review, both measured before fixing. svg-path-ops passed every arc to arc-points, which divides by the radius and by the chord. A zero radius or an arc ending where it starts came back as 6 NaN ops of 7, written straight into the PDF content stream. SVG 1.1 appendix F.6.2 says: a zero radius is a straight line to the endpoint, and an arc to its own start draws nothing. Both handled before sampling. No vendored icon has one, but the function takes arbitrary path data. dev/user.clj create-user! and email-exists? lowercased email with str/lower-case. They serve the CLI and REPL, which never start the server, so pin-locale! never runs there: on a Turkish machine IVAN@x.com would be stored and looked up as ıvan@x.com. Now ascii-lower-case, and dev/user.clj joins identity-files, so the guard covers it. One new lint warning, accepted: dev/style_gallery.clj re-requires orcpub.common, now also required by user.clj, the namespace the script runs in. It re-requires orcpub.pdf and clojure.java.io for the same reason, so it still runs without the dev profile. Removing the line would break that to save a warning. 1124 tests, 7421 assertions green under the default locale, tr_TR and es_ES. Lint 0 errors. No baseline moved.
The sheet mixed two fonts: Helvetica for fields it could draw, Nimbus Sans for the rest. That split existed only to keep Latin-1 exports byte-identical. It is not worth two fonts on one form, so the switch is reversed. Every text field, filled or blank, names /NmS -- a blank field typed into in a viewer gets Nimbus's glyphs too. Embedding also ends the viewer lottery: standard-14 Helvetica is never embedded, so each viewer drew its own substitute. Cost, measured on a Latin-only sheet: 290,018 -> 393,146 bytes, +101 KB, the full embed a fillable form needs. The trap, found by an existing test. PDVariableText.setDefaultAppearance copies the field's DA over every kid widget's own DA (PDFBOX-5797). Style 1 sets fixed sizes on 25 widgets -- 24 at 8pt, one at 10pt -- and swapping the font through it turned them into auto-size: a save box holding +7 went from 8pt to 4.89pt. The previous commit had the same fault for any non-Latin value in one of those 25. use-font! now rewrites each dictionary's DA directly, changing only the font name. 112 merged field/widget dictionaries that only inherited a DA now carry their own, still auto-size. The sheet baselines could not catch this: they pin page artwork and widget rectangles, not field appearances. A new test pins every widget's template size. drawn-text in pdf_test read appearance bytes as text. With a Type0 font those are glyph codes, so a drawn "4" read as nothing; it now decodes through the font. The refused-count helper is gone with the switch it served. 1125 tests, 7425 assertions green under the default locale, tr_TR and es_ES. Lint 0 errors. No baseline moved.
…P message
Registration mode used to print at namespace load from routes.clj, separately from
the startup report -- in every REPL and test run, and nowhere near the rest of the
effective configuration. It is now an ALLOW_UNVERIFIED_REGISTRATION row in the
report, whose value is the combination of that flag and EMAIL_SERVER_URL:
verified by email SMTP set
REFUSED: no mail server no SMTP, no opt-in
OPEN: no address check no SMTP, ALLOW_UNVERIFIED_REGISTRATION=true
verified by email (flag set, inert) both set: harmless today, but signup opens
without checks if the SMTP value is lost
The routes.clj printout is removed. The report only prints when the server starts,
which is where this belongs.
Also corrects email-missing-message, the (!!) block printed when EMAIL_SERVER_URL is
missing. It still said signup throws inside the transaction and tells the user to
try again -- the bug the registration changes fixed. It now says password reset
fails (still true; EMAIL_SERVER_URL stays critical for that), that signup is
refused unless the opt-in is set, and points at the row that says which. The same
outdated story was in a test description in config_report_test.clj and is fixed
there too, and docs/email-system.md described the removed startup warnings.
Tests pin all four modes, the row's presence in the rendered banner, and that the
message no longer describes the old behaviour; against integration's source they
fail with "No such var: config/registration-mode".
lein test 1064 tests / 7039 assertions / 0 failures. lein lint errors 0, warnings
30 -- one fewer than integration's, none in these files.
…SMTP-loss case needs the flag
…uses The schema stores used uses per reset period, and dawn and short rest were missing, so saving a character that had used a once-per-dawn weapon power failed. features_used_save_test saves a use under every period a weapon's recharge can name.
…onger fails a check A ctrl-click to-hit on desktop opens a card with both dice, the unused one struck. The check on the damage options read 'Damage' first, which a real natural 20 (1 run in 20) labels 'Critical damage'; it now accepts either.
… deleted once sent Sign-up verification, password reset, the password-changed, email-change and sign-in notices, and the artist emails are written to the database in the same transaction as the action that causes them. One worker sends them in the background, retries a busy or down mail server with growing gaps, gives up on a permanent refusal or after 8 attempts with an admin alert, and deletes each email once sent; the message keeps no history, since it holds reset and verification links. Claims are compare-and-set, so several servers never send the same email. Signing up while the mail server is down now works and the email follows, so the rollback that undid an account when its email failed is gone. A notice that cannot be built never blocks the change it reports on. The character-load report still sends directly, since the page reports the result to the player.
… deleted once sent The previous commit holds only the test file's rename; this one is the change. Sign-up verification, password reset, the password-changed, email-change and sign-in notices, and the artist emails are written to the database in the same transaction as the action that causes them. One worker sends them in the background, retries a busy or down mail server with growing gaps, gives up on a permanent refusal or after 8 attempts with an admin alert, and deletes each email once sent; the message keeps no history, since it holds reset and verification links. Claims are compare-and-set, so several servers never send the same email. Signing up while the mail server is down now works and the email follows, so the rollback that undid an account when its email failed is gone. A notice that cannot be built never blocks the change it reports on. The character-load report still sends directly, since the page reports the result to the player.
…hes Java Docker logs are capped per container (LOG_MAX_SIZE, LOG_MAX_FILES), so they cannot fill the disk. Java starts with flags that make it exit cleanly when it runs out of memory, writing a heap dump, and write a crash log if it dies; both go to the new orcpub-state volume with the unsent admin alerts, so they survive the container being replaced. On the next start the server emails the admin, once per file, what happened and where the file is. JAVA_OPTS was passed to the container but `java -jar` never read it, so the documented memory settings were ignored and the app ran with 25% of its container's memory. It now reaches Java through JDK_JAVA_OPTIONS, after the crash flags, in Compose and in generated Swarm stacks.
Characterization: the export's own drawing (headings, annotations, relabels, site line, notice page, cards) uses three Standard 14 Helvetica faces, none embedded. Read from a real export through generate-character-pdf.
The export's own drawing (spell-column headings, relabelled numerals, annotations, site line, notice page, card captions) used three Standard 14 Helvetica faces, none embedded: the viewer substituted its own, and they are WinAnsi-only, so a heading for "Czarodziej Lodz" with Polish letters printed "Czarodziej ?od?". Now Nimbus Sans Regular, Bold and Bold Italic (URW, OFL- compatible AGPL + PDF-embedding exception), the face the form fields already use. - draw/load-sans: per-document map of lazily embedded faces; load-fonts includes it. The export makes one and passes it everywhere. - Each face's 224 WinAnsi widths equal its Helvetica's (pinned by nimbus-sans-is-helvetica-width), so no position moved: the card and sheet baselines differ only in text strings (564+564+63 lines) and text hashes. - fit-text measures in the fields' own font; it measured Helvetica, which counts L-stroke as "?". - site-line-pages scans for artwork site lines before anything is drawn. Scanning after drawing read not-yet-embedded fonts and logged a fallback warning on style 4 exports. A saved export now renders with none. - Tests that read or render text use a saved copy (pdf-ops/reloaded). Size: plain sheet +3.2 KB (0.9%), sheet with cards +15.2 KB (3.5%).
Artist pages: a public page for each portrait artist
Weapons table, item charges, the Rest box and casting from items
…ith no name is still offered subclass-option left the option key to the name, so a subclass whose name does not make its stored key (a short name, or none) was offered under another key (or none) and could never be picked in the character builder.
Seen failing with the fix reverted (options.cljc at 097f983), lein test :only orcpub.dnd.e5.subclass-key-test: FAIL a name that does not make the stored key: (not (= :my-oath :x)) FAIL no name at all: (not (= :nameless nil)) Ran 1 tests containing 3 assertions. 2 failures, 0 errors. The name-derived-key claim passes either way. With the fix: 0 failures, 0 errors.
…evelop docs/kb/homebrew-guard.md
…nster scores, lone ability increase, shared reports, stale set-aside, shared count, auto-clean, pre-fix copy, audit exit)
…bility increase, shared reports, replaced entries Fail first, with the fixes reverted: clj shape table 3 failures + 2 errors (leading zeros, monster score, lone ability increase); cljs suite 3 failures, only a-report-from-shared-content-never-sets-aside-a-local-entry and an-entry-replaced-since-its-report-is-not-set-aside.
Guard homebrew: one shape check on every way in, and broken items set aside
…d a full regex escape The 12 test/e2e scripts each carried an inline copy of the static server, flagged as js/path-injection by CodeQL (the root-or-inside check was one compound condition). They now share test/e2e/static-server.js: root serves the host page, a path outside the root, with a NUL byte or with bad %-encoding gets a 404 before any file read. soak_e2e.js escapes every regex metacharacter in the section name (js/incomplete-sanitization). Checked by hand: root, asset, missing route, ../ traversal, bad encoding and NUL. CodeQL cannot run locally; the alerts clear when it re-scans after this reaches integration.
…port Browser scripts: fix the 13 CodeQL alerts (path injection, incomplete escape)
Seen failing before it passed: with the missing-file check, the age comparison and the build-config input each broken in stale_bundle.clj, 7 of the new test's 10 assertions failed (current-build, missing-build-files x3, newer-client-source, newer-style-source, newer-build-config); restored, 12 assertions pass. The banner's dev-mode gate is covered with redefs, not by a break.
…Zone.Identifier ignores
They are on agents/develop now, under docs/archive and scripts/research. CodeRabbit's docs/design exclusion goes with them: it kept #65 under the 100-file limit by hiding them.
…banner ./menu start and ./menu start server never built anything, so a pull left the page on old code and the banner up. They now run the rebuild check scripts/e2e/run.sh already had, moved to scripts/bundle-check.sh, and skip the compile when nothing changed. Seen failing before it passed. With the out-of-date check removed: FAIL a changed source builds the client: calls '' exit 0 FAIL a changed build config builds the client: calls '' exit 0 FAIL no bundle builds the client: calls '' exit 0 start build: 4 passed, 8 failed With a failed build ignored: FAIL a failed build stops the start start build: 9 passed, 3 failed Restored: start build: 12 passed, 0 failed
Reads DEV_MODE as the app does (only "true", unset is dev), counts project.clj as a build input, skips a build only for a real Figwheel or Garden process, refuses a production start under a dev Figwheel, stops the Datomic it started when a build fails, and runs the PR check on a retargeted PR. Seen failing before it passed, with the reviewed bundle-check.sh back: FAIL Figwheel here while production is wanted stops the start FAIL another program on the port here does not skip the build FAIL a changed project.clj builds the client FAIL DEV_MODE unset means dev FAIL TRUE counts as dev FAIL 1 is not dev, as the app reads it FAIL a reused garden.pid does not skip the stylesheet start build: 13 passed, 7 failed Restored: start build: 20 passed, 0 failed
Release cleanup: unblock #32, stray files off the code line, menu builds what is stale
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.
Takes
integrationintodevelopfor the Summer Patch. What it does for players and admins is inCHANGELOG.md, under [Summer Patch].Review: the PRs feeding this were reviewed one at a time, up to #79 (
fix/release-cleanup). This PR is too big for CodeRabbit to stand in for them.Before the upstream PR: remove the fork-only files
.coderabbit.yaml,.github/workflows/agent-trailers.ymland.github/workflows/branch-shape.yml.Upstream issues this release fixes
Found by reading every open Orcpub/orcpub issue against this code on 2026-10-04; each has its evidence on the OrcPub Tracker. They close when Summer Patch merges upstream.
Branches merged into
integrationwithout a PR (2026-08-27 to 2026-09-18)Listed so each change has a trail. Each is a first-parent merge in
git log origin/integration.feat/starting-equipment(2026-08-31),feature/one-template-per-style(09-05)perf/homebrew-builder-loop,feature/browser-side-character-images,feat/whats-new-panel(09-06)fix/header-flyout-under-sticky-toolbar,fix/tall-flyout-and-held-release,fix/release-panel-hold-ceiling,hotfix/my-content-dropdown-and-probe-cost,hotfix/boot-config-report,test/overlay-probe-user-menu-and-modals(09-07)fix/message-banner-spacing(09-08)fix/homebrew-save-keys,fix/filtered-list-staleness(09-13)fix/get-auth-token-undeclared,feat/source-tagged-keys(09-18)Housekeeping: upstream issues already resolved elsewhere
These are already fixed upstream, duplicated, or cannot occur in current code; they can be closed with these references.
729225cd), Apache repository mirrored over https20d613a7(2018), race builder offers a language choice including homebrew languages2539a0c1), Missing Content warning; this release widens it to spells and languages6b2e295c(2017), Champion adds half proficiency to initiative423b7632,ab95ba77), custom weapon melee/ranged reset