Artwork first. Native transfer still separate.
Current local screen: 8 October 2026. No live Shopify or Gelato configuration is changed.
Shopify Files hosting — implemented locally, uploads disabled
The server-only adapter uses pinned Admin GraphQL 2026-10: staged target → unchanged finished print PNG → fileCreate → read until READY → final Shopify CDN URL. It never uploads the original artwork, mockup, thumbnail or supplier guide instead of the placed export. The final CDN file must pass the exact export checksum; image processing that changes the bytes blocks handoff. No live upload has been authorised or performed.
Shopify Files are public-by-possession, not private storage. Random filenames contain no prompt, customer or product information. Immutable revision/checksum associations remain in the private server ledger. Retrying the same export reuses its verified file; a new design revision gets a separate random file even if the image bytes are identical. Failed/uncertain writes are retained and never blindly retried. Known PROCESSING file IDs can be polled read-only. No file replacement or deletion is implemented.
CustomPrintFile stays public in Shopify cart data and contains only the final READY CDN URL. Internal metadata stays underscore-prefixed. The local shared cart/drawer renderer explicitly hides both, without deleting properties or touching native Gelato preview/Edit behaviour. That theme patch is not deployed. Hiding properties is not proof of analytics privacy.
- Privately configure an existing authorised Shopify Admin app token as
SHOPIFY_ADMIN_ACCESS_TOKENin the ignored server.env. Theme CLI login and the OpenAI key are not substitutes. Do not create credentials or change app permissions without approval. - Run
node --env-file-if-exists=.env check-shopify-files.mjsfor a read-only app identity, granted scopes and Files query. Preferwrite_files; if existing file-creation permission is insufficient, request that precise scope/reauthorisation instead of broad product, order or theme access. Current local credentials/scopes are unverified. - Keep
CUSTOM_SHOPIFY_FILES_UPLOAD_ENABLED=falseandCUSTOM_SHOPIFY_FILES_UPLOAD_CAP=0. The browser has no hosting or commerce endpoint. A separately approved operator-only test can invoke the existing server-owned export registry once, with the exact synthetic revision and an approved lifetime attempt cap. No arbitrary browser URL or print bytes are accepted. - Retention is metadata only: configurable unpurchased period (default 30 days); purchased files at least 90 days after verified order creation. Any future deletion requires fresh checks for all active/unfulfilled references. Nothing is deleted now.
The next live check requires a working authorised Admin token and explicit approval for one synthetic file upload. Verify the resulting file ID, READY state, CDN PNG bytes/dimensions/alpha and checksum before preparing any basket payload. Gelato field configuration, exact template/front assignment, native/external precedence, fail-closed artwork behaviour, an isolated safe order hold and actual production proof remain separate approval gates. Paid AI, live basket transport, checkout and fulfilment remain disabled.
Local OpenAI integration — one authorised browser test passed
On 7 October 2026, one real robot-artwork request succeeded using the approved configuration, with zero retries. The 1024×1024 PNG contains actual transparent pixels; history, original checksum and local Black/M placement survived design switching and refresh. Paid generation is disabled again and the one-attempt allowance is exhausted. This is not production or Gelato-transfer approval. Returned usage: 108 input text tokens and 439 output image tokens; the billed amount is unverified.
Demo and Live are separate. Demo loads the retained samples and never calls AI. Live uses the official server-side OpenAI Image API adapter; no other model or sample is substituted on failure. Original returned PNG bytes, separate thumbnails, actual alpha, dimensions, SHA-256, model/settings, creation time, safe request ID/duration and returned token usage are retained. “Use this design” feeds the original into the existing local Black/M placement engine. Checkout and automatic native transfer remain disabled. No prompt, image, private link or raw provider-error logging; no analytics. This is a single-owner loopback development tool, not a public multi-user AI backend.
Local setup — paid generation stays off until separately enabled
- Use Node24 or newer. In
prototypes/ai-tshirt, runpnpm install --frozen-lockfile --ignore-scripts. The official OpenAI SDK is pinned to7.30.0. Existing local Sharp image validation is retained. - A private
.envis now configured locally. On a new installation, copy the placeholder-only.env.exampleto.envand enterOPENAI_API_KEYonly there. Do not overwrite an existing private file. Do not put the key in a browser, chat, screenshots, frontend environment variable or Git. Both the file and local runtime storage are ignored by Git and blocked by the static-file allowlist. - Keep
CUSTOM_STUDIO_LIVE_ENABLED=false. The 7 October one-attempt approval has been used; the retained ledger contains one successful job. Do not raise limits, delete ledger rows or enable another paid attempt without separate owner approval. Default private-file configuration is disabled/cap0; the running disabled service also retains the exhausted cap1. - Start with
node --env-file-if-exists=.env server.mjsfrom that folder. Only127.0.0.1is bound; usehttp://localhost:4187/consistently to retain the same browser history. - For a separately approved future live session, use the locally generated
.studio-private/access-tokenin the local unlock field. This is not your OpenAI key. It creates an eight-hour HttpOnly/SameSite session with an independent CSRF token. Do not share it. It is not printed by the server.
Approved server-only settings: gpt-image-2.5-flare, one1024×1024 image, medium quality, PNG, requested transparent background, moderationauto. Actual transparency is inspected rather than assumed. See the official Image API schema and model documentation, checked7October2026; installed SDK types support these values. An inaccessible model or unavailable billing is an explicit error, not a substitute.
Cost, recovery and privacy boundaries
Each job reserves capacity in the private SQLite ledger before its sole provider attempt. The lifetime cap persists across restarts; the hourly cap and one in-flight limit are shared across processes using that ledger. SDK retries are disabled. Failures, refusals, timeouts, cancellation and uncertain outcomes retain their reservation. Cancel stops accepting a result locally; it does not guarantee avoiding charges. A read-only “Check saved generation” action recovers the existing job/result after a refresh or lost connection without sending it again. An intentional new generation uses a new ID and may incur another charge.
Do not delete or edit the private ledger to retry a job or reset the budget. An interrupted in-flight job becomes uncertain when its deadline expires; it is never automatically restarted. Malformed or unexpected-size results are rejected, without samples. Browser IndexedDB retains history and originals; the private server ledger also retains successful original PNG bytes and safe metadata. Prompt text is kept in local browser design history and sent to OpenAI only for a requested Live generation. Uploads are never AI inputs. No API key or raw provider response/error is stored in acceptance evidence. This local test does not establish public-service retention, multi-user security or print readiness.
Tests and the separate paid smoke test
node --test test.mjs test-upload-fit.mjs test-studio.mjs test-generation.mjs uses only mocked providers and does not read a real credential into a generation client. All31groups pass after the live browser test, including the original20groups. The optional node --env-file-if-exists=.env live-smoke.mjs --approve-one-paid-attempt requires separate approval, explicit enablement, credentials and remaining capacity. It allows at most one attempt per invocation and records a safe summary, never image bytes, prompt or credentials. No separate paid smoke test was run or is authorised under the exhausted browser-test allowance. The browser request's returned token usage is recorded above; monetary billing remains unverified.
Observed native manual route — d7ff86b
The prepared portrait PNG survived manual native upload, native positioning, one quantity-1 cart addition, refresh and Edit design for Black/M at £24.95. A 20mm upward change persisted after saving and reopening. The synthetic basket line was removed. This is not automatic insertion, prototype placement transfer or production-file proof. The evidence and all11 accepted tests remain preserved.
Current blank native layout — owner-reported
The live editor now has a blank personalisation layout without fixed placeholder boxes. It is left untouched. Earlier square-frame padding evidence is historical, not a requirement or reason to restore old placeholders. Optional local prepared-source downloads remain explicitly labelled historical/manual.
Exact unresolved integration
No documented supported automatic insertion method into the current native customer editor has been established in the retained account/support evidence. Native/manual transfer uses source artwork and requires reviewing placement again inside Gelato. Do not inject into its iframe, patch its SDK or supply a shirt preview as production artwork.
Exact connected supplier productUid and production output remain unverified. Retained records contain differing connected-ID interpretations; do not use historical values as fulfilment authority. External-file coexistence, precedence, retrieval/failure safety and scaling remain separate open support questions. No external field is populated and no second fulfilment route is built.
7 October handoff checkpoint — blocked, not an automatic pass
The existing Gelato ticket #141243505 was read again: the 4 October insertion/UID/external-file question and 5 October fitting question have no newer technical answer. The only human reply concerns production review after ordering. A focused question is prepared, not sent. No unsupported connector was built. Automatic artwork insertion is blocked; automatic placement transfer and the robot's native basket round-trip are not tested. The earlier manual calibration round-trip remains passed on its own terms.
A fresh public-product and native connected-row check matches Black/M variant 54847907070289, connected SKU 812c298a-4224-4be1-8ac4-d65fe10f71f0, Gildan64000/DTG and137variants. Current Shopify/Gelato Black/M price is £22.10, not the historical local £24.95 snapshot. No price or saved revision was changed; the discrepancy needs owner reconciliation before any commerce handoff relies on it. Exact connected supplierUID and certified current Front geometry remain unresolved. The old round-trip record accidentally labels the storeID as a productID; the separately verified connected product is bf632a86-7f1c-4f0b-925c-4cf0a4e28887.
Unchanged robot source — print-size diagnostic
The exact original is still1024×1024px, SHA-256 bc7bd49d2a337865ce38d83b2722824b00ba1ff74759d1e18c43575baf331eb1. At the saved100mm square frame,1024×25.4÷100 = 260.096PPI. That frame includes the transparent margins; the faint-inclusive artwork bounds span95.12×96.58mm. The source has675,911fully transparent pixels and372,665partial-alpha pixels; most artwork pixels are near opaque. Nothing was cropped, flattened, resized or thresholded.
300PPI original detail limits the complete source frame to86.70mm square;150PPI permits173.40mm. At the supplier model's304.8mm width it would be only85.33PPI. Current DTG guidance still requires appropriate PNG/JPEG and sRGB preparation, with150minimum/300recommended resolution and caution for semi-transparent art. The file has no embedded colour profile or density chunk; a decoder's default density is not print sizing. No print-readiness claim is made.
Separate external-file alternative — outline only
Gelato documents an order-line print-file URL property, not an editor insertion interface. A future route would validate ownership, immutable revision, exact Front mapping, source-to-print transform and separate artwork-only export/checksum; provide separately approved secure retrieval; and bind that file to the eventual Shopify order and line, with one fulfilment route and idempotency per line. Native/external precedence, absent/invalid/expired file behaviour, retrieval timing and scaling must be confirmed first. No field, hosting, approval setting or second order-submission service was enabled.
Versioned calibration — exact template verified, connected binding still open
The original supplier ZIP is retained unchanged with its source and SHA-256. Independent inspection confirms PDF MediaBox and ArtBox864×1152points, PSD1800×2400pixels at150PPI, PNG1800×2400pixels and the visible12×16inch all-sizes Front/Back guide. The exact model-template canvas is 304.8×406.4mm; its calculated300PPI export grid is3600×4800pixels. No guide artwork, shirt diagram, inferred collar offset, safe inset or new Back permission enters the print pipeline.
New profile gildan-64000-front-supplier-template-v2 is registered for isolated calculations but is not the default. The connected Black/M Front/DTG identities are recorded separately; the current supplier productUid and exact template binding remain unresolved. The ZIP does not supply that association. Transport stays disabled and neither profile is production-approved.
Existing designs retain black-m-front-native-ui-nominal-v1:305×406mm and3602×4795pixels. Reopen, bounds, preview, movement and export now use each saved design’s own profile snapshot; saved mapping metadata and millimetre placement also remain unchanged. Unknown or conflicting profiles are blocked instead of silently resized. Profile-less legacy records have an explicit nominal-v1 compatibility rule. No automatic migration, centring, crop or conversion is provided.
Effective resolution still uses original pixels divided by placed physical size. Square artwork stays square. The existing1024×1024robot at100×100mm remains260.096PPI after refresh, on revision3. Template/export pixel counts do not add source detail. 41automated tests pass, including all31previous groups; no paid generation or store change.
Earlier screenshot calibration evidence — retained history
The owner's5October screenshot shows Gildan64000/Front/DTG, selected artwork305×406 and300DPI, with the Rs Sport Grey group highlighted—not an individually selected Black/M. The retained portrait PNG really is3600×4800pixels. Read-only exact Black/M inspection confirms centimetre rulers at30.5×40.6; retained Properties labels size/position in millimetres. Rounded labels and inset markers do not prove exact edge-to-edge fill. Literal305×406 differs from the exact model template by+0.2/−0.4mm; source-axis resolution299.803/300.296PPI can still display300. This historical evidence is preserved; only profile-aware local handling is added in the current pass.
All31 existing automated groups still pass using mocked providers only. No adapter tests were added because no supported adapter was implemented. Paid generation remains disabled, the ledger retains one successful attempt, and no new provider request or native basket action occurred. Server credentials/model access were demonstrated by the accepted one-request test; they are no longer missing setup. Automatic Gelato transfer, production verification and any future paid-test approval remain separate.
Retained 4 October evidence — superseded where the current results above differ
The following is historical evidence, not a current instruction or description of the updated local screen.
DOCUMENTED
Native PNG upload is a supported way to use an image in the existing editor. Positioning must be reviewed again there; prototype placement does not automatically transfer.
Gelato's external print-file route reads line_items[].properties[].name matching the store's configured Print file field name, with the full file URL in value. There is no universal field name. “Preview” is merely a documentation example—not permission to send a shirt mockup as artwork. Gelato documents retrieving the file and displaying it in order details, including automatic-approval workflows.
OBSERVED
Rechecked 4 October: Custom T-Shirt 11125948350801; Black/M 54847907070289, £24.95. Native Gelato product bf632a86-7f1c-4f0b-925c-4cf0a4e28887; matching connected variant/SKU 812c298a-4224-4be1-8ac4-d65fe10f71f0; Gildan 64000 / DTG. No identity or price was changed.
The exact-model catalogue links a supplier template explicitly specifying 12 × 16 inches maximum print area, all sizes: 304.8 × 406.4 mm. Its PDF is also 864 × 1152 points. A 300 PPI full-area canvas would therefore be 3600 × 4800 pixels (calculated); the supplied instructional PNG is 1800 × 2400. Remove every guide layer from artwork. The supplier warns of small physical placement variations. This proves model-level maximum geometry, not the current connected UID or automatic insertion rules.
Accepted prototype geometry remains frozen. Commit 732258c and its eight passing groups are closed. Existing sample exports use nominal 305 × 406 mm / 3602 × 4795 pixels and are not production-approved. They have not been relabelled, resized or silently reinterpreted. A future exact-geometry revision must handle saved-spec versions explicitly.
The retained account check shows external Print file field name empty and approval Automatic / instantly. Neither was changed. The separate 2 October native Gelato account-check evidence was reused.
MANUAL HANDOFF — contained attempt
A separate Incognito session opened the correct Black/M product and native editor, with optional analytics declined. The original synthetic calibration PNG was selected for the test, but the operating-system picker did not complete upload after two attempts. Jonny was asked to cancel that dialog and close only the isolated window; he acknowledged the request. No Continue to cart, checkout, order or draft-order action occurred. No completed image transfer, orientation, scale, crop or front-placement pass is claimed.
The next native test uses original source artwork, positioned and reviewed inside Gelato—not the shirt photograph and not a pre-positioned full-area canvas. Prototype placement does not automatically transfer. Do not apply placement twice. Stop before Continue to cart.
STILL UNVERIFIED
- A supported programmatic insertion API for this customer editor has not been established. No iframe or SDK workaround was attempted.
- Current connected
productUid. The current catalogue Black/M UID containsgpr_4-0; the historical connected candidate containsgpr_4-4. Neither proves the current connected value, so the active field remains null. The existing key is active but its secret is not re-displayed; no new key was created. - Supplier template applicability to that connected UID, exact collar offset/bleed rules, and native upload handling of scale/crop/transparent margins.
- External-file versus native Personalization Studio precedence, per-area placement/scaling, URL retrieval/expiry/retry and whether missing artwork fails closed rather than printing default artwork.
- Corresponding order production output. No order was created; previews are not production proof.
Revision and file contract
Every local design has its own prototype-only ID and append-only revisions. The downloadable manifest ties source SHA-256, dimensions, placement in millimetres, print-area specification, export SHA-256 and Shopify/Gelato identities together. Native customization ID, eventual Shopify order/line IDs and transport route remain null. The shirt preview has a separate checksum and is explicitly not print artwork.
A future server must authenticate file ownership; recheck the current mapping, geometry and approved immutable revision; validate the fetched bytes; and enforce one fulfilment route per order line. Browser properties are not trustworthy fulfilment authority. No native design identifier may be fabricated.
Next transport test — separate approval
The authorised focused enquiry was sent on 4 October to existing Gelato ticket #141243505, covering current connected UID, native insertion, external/native coexistence and precedence, absent/invalid/expired/unreachable files, Front scaling and an isolated submitted-order review without production charges or whole-store approval changes. Response pending. One documented connected-product GET returned 401 Unauthorized because the existing API secret is unavailable locally; no mapping failure is inferred. The original calibration PNG and exact Black/M URL have been supplied to Jonny for manual upload; inspection is pending. If an order is required, obtain its complete current charge and a supported safe review/hold stage before requesting separate order approval. Do not change the current automatic-approval setting or populate the external field now.
Paid AI stage — separate approval
Approve a provider, capped spend, content/ownership rules, privacy/retention and moderation. Keep credentials server-side. Prepare the source for print and validate its resolution/alpha/colour before review; a raw generated image is not automatically print-ready. No paid AI, new app, subscription or remote artwork processing is connected here.
Historical review limits
The shirt photograph is the existing exact supplier blank. The flat overlay registration is illustrative, not a verified physical placement simulation. Original flower/calibration fixtures and the existing owned demonstration pet image are not customer examples. The former static-only server rejected every non-read request. Saved samples remained in this browser. Mobile-width checks were not physical-phone or production tests.