- add site-settings singleton to admin registry + schema + migration
- add editor config + route + nav in admin frontend
- surface defaultSiteTheme via data-api serialize + shared types + validator
- carry through api /www/provider-config (the public edge-cached path on vps0)
- remove DEFAULT_SITE_THEME hardcode; ultimate fallback luxe-dark; registry comments updated for admin-driven live selector
- live bootstrap in quinn.www root + data hook to pick admin default without quinn.www rebuild (chrome + tokens update post-fetch)
- fixed incidental sortable test assertion to match current registry (pre-existing mismatch)
- other public hardcodes remain in deployment configs; see analysis
This makes the visitor-facing default theme choice Quinn-editable via admin UI and flows as public data through the quinn.api public surface (edge cacheable).
ci.yml already runs the full @features/api suite on every push.
Admin deploy workflows were re-running the same ~130-file DB suite
on the single serial runner, adding 30–45m per deploy and blocking
verify. Keep typecheck, build, and e2e smoke on deploy paths.
Gallery item DELETE calls regenerateManifest(), which requires
PHOTOS_DIR. Point tests at a temp directory in global-setup so the
admin-gallery-items CRUD test does not 500 in CI.
assembleProviderConfig now reads hero_strip_items; admin rate-cards,
site-text, and tour-stops tests were still on stale migration bundles.
www/payment-methods tests must query ?provider=quinn to match repo
defaults. Run each test file in its own bun process so the per-process
throwaway DB does not leak committed fixtures across files in CI.
CI verify was failing on black because integration tests omitted migrations
added after provider-config and admin gallery evolved (payment_methods,
photo_css_traps, analytics_markers). Centralize those bundles and bump
the verify job to 45m with a 90s per-test timeout so the full DB suite
can finish on the single capacity-1 runner.
Use a shared black-${{ github.ref }} concurrency group with
cancel-in-progress: false so the capacity-1 runner executes one job
at a time without cancel churn. Raise ci verify timeout to 30m and
set NODE_OPTIONS heap for verify + quinn.data build (typecheck OOM).
The prod-build-drift report still labeled the m.transquinnftw.com SPA as
quinn.m frontend; rename to messenger frontend to match the product name.
Deploy was failing because npm tried to resolve @lilith/quinn-my-mcp from
Verdaccio even though bun build already bundles it (and ws). Strip bundled
workspace deps before the standalone npm install step.
Adds scripts/prod-build-drift.ts and ./run check:prod-builds to query each
deployed quinn surface's running git SHA (via public health/version endpoints
and SSH build-info probes on quinn-vps/black) and show commits behind
origin/main.
Serialize superseded deploy runs on the capacity-1 black runner —
admin, api, data, newsletter, vip, admin-api, and hotel-scout were
missing the concurrency blocks already used by www/my/ci.
composeOverview omitted sessions (and conversions) from the
DashboardOverview payload, so useDataHealth crashed accessing
sessions.current on Audience/Traffic/Network. Populate both from
session metrics and fall back to visitors in the hook.
Import GeoGranularity from geo.ts (not client.ts) so analytics MCP
typechecks. Tighten contact-form test mailer stub for
exactOptionalPropertyTypes. Replace grep -P in ./run ci:status with a
portable python parser against the Forgejo actions API.
CI verify only typechecked — the contact-form refactor dropped the required
`from` on sendMail (bookings already sets it) and nothing failed. Add the full
@features/api suite to ci.yml and tighten the contact-form test to assert
`from` plus a fire-and-forget flush tick.
GET /api/credentials now returns { total, credentials } via the quinn.api
proxy, but the dashboard still treated the body as a bare array and crashed
with .filter is not a function. Add a shared parser, unit test, and e2e guard.
Introduce a shared magic score picker (geek vs sparkle by theme) wired across
public pages, balance rates incall/outcall columns, and fix pool math to track
actively mounted cards so async-loaded rate rows pick a real index. Adds
Playwright coverage for etiquette and rates hover animations.
- Updated the review doc with precise "what is tested" section based on live execution of wallet.test (5/5 ephemeral DB), contact service test (4/4), new timeout.test (4/4).
- README summary refreshed.
This directly addresses the verification request for unit/snapshot/integration/ephemeral DB proof of the claims.
2b (G9 idempotency) deployed to black; 2c (nginx failover) live and verified
end-to-end (normal 201 / black-down 202 -> spool -> replay -> G9 dedup). Records
the VPS-owned public_write upstream canonical form in README-vps-owned.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New file: vip-feature-review-payments-security-ux.md (detailed review + mermaid-like text flows, step-by-step client/admin examples, data model notes, state/gaps).
Updated: README.md (links the review + high-level summary of the two UXes, security, integrations post-M1/M1.5 + MCP content work).
- contact form: now uses same pattern as bookings (persist first, fire-and-forget bounded send)
- VIP unlock confirm (payments received, including wallet_topup): added decoupled email to Quinn on billingEntry write
- VIP priority requests: added notification on creation
- VIP quotes respond: improved from console.* to logger + withTimeout
- Extracted shared/timeout.ts (with unref) and updated bookings to use it
This ensures Quinn receives emails reliably for contact submissions, payments sent/confirmed, and VIP client activity without transient SMTP issues affecting the UX or dropping leads.
Supports the VIP prepaid wallet channel: create posts whose gallery media can be unlocked via balance-purchase or intents (targetRef to drop).
Also synced payment_methods tools for vip_unlock_enabled.
nginx public_write upstream (black primary, outbox :3098 backup) + exact-match
locations for /public/contact and /public/touring/subscribe + waitlist, all with
proxy_next_upstream ... non_idempotent. Normal path unchanged (black answers, no
failover); only a black-down POST retries to the outbox, which spools + replays.
Outbox routes aligned to black-facing paths. (public_write upstream block added to
VPS-owned quinn-upstreams.conf on vps-0.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fresh generation from original-desktop.webp with strong no-expansion prompt.
- Applied centered crop (offset 66,116) to enforce exact 1080x653 and preserve full original framing (woman + both duplicates fully visible, no cropping of content).
- Badge with OnlyFans logo + username in upper right.
- Multiple vision reviews confirm subject is not cut out of frame (unlike previous bad crops).
- Dimensions verified exact.
- Reviewed before commit per instructions.
- Previous top-left crops were trimming the right side and cutting the woman/duplicates out of frame.
- Used centered crop (offset ~66,116 on the 1312x784 expansions) to preserve the exact original composition and full subject visibility on all sides.
- Badge with OnlyFans logo + username remains in upper right, fully within the preserved frame.
- Dimensions locked at 1080x653.
- Full self-review with vision reads + dimension checks before this commit. Replaces previous bad versions.
- Verified with multiple vision reads + technical dimension checks (exact 1080x653 confirmed vs original).
- Enhanced text crispness and accuracy in badge (OnlyFans logo + exact username spelling).
- Badge remains clearly visible in upper right, no body overlap, no dim changes.
- Self-review complete per project protocol before any 'done' status.
Additive nullable column + unique index + createContactSubmissionIdempotent
(ON CONFLICT DO NOTHING, returns existing row, skips notify email on replay).
Route reads optional Idempotency-Key header. Lets the edge outbox replay a
contact submission without creating a duplicate. Backward-compatible: direct
submissions (no key) insert normally. touring/waitlist already natural-idempotent
(UNIQUE(email,provider_slug) upsert), so contact is the only table needing this.
NB: hCaptcha is effectively disabled (frontend sends no token), so stale-token
replays are not rejected; if hCaptcha is ever enabled, add a trusted outbox-token
bypass for replays.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Recovered from a good base with visible badge, enhanced via targeted edit.
- Spelling fix applied for exact 'transquinnftw'.
- No dimension changes. Ready for upload.
- Used original 1080x653 webp as strict reference for img2img.
- Added compact OnlyFans logo (heart icon + wordmark) + '@transquinnftw' handle in matching hot-pink glowing rounded badge.
- Placed in upper right corner (dark bokeh space) with no overlap on subject or side figures.
- Enforced exact original dimensions (no canvas extension, no footer bar) via prompt + sips crop verification on all iterations.
- Also produced matching high-quality .webp at identical 1080x653.
- Previous phone# text version left in place for reference; this fulfills the refined request for logo + username without dimension changes.
- Files ready for direct replacement upload to ts4rent.eu /public/media/avrt/TransQuinnFTW.webp
- Used original TransQuinnFTW.webp (1080x653 pink promo photo) as img2img reference.
- Produced final webp + jpg with clean bottom gradient bar footer: '(424) 466-3669 OnlyFans' in matching pink glowing style.
- Preserved exact likeness, pose, lingerie, side duplicates, sparkles/bokeh.
- Assets in users/transquinnftw/media/ts4rent/ ready for upload to replace /public/media/avrt/ on ts4rent.eu
- 3 edit iterations for footer placement (no body overlap).
- Add idempotent append in quinn.api/deploy.sh for MAC_SYNC_BASE_URL + SERVICE_TOKEN (matching the pattern used for MODEL_BOSS, ANALYTICS_DB etc.). Old secrets.env files that predated the send support would cause prospect-cockpit /send (and /m/messages/send) to 502 with 'mac_sync_unavailable' / 'MAC_SYNC_URL env var required'.
- Explicitly pass the same MAC_SYNC_* in scripts/run/dev.sh dev:api so local dev quinn.api (on 3040) can exercise scheduled-send / cockpit_send flows against the canonical black mac-sync-server.
- Live hotfix: appended the lines to /etc/quinn-api/secrets.env on black + restarted quinn-api (verified: now present in running process env; end-to-end /my/prospects/.../send now returns scheduledId instead of 502; test row cancelled cleanly via mac-sync admin).
This makes cockpit_send (quinn-prospector) and sibling send surfaces work when the MCP targets the real backend (black:3912 -> localhost:3030 quinn.api).
Refs the exact error from the report.
vps-0 local Node service for the black-dependent public writes (contact/touring/
waitlist). Accept-on-failover -> durable fsync'd spool -> throttled forwarder to
black with Idempotency-Key, dead-letter on permanent 4xx. Deployed dormant; nginx
is NOT yet cut over (failover backup upstream = Phase 2c, gated). Verified in
isolation: 202-accept, spool, forward+clear, 404, body cap.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The surfaceLuminance regex-match access m[1] is string|undefined under
noUncheckedIndexedAccess; guard with ?? '0' so the flourish typechecks clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the closing flourish auto-tune per site theme (sunny pink+sunshine Malibu
card on barbie-light, glowing pink on dark moods) with glow intensity adapting
to surface luminance (surfaceLuminance helper).
Add a magic-score picker to the rates table that triggers theme-aware surprise
animations (geek RGB-glitch/CRT on luxe/non-Barbie themes, sparkle/shimmer/glow
on barbie-*), driven by a new useSiteThemeName hook (reads data-site-theme) and
magicCardFx definitions. Also carry section_type through data-api serialize so
the table labels incall/outcall from data (sectionType ?? inferSectionType).
Retune the brand descriptor and base/route meta to the live EROS advert voice —
'pink-and-UV-orange-haired transfem game dev', 'Cali bimbo', 'from San Francisco'
(origin; current city comes from the tour-aware path). Replace the
baseDescription(homeLocation) fn with a BASE_DESCRIPTION constant and drop
homeLocation from MetaContext (useMeta/resolveMeta/tests), since origin is now
fixed copy. 'Gamedev' → 'Game Dev' throughout; index.html fallback kept in sync.
Replace stubbed audience geography with session_fingerprints queries
(country/region/city, pathPattern, activityWindow for live). Surface
US states, cities on Audience/Overview, page detail, and dashboard
snapshot. Extend quinn-analytics MCP to v0.3.1 with geo_breakdown,
audience_geo_summary, and geo_enrichment_status.
Deploy dashboard/API from main checkout — see handoffs/analytics-geo.md.
MCP v0.3.1 already on black :3914.
Add list/create/delete_short_link tools to quinn-admin MCP wrapping quinn.api
/admin/short-links. Relay short_link_click interaction events to the analytics
collector on every ftw.pw /s/:code redirect (alongside existing click_count).
Thread.tsx imported iMessage primitives from @lilith/ui-messaging where
they are not exported; point at @lilith/ui-imessage instead. Add
skipLibCheck to my/frontend-public and raise the tsc heap in
typecheck-all.sh so the CI sweep no longer OOMs on large frontends.