Every change we ship to katura1999.com — features, fixes, security patches, the lot. Pulled straight from our private GitHub repository so you can see exactly what was built and when.
By the numbers
Lines of code
943,828
Web platform — TypeScript, React, Prisma, CSS
iOS
79,607
Swift + SwiftUI lines
Android
3,117
Kotlin + Jetpack Compose lines
All platforms
1,026,552
Web + iOS + Android combined (51.0× the King James Bible)
Characters written
40.17M
40,168,559 total characters
Updates pushed
2,265
exact commit count on main
Current version
v1.22.65
build 2265 · d89cabc
Database models
420
across 47 schema files — most SaaS platforms have 20–50
API endpoints
1,052
individually routed — Stripe's public API has ~400
Translated strings
90,960
every string, in 24 languages
System permutations
10^316
2^1,052 endpoint combinations — more than atoms in the observable universe (10^80)
Project age
9mo 16d
since Dec 14, 2025
Pre-AI dev hours
34.2K hrs
1,026,552 lines ÷ 30 LOC/hr — equivalent to 16.5 years (senior engineer, no AI)
With-AI dev hours
8.6K hrs
4× AI productivity multiplier (2024–2026 studies) — equivalent to 1,069 days
Equivalent firm cost
$8,963,364
live ticker · Katura rate: $60 USD/hr
Hours estimated from source line count at 30 LOC/hr (industry benchmark for production-quality TypeScript/React without AI assistance), with a 4× multiplier for AI-assisted development per published 2024–2026 enterprise studies. Equivalent Firm Cost uses a $250/hr loaded billable rate reflecting a premium engineering firm building enterprise-grade SaaS — and ticks up live, because the project is still being actively built.
Commit history
2,265 updates pushed
Showing page 1 of 40 · 1–50 of 2,000 fetched
Friday, September 25, 2026
15 updates pushed
Featureanalytics5:32 PM · ZRosserMcIntosh
send GA4 hashed user-provided data for enhanced conversions
GA4 Data collection flagged the property as urgent: user-provided data
collection is on, but the site never sent any. The purchase, both
consultation bookings and signed-in customer pages now call
gtag('set', 'user_data') with a SHA-256 email, and a phone number when it
is valid E.164, normalized to Google's rules. Staff browsers, internal
emails and back-office routes send nothing. The purchase still fires once,
manual ShipStation label purchase from admin → Orders
lib/shipstation/v2.ts: API v2 client (API-Key header, overridable base URL, timeouts, typed errors, no key in logs): carriers, warehouses, rates, rate by id, buy label from rate id (pdf/4x6, idempotent pre-check via GET /v2/labels?rate_id=), owner test label (POST /v2/labels test_label), get label, void.
label-builder.ts: jewelry package presets, signature default at/above $500 (domestic), ParcelGuard/carrier insurance at merchandise value, customs products from order items (HS 7113.19 / 7113.11, origin US), Brazil CPF/CNPJ as recipient tin, rate table (media mail dropped, USPS jewelry restrictions flagged, carrier errors listed).
label-policy.ts + label-service.ts: buy/void need MANAGER or OWNER (requireKaturaAdmin admits EMPLOYEE), test labels OWNER only; price re-read from ShipStation must match the confirmed price; one active label per order unless "Buy another label"; per-order lock and per-attempt claim (ShipmentEvent unique eventId) so double clicks replay; timeouts become UNKNOWN and "Check again" reconciles by rate id without buying. Shipment row + SHIPPED status like the manual route; void reverts status; every purchase, failure and void is audit-logged with cost and actor.
One route file: /api/admin/orders/[id]/ship gains GET (panel context, label/customs PDF proxy), POST actions rates|buy|email and DELETE (void); manual "Mark as Shipped" unchanged.
Shipping email moved to lib/shipping/shipment-email.ts; label emails are claimed per shipment so they go out at most once.
Admin order page: Shipping label panel (en/pt/es); voided shipments are hidden from the customer order page.
Casting jobs: EasyPost buy is now quote → confirmation dialog with the exact rate → buy that rate; MANAGER/OWNER only.
Stripe webhook: drop both fire-and-forget exportOrderToShipStation calls (checkout.session.completed and payment_intent.succeeded), with a comment. They used the v1 API, which production cannot authenticate to (no SHIPSTATION_API_SECRET), so no order was ever exported.
Remove the /api/cron/shipstation-sync schedule and route (export + v1 shipment polling), its call from /api/cron/daily and the synthetic probe.
Delete dead v1 code left without callers: lib/shipstation/export.ts, lib/shipstation/index.ts, /api/admin/shipstation and the unused ShipStationStatus component. client.ts, fulfillment.ts and notifications.ts stay (the SHIP_NOTIFY webhook, dev test panel and Virgil still import them).
Synthetic ShipStation probe now checks GET /v2/carriers with API-Key.
vercel.json: 60s maxDuration for the order ship route (label purchase).
on-demand, cached translation of product descriptions
ProductTranslation model + hand migration 20260925_product_translations (NOT applied). Until it is, the cache read fails and pages show English without calling the API.
src/lib/i18n/product-translation.ts: locale normalization (website + app codes), sha256 sourceHash so edited English re-translates, ACTIVE public products only (English re-read from the DB), structured output, in-instance dedupe of concurrent misses, 6 s wait with after() finishing and saving slow translations, per-IP 'product-translation' rate limit on misses only (30 / 10 min), never throws.
PDP: translated short/long description with lang=, "Translated from English" note (all 24 message files), translated copy in meta/JSON-LD.
GET /api/products/[id]?lang=: translated copy under the same keys plus translatedFrom/translationLocale; English-while-pending is no-store so the CDN never pins English under a language URL.
Admin product PUTs delete a product's translations when its English copy changes.
Pix confirm, own-hold quotes, releasable checkouts, BR número
Pix PATCH confirmed without a return_url. For an intent created with automatic_payment_methods, Stripe refuses a server-side confirm that has none, so iOS Pix could never have issued a code. The confirm now sends one. Pix never redirects, so the URL is never visited.
A Pix code was always valid for 30 minutes, whatever the intent's age. The cleanup cron runs every 15 minutes, so an intent can still be unconfirmed at about minute 35. A code issued then would still be payable after the sweeper cancels the intent at 60 minutes. Expiry is now capped at 5 minutes before that cutoff. If less than 10 minutes would remain, PATCH refuses with PIX_CHECKOUT_EXPIRED and the app starts a new checkout. A PATCH on an intent that is already paid returns 200 {status:"succeeded"}, so the app can finish the checkout, instead of 409.
ring sizes start at 5; stop defaulting and re-flagging one-of-one
Customer size pickers (PDP, design-your-ring, engagement design, ring builder, app config) start at US 5. Staff preference records keep the full range because they capture real measurements.
'One of one' meant 'one in stock', not 'cannot be made again'. New products default to false (form, admin API, schema default + migration), and the admin update route no longer sets it to true whenever an edit omits the field — that would have re-flagged every product on save.
Apple Pay quotes counted the shopper's own stock hold against them. A one-of-one they had just reserved through the form read as out of stock, and every Apple Pay address was refused. Quotes now exclude what the real call would free first: this customer's own pending holds (same user or email) and any expired holds.
New DELETE /api/create-payment-intent, in the same route file (no new route). The app abandons a checkout by client secret, for example on a switch to Apple Pay, a refused express total, or cancelling a Pix code. The server cancels the intent, including a live Pix code, and frees the hold. Processing or paid intents are never touched.
Errors the app shows now carry a machine code (OUT_OF_STOCK, EMAIL_INVALID, INVALID_REQUEST), so the app can show its own translated text.
Countries with no postal codes (UAE, Qatar, Hong Kong...) no longer need one here, in /api/user/addresses or on the web form.
The web checkout gets a Número field with "No number" for Brazil and Portugal. The CEP lookup fills only the street name, so orders could go out with no house number. Line 1 is sent as "Rua, 123" or "Rua, s/n". New strings are added in all 24 languages.
/admin/ios (listed under Core): hero slide editor with real photos or video per piece/collection, caption, sub-caption and autoplay; Featured picker with editable title; per-piece video mode (autoplay, tap to play, photo only); per-collection cover picker; shelf order and visibility; phone-frame preview; published timestamp. en/pt/es copy.
Publishing is a server action on the page itself, so the feature adds only two routes (the page and the public endpoint) against Vercel's route cap. Managers and owners publish (requireKaturaAdmin admits EMPLOYEE by default); employees with Products access can view. Saves are audit-logged with old and new values, and a save over someone else's newer publish is refused instead of silently overwriting it.
GET /api/app/home resolves the stored ids against the live catalog on every request: only ACTIVE public pieces (no custom-ring orders, no Trunk Show specials), photos/videos must still belong to their item, deleted collections drop out, new collections join the shelf order. Edge-cached for a minute; returns configured:false on failure so the app keeps its built-in Home. The resolver is pure and unit-tested.
Pix for the iOS app, BNPL for US orders, Apple Pay quotes
PATCH /api/create-payment-intent confirms an existing checkout PaymentIntent with Pix server-side (CPF/CNPJ validated, client secret as the credential) and returns the QR / copia-e-cola code. Same order, same webhook. Codes expire after 30 min, inside the reservation sweeper's in-flight grace, so the sweeper never cancels a code still being paid.
POST now returns the intent's resolved payment_method_types, so the app offers Pix only when Stripe really made it available (dashboard setting, BRL, under the 3,000 USD Pix cap).
POST { quoteOnly: true } prices the bag for a partial address with no side effects (no customer, order, hold or superseding). The iOS Apple Pay sheet uses it to show the same shipping/tax/total the charge will use. Own rate-limit bucket so re-quotes never eat the checkout allowance.
House allowlist: opt-in BNPL (affirm, klarna, afterpay_clearpay) for USD product orders. They settle to the house in full on success, so they pass the settled-funds rule; gift-card purchases do not opt in (providers prohibit stored value). Stripe enforces each provider's amount window.
Webhook records payment_intent.processing as Payment PROCESSING.
Web Payment Element lists Apple Pay / Google Pay first, adds Klarna to the USD order.
Sign in with Apple and Google for customers, web + iOS
One resolver (src/lib/oauth/identity.ts, rules in identity-decision.ts) for web and native: existing identity -> sign in; signed-in Connect -> link; verified email match -> auto-link; else create a CUSTOMER with emailVerified and the register side effects (no newsletter, no WELCOME100). Staff / platform / non-zero-tenant / SaaS-owner / support-IT accounts are never signed in, created or linked.
NextAuth: Google and Apple providers register only when their env vars exist; the signIn callback runs the resolver before Auth.js's second getUserByAccount, and the adapter's createUser/linkAccount now refuse to run. Apple client secret is an ES256 JWT signed from the .p8. state/nonce/PKCE (and callback-url) cookies are SameSite=None in production for Apple's form_post; the session cookie stays Lax.
POST /api/auth/mobile/oauth: verifies Apple/Google ID tokens (jose, remote JWKS, iss/aud/nonce), exchanges Apple's authorization code for a refresh token, and mints the same NextAuth session cookie a browser sign-in gets.
/api/account/sign-in-methods (GET, DELETE /{provider}, POST link-intent); change-password lets passwordless accounts set a first password; account deletion and unlinking revoke Apple tokens.
/api/app/storefront gains auth flags; login/register get provider buttons and settings a Sign-in methods card (en + pt strings).
Customer OAuth errors bounce from /employee-login back to the page the customer started on.
use Stripe's decimal rules for Stripe amounts, not the display flag
STRIPE_ZERO_DECIMAL_CURRENCIES: bif clp djf gnf jpy kmf krw mga pyg rwf vnd vuv xaf xof xpf (UGX, though on Stripe's list, is represented two-decimal with "00" for backwards compatibility).
STRIPE_WHOLE_UNIT_CURRENCIES: huf twd isk ugx — ×100, whole units only (amount divisible by 100).
Everything else (incl. IDR) ×100. toSmallestCurrencyUnit / fromSmallestCurrencyUnit delegate to it; `zeroDecimal` in config stays for display and rounding only.
create-payment-intent (via toSmallestCurrencyUnit) and the webhook inverse.
/api/checkout/order/[orderId]: also charged the USD Order.total under the order's foreign currency code; now charges chargedAmount in that currency, else the USD total in USD.
SalesInvoice public payment, quick-invoice, signatures (PI + Checkout), whose "cents" are major × 100 in every currency: converted at the Stripe boundary (internalCentsToStripeUnits), and Stripe amounts recorded back into SalesInvoice (webhook invoice.paid / sales_invoice_public, sync-stripe) via stripeUnitsToInternalCents.
Casting order pay + refund, and order refunds (a USD refund on a non-USD order is now the same proportion of chargedAmount, in that currency). USD-only paths (Checkout Session, mobile PaymentIntent, gift cards, deep diagnostic, SaaS billing) are unchanged. The iOS app never computes Stripe units (PaymentSheet uses the server's PaymentIntent).
stop advertising a smart-link CAPI ViewContent that no longer fires
"CAPI ViewContent on click" badges removed (list + detail)
the detail page's ON/OFF toggle for fireViewContent is replaced by a note saying what the link does now (click cookies + click log) and that ViewContent comes once from the landing product page
"CAPI fire rate" KPI removed (it would read 0% by design); the list view shows avg time on page instead, now that durationMs is recorded
recent clicks no longer flag new clicks "no CAPI"; old clicks that did send one show "server VC (legacy)" The fireViewContent column and API field are kept, just no longer surfaced.
social-proof line reads the real ProductView columns, never blocks
one query for the 30-day and 7-day distinct non-bot viewer counts, scoped to tenant zero, excluding rows written by local dev servers (pageUrl on localhost) so test traffic cannot inflate the number
2 s timeout; any failure or malformed id returns the empty result with 200 (the component renders nothing) and logs a safeLog.warn
CDN-cacheable (s-maxage 300 with a line, 60 without)
copy rules moved to buildSocialProof (unit-tested); every number shown is a real distinct-visitor count, "100+" is a true lower bound, and nothing is shown when there are no real viewers
identify server events and persist the funnel first-party
the client now sends its first-party visitor id (katura_visitor_id), referrer channel and first-touch UTMs with every /api/tracking/* call and with POST /api/cart (getTrackingContext)
ViewContent / AddToCart / InitiateCheckout / Purchase CAPI calls add the signed-in user's email and id via auth(), plus the visitor id, as em / external_id
view-content → PRODUCT_VIEW
POST /api/cart and add-to-cart (quantity increases) → CART_ADD; the two paths are disjoint, so nothing is counted twice
purchase → CHECKOUT_COMPLETE, built from the Order (USD total, paid status), at most one per order
initiate-checkout writes nothing: /api/analytics/checkout-start already records the deduplicated CHECKOUT_START the admin funnel reads; it now also stores visitor id, channel and UTMs No migration: the enum already has PRODUCT_VIEW, CART_ADD, CHECKOUT_START and CHECKOUT_COMPLETE, so the Meta-style names map onto those.
drop GTM and send pixels, gtag and CAPI from the storefront only
layout: tags render only for a tracked request host, and each inline bootstrap re-checks location.hostname
sendCapiEvent drops any event whose sourceHost (request host) or event_source_url host is not tracked — covers the /api/tracking/* routes, the cart route, the marketing Lead and the Stripe webhook