Introduction
I added optional per-book QR page configuration to a print generation pipeline. Before this change, print books had pen-name branding defaults but no way to attach a custom QR page to an individual book. I kept the new configuration separate from those shared defaults. Each book can now carry its own qrPage object, stored in a new nullable JSON column on the BookGeneration table and surfaced in the branding step before payment.
The change leaves the existing page-count and pricing defaults unchanged. That describes the configuration boundary, not a verified physical pagination result. I have not verified how a completed QR page fits into a finished book. What is supported is the per-book data path and its validation rule; actual print rendering and end-to-end behavior still need separate verification.
The Rule That Shipped
qrPage is optional. If it is supplied, however, it must include title, text, url, and closingText, and all four fields must be non-blank. Any blank field produces an error message instead of being accepted as part of an incomplete QR page. Leaving out the object is therefore different from supplying one with blank content.
I chose to store the object on the book generation record rather than make it part of pen-name branding. The nullable JSON column holds the optional per-book configuration without changing existing page-count or pricing defaults. Although the configuration appears in the branding step before payment, it is not a shared branding default. Where the interface presents the data and which record owns it are separate decisions.
The documented contract requires those four fields and rejects blanks. It does not define the exact error response, how blanks are classified, or any additional URL-format checks. The four-field rule should not be read as establishing those details.
Worked Example
Consider a create-job request with a qrPage object whose title, url, and closingText fields are filled, but whose text field is blank. Under the shipped rule, the request fails validation and returns an error message for the blank text field. The other three values do not make up for the missing body content, and the request does not proceed with an incomplete QR page.
This example applies the stated rule; it is not an observed end-to-end test. The evidence does not establish the error's wording or response structure. It also does not show whether several blank fields would produce one combined error or multiple field-level errors.
Filling text as well would satisfy the stated four-field non-blank requirement. That would not, by itself, prove that the whole job succeeds or that the finished book contains a correctly rendered QR page. Making the configuration available before payment is part of the supported change. Rendering it into print output is a separate behavior that has not been demonstrated here.
Challenges and Tradeoffs
The main design decision was to keep per-book configuration separate from shared pen-name defaults. Storing QR data only in shared defaults could couple books that need different content, unless there were an override mechanism. Shared defaults with per-book overrides would be another possible design, but that would require precedence and fallback rules. The documented choice was narrower: store this QR configuration as separate, optional data on each book generation record.
The storage choice is a nullable JSON column. A separate relational record or individual columns would also be possible, but the evidence does not establish their relative delivery cost or suitability for this workload. JSON field queries and indexing depend on the database and its configuration, neither of which is established here. I therefore cannot conclude that reporting would require application-side deserialization or that field-level indexes would be unavailable.
Strict validation sets another boundary. Allowing a blank closingText, for example, would create a different contract in which some page content is optional. The shipped rule requires every listed field whenever qrPage is supplied. Consumers have one completeness requirement to follow, but they must provide all four values even if they would prefer to leave out a closing line. Non-blank validation establishes that content is present. It does not establish layout quality, destination correctness, or successful printing.
Verification Process
The implementation record shows the scoped tasks moving from in progress to done. I also documented the qrPage integration, communicated the required consumer API changes, and finalized front-end guidance for the print-book flow, field requirements, and error handling. Those facts establish implementation status and handoff work. They do not independently show that the schema, validation, and branding interface work together at runtime, or that downstream integration was completed successfully.
The behavioral evidence is more limited. The supported change identifies the storage location, the optional per-book object, its placement in branding before payment, and the requirement to reject blank fields. There is no documented end-to-end test in which a deliberately blank field was submitted and the exact response observed. There is also no evidence confirming an actual print render or a completed QR page in a finished book.
Verification still needs to cover a request without qrPage, the worked blank-text rejection, a fully populated object, and multiple blank fields. Inspecting the responses would establish error wording and whether errors are combined or returned per field. A separate check that the per-book configuration is available in the branding step before payment would test the interface boundary. A finished-book render would then be needed to assess layout and physical pagination. These checks remain open; I cannot claim they were completed.
Conclusion
I added a separate per-book configuration path: an optional qrPage object stored in a nullable JSON column, surfaced before payment, and subject to a strict non-blank requirement for title, text, url, and closingText. The change leaves existing page-count and pricing defaults unchanged and keeps QR configuration separate from shared pen-name branding.
The exact error wording and structure, handling of multiple blank fields, end-to-end execution, and finished-book rendering are not established. Those limits need to stay distinct from the implemented contract so the result is clear without claiming more than the evidence supports.