Repository navigation
fix: step 8 — address-label caps + zip guard, global-error, safe decode, codegen escaping, @DomainID, trimmed profile - #52
Merged
Conversation
…unzip - Validate caller-supplied labels and config with Zod (parseLabelInput): count capped at MAX_LABELS (10,000), every string bounded, barStates/ barType dropped (they are computed server-side), serviceType restricted to SERVICE_TYPES, startPosition bounded by the stock's sheet size (it is a count of blank cells, so it was an unbounded page count). - New src/lib/zip-guard.ts walks the template's central directory and inflates each entry with maxOutputLength = its declared size BEFORE PizZip sees it, capping entry count and total uncompressed bytes. A zip bomb, or an entry that lies about its size, now fails fast. - Template limit 5 MB -> 2 MB, with experimental.serverActions .bodySizeLimit raised from the 1 MB default to 4 MB (under Vercel's 4.5 MB request cap). The old 5 MB check could never be reached. Limits live together in address-labels/limits.ts. - preEncodeBarcodes logged label names and ZIP/routing digits on encode fallbacks (rule 14); it now logs the label index and error name. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Description decode - global-error.tsx: add a plain <a href="/"> that works without JS, and render "Try again" disabled until hydration (useSyncExternalStore), so a click on the server-rendered page is not silently swallowed. - tool-params.server.ts: decodeURIComponent threw URIError on a stray "%" in recordDescription and crashed the tool page; fall back to the raw value. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
generate-types.ts wrote table names, FK targets, permission strings and column sizes into generated source verbatim. A newline or "*/" in a name could close a comment early, a quote in a column name broke out of the quoted property key, and col.Size went straight into `.max(...)` in the Zod schemas as executable code. Route every interpolation through new scripts/codegen-escape.ts: propertyKey() (JSON-quoted keys), commentText() (no line terminators or */), positiveInt() (sizes). Output is byte-identical for ordinary metadata. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…inition Every api_* procedure must take @domainID INT first so the MP API can inject it. Regenerated _INSTALL/ministryplatform-install.sql. The proc must be re-deployed to an MP instance for the change to take effect. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… test Building an 80 MB archive timed out under coverage. A header that understates its size is fast to build and is the case that a declared- size check alone would miss; the honest-but-huge case stays covered in zip-guard.test.ts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
getCurrentUserProfile sent User_ID, User_GUID, Contact_ID, Mobile_Phone, Image_GUID and the user's security roles and user groups to the client. Nothing displayed them, and roles/groups describe the domain's security setup. MPUserProfile is now First_Name, Nickname, Last_Name and Email_Address; UserService selects only those, maps the row explicitly, and drops the two dp_User_Roles / dp_User_User_Groups queries. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Address-label limits/schemas/zip guard, barcode log shape, global-error, safe recordDescription decode, codegen escaping, and the trimmed MPUserProfile (single dp_Users query, no roles/groups). Also corrects tool-params.md claims already stale (NaN handling, page-data log). Deletes .claude/TODO/2026-09-30-step8-fork-specific-low-risk-items.md and updates INDEX.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Closes the Step 8 TODO from the 2026-09-30 playbook audit. One commit per item.
Summary
Address labels (
5f20cbd,9cc2879)schemas.ts→parseLabelInput): at most 10,000 labels, bounded strings,serviceTypelimited toSERVICE_TYPES, andbarStates/barTypedropped (only the server computes those). A sharedprepareLabelshelper also capsstartPositionat the stock's labels per sheet. It's a count of blank cells, so before this it was an unbounded page count.src/lib/zip-guard.ts): reads the central directory itself before PizZip sees the file. It caps the number of entries (1,000) and the declared uncompressed total (64 MB), then inflates each entry withmaxOutputLengthset to its declared size, so a header that lies about its size fails fast. PizZip only checks sizes after inflating each file fully into memory.experimental.serverActions.bodySizeLimitgoes from the 1 MB default to 4 MB, just under Vercel's 4.5 MB request cap. The old 5 MB check could never fire. All limits now live inaddress-labels/limits.ts, shared by client and server.preEncodeBarcodeswas logging label names and ZIP/routing digits on encode fallbacks. It now logs{ labelIndex, error: <name> }.App (
5f3992b)global-error.tsx: adds a plain<a href="/">that works without JS. "Try again" stays disabled until hydration (useSyncExternalStore).tool-params.server.ts: a stray%inrecordDescriptionthrewURIErrorand crashed the tool page. It now falls back to the raw value.Codegen (
efa6923): every MP metadata value interpolated into generated types goes throughcodegen-escape.ts(propertyKey,commentText,positiveInt). Before this,col.Sizewent into the Zod.max(...)calls as raw code. Output is unchanged for ordinary metadata.SQL (
e181994):api_dev_GetProcedureDefinitionnow takes@DomainID INTfirst;_INSTALLregenerated. It must be re-deployed to MP.Profile (
7f22608): theMPUserProfilesent to the client is nowFirst_Name,Nickname,Last_Name,Email_Address. That dropsUser_ID,User_GUID,Contact_ID,Mobile_Phone,Image_GUID, roles and user groups, none of which were displayed.UserServiceruns one query instead of three.Docs (
docs:commit): reference docs updated; TODO deleted andINDEX.mdupdated.Notes / follow-ups
.docxreturned as base64 could exceed it. This PR doesn't address that.UserMenuisn't rendered anywhere at the moment, so the profile trim has no visible effect today.Test plan
npm run lintnpm run typechecknpm run test:coverage: 2161 passed, 99.12% statements. New: zip-guard unit tests against real archives, a merge integration test with real PizZip/docxtemplater (sample template merges, forged-size bomb rejected), label-validation tests, global-error SSR test, codegen-escape testsnpm run build(production build succeeds with the newnext.config)🤖 Generated with Claude Code