Above 150 MB the browser cannot read JPG or WebP in parts, so a large
artwork was refused. It is now measured from its header, graded and priced
with the discount like any other, and placed on the sheet as a full box,
which is exact for JPG. The card says there is no preview and that the team
checks the art before printing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The product page is rebuilt around mockup 1. The two ways to send are
cards under the title; the PNG/CDR route choice is gone (it never changed
the price, and the picker now takes every allowed format). Each file card
has a thumbnail, its size, check chips with a plain sentence for any
problem, a "Ver detalhes da conferência" link and a copies stepper; a CDR
file says "Conferência manual · preço cheio" and asks for the length. The
buy box shows the price scale in DPI with the customer's step, the metre
and 10 cm length, the total and what the resolution saved, and "Sai em N
partes" only above 20 m. Folha já montada gets "Ampliar" instead of zoom.
Pricing, grade and checks are unchanged.
Fixes on top: the card thumbnail is a small image made once, not the full
preview re-parsed on every repaint; sizes from 1 GB up read in GB; a failed
upload is shown with "Tentar de novo" instead of retrying silently on every
cart change. The browser suites wait for the product and the reloaded page
instead of racing them, and the artwork suite delays imagemDaArte, which
the packing now uses, fixing the CI failure of f4aacb5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A complete CEP now looks up its address on the server (ViaCEP, rate
limited, keeping the Site's CSP to its own origin) and fills street,
district, city and state, moving the cursor to the first field left, and
quotes the freight without pressing Calcular. The CEP keeps its mask when
the cart is restored. Freight and its delivery time appear in the order
summary instead of a line under the CEP, the delivery option says it ships
with Jadlog, and the address reminder is a hint rather than an error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each cart item has a visible "Remover" button instead of a faint ×, and
carts with two or more items get "Esvaziar carrinho". Both show a
"Desfazer" notice for 8 seconds, so a wrong click costs nothing. The
browser test covers remove and undo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Week 2 work that did not need client inputs.
Print files (1.4): each paid item gets a PDF the width of the film and the
length of the approved layout, with every copy at its reviewed position,
rotation and mirror. Sources are embedded once at original resolution; JPEG
bytes pass through and PNG alpha becomes a soft mask. Artwork the generator
cannot reproduce goes to hand preparation with the reason. The worker renders
outside any transaction, and the operator approves the generated file as the
final one through the existing review.
Delivery address (3.8): required for any non-pickup quote, bound to the
quoted CEP, carried into the order snapshot, the Kanban card and Tiny.
Kanban (1.5): print-file status per item, and a panel of payment events that
need a person (money without an order, refunds after an order) until an
operator records the resolution.
Mercado Pago and Tiny (1.1, 1.3): adapters written from the public API
documentation and tested against fake transports only. Selectable for
sandbox testing with their credentials; the production preflight still
blocks release. Adds payment intents and a PIX step on the Site.
MinIO: Docker Hub and quay.io now refuse anonymous pulls, so local and CI
storage use Chainguard's MinIO build, pinned by digest.
Verified with the full CI integration sequence on a fresh local build,
including the new print_file_test and both browser suites.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Site's page sat at the repository root while its scripts lived in
local/static, a split with no reason behind it. They are together in web/ now,
with the page as index.html, which is also what the image serves.
app.py held the adapters, the configuration, the shared query helpers and
nineteen routes; customer.py held fourteen more but could not import from it
without a cycle, so it was wired by passing nine callables into install_routes.
Configuration and shared helpers move to local/runtime.py, the rules for
attaching artwork to an order move to local/artwork.py where a customer
correction and an operator final-file set can share them, and the routes become
seven routers under local/api. app.py is 48 lines that create the application,
apply the middleware and include them. Routers import downwards only.
Three faults came out of the extraction and are worth recording, because each
passed a check that looked sufficient. ast reports a function's line at the def,
so every decorator on the line above fell outside the extracted range: twelve
routes and the security middleware were defined but never registered, and the
files still imported and parsed cleanly. Names the old closure renamed on the
way in, and a Jsonb import, were missing in three modules. A name-resolution
pass over every new module found those; the route count matching the original
exactly, 32, is what confirmed the first.
The release gate's marker for the fake payment adapter pointed at app.py and the
adapter moved to runtime.py, so the gate passed while the condition it guards was
unchanged. That is the same silent decay 2.5 set out to fix. A test now asserts
every marker still matches something in its file, so the next move fails loudly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>