builtbykev
aaafc3e0f2
Merge S8 (a1): ops — the product watches itself
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
# Conflicts:
# BUILD-STATE.md
# CLAUDE.md
# src/snapshotScheduler.js
2026-07-11 14:38:06 -04:00
builtbykev
044941d406
S8 (a1): ops — the product watches itself
...
Settlement alarm (settle-pass THROW pages high; morning zero-settle alarm
keyed off the Postgres ledger settle results, once per ET date, never on an
empty yesterday), per-sport 3-consecutive-slot failure pager (pure
opsWatch.createFailureTracker, pages once per losing streak), odds-api >=80%
quota alert (once per day, Redis-deduped), systemHealth (statfs + os mem,
disk>85 / mem>90 pages), daily 9 AM ET pulse (ONE notification: ledger rows
yesterday via ledgerService.countRowsForDate, settles 24h, quota, disk/mem,
desk line), docs/OPS-RUNBOOK.md (Uptime Kuma monitors, Coolify
deploy-failure -> ntfy, phone subscription). All copy VOICE v1.1 — deadpan,
numbers, no exclamation points (tests lint for it). 2398 -> 2437 tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-11 14:34:45 -04:00
builtbykev
a6a81f5d42
Merge S2 (a1): compliance + approval pack
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
# Conflicts:
# BUILD-STATE.md
# web/src/app/about/page.tsx
2026-07-11 14:33:18 -04:00
builtbykev
fc0c7bfd18
Merge S7 (a1): newsletter — THE VYNDR REPORT
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
# Conflicts:
# BUILD-STATE.md
# CLAUDE.md
2026-07-11 14:32:18 -04:00
builtbykev
4b262fdd65
S2 (a1): compliance + approval pack
...
- /responsible-gambling rebuilt sincerely: 21+, 1-800-GAMBLER primary,
17-state resource list, warning signs, self-exclusion guidance, links
to the existing /settings surfaces. No marketing adjacency.
- /terms + /privacy honest drafts with entity placeholders ([ENTITY NAME],
[STATE OF FORMATION], [ARBITRATION VENUE], [CONTACT EMAIL]); privacy
sub-processors match reality (adds Sentry, honest PostHog description).
- NEW /methodology: pipeline -> engine -> letter grades, refusals,
VYNDR Originals, ledger settle + CLV + n>=20, why misses are public.
- /about audited to North Star framing (THE PROOF card, methodology link).
- Footer: 1-800-GAMBLER + Methodology link; compliance audit found zero
pages suppressing the global footer.
- 5 Ghost seed articles in content/articles/ + docs/GHOST-PUBLISHING.md
manual runbook (no Ghost access used).
- tests/unit/compliancePages.test.js (repo source-text style). 2429 tests
green, web build exit 0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-11 14:29:31 -04:00
builtbykev
32d7200571
S7 (a1): newsletter — THE VYNDR REPORT
...
Email capture + daily report assembly + operator-triggered Listmonk send.
- NewsletterCapture (dark terminal, mono) on landing (below FAQ) + /welcome
(the real signup success surface); double-opt-in note; 'Signups open soon'
when Listmonk env is unset.
- POST /api/newsletter/subscribe: public, 10/min IP limit, honeypot,
server-side email validation, forwards to Listmonk subscribers API with
preconfirm_subscriptions:false (Listmonk sends the confirmation).
No env -> calm 200 { ok:false, reason:'not configured' }. Next proxy
web/src/app/api/newsletter/subscribe/route.ts (S25 rule).
- newsletterService.buildDailyReport: signals from snapshot:{sport}:latest,
STREAK WATCH via rosterLogs -> streaksService -> streakLens, THE RECORD via
ledgerService.getModelAggregate (percentage only when hit_pct != null —
n>=20 gate — else 'RECORD BUILDING · N pending'). RG footer (21+,
1-800-GAMBLER, Listmonk-native {{ UnsubscribeURL }}) in html + text.
VOICE v1.1 lint locked by tests: no '!', no banned vocabulary, numbers
only from injected pipeline data.
- sendDailyReport: creates + starts a Listmonk campaign; env-gated no-op;
refuses an empty report. Deliberately UNSCHEDULED — only
POST /api/internal/newsletter/send (internal key) triggers it.
- docs/NEWSLETTER.md: box-side Listmonk runbook (install, double-opt-in
list, API user, Coolify env, test-send).
- Spec: specs/feature-a1-s7-newsletter.md.
Tests 2398 -> 2429 (207 suites, all green); next build exit 0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-11 14:29:22 -04:00
builtbykev
0996320bd1
S3 (a1): affiliate + partner plumbing
...
Zero out-of-pocket; everything config-flip-ready but DISABLED/organic.
- BOOK IT deep links: web/src/lib/bookLinks.js + affiliateConfig.js
(all books enabled:false, Impact/Partnerize param shapes documented,
empty params skipped). Wired into StatStrip BookItTeaser (real anchor
now) + scan hand-off links. Every book anchor renders
rel="sponsored noopener noreferrer" (BOOK_LINK_REL).
- Best-price marker: slateAdapter.detectBestBook (only when >=2 books
post the SAME line and prices differ — absent beats wrong) + subtle
signal-green dot in StatStrip. Slate.groupByGame threads the grouped
per-book rows (books[]) onto PropRowProp instead of discarding them.
- Partner refs: ?ref=CODE -> vyndr_ref cookie (90d, first-touch,
PartnerRefCapture in layout) -> signup metadata partner_ref ->
internal GET /api/partners/report/:code (requireInternalAuth; honest
zeros + note until the TODO migration in docs/PARTNERS.md adds
user_profiles.partner_ref — NOT run). Stripe promo-code convention:
partner code == promotion code, verbatim.
- Tests: +41 (2398 -> 2439, 209 suites); bookItTeaser + vyndrCoreScreens
invariants updated to the new (stronger) rel contract. Web build exit 0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-07-11 14:28:18 -04:00
builtbykev
f5d79cf70d
Session 14: Africa checkout, Tank01 NBA/MLB wiring, WNBA+MLB odds proxies, OAuth icons, loading skeletons (1330 tests)
2026-06-11 10:06:49 -04:00
builtbykev
10159209fa
Session 13: The Slate, Africa geo-restriction, OAuth providers, PropRow + GameCard (1311 tests)
2026-06-11 03:48:07 -04:00
builtbykev
d957dee17b
Session 12: i18n (10 languages, cookie-based), Africa tier .99, locale switcher, RTL Arabic (1305 tests)
2026-06-10 22:24:40 -04:00
builtbykev
e5c45ecc8e
Session 10: Internal auth refactor, prefetch cascade keys, Sentry, welcome email (1286 tests)
2026-06-10 20:45:05 -04:00
builtbykev
b55dcbd614
Session 9: api-football + FootApi + Tank01 adapters, grace period middleware, cookie consent, /pricing page, OOM fix documented (1240 tests)
2026-06-10 19:41:37 -04:00
builtbykev
4db1c1c539
Session 8: Frontend Stripe cutover, soccer pages, sport selector, grade result cards, beta badge
2026-06-10 15:34:23 -04:00
builtbykev
ad5ea8d5a8
Session 7j: Soccer intelligence - 9 leagues, 11 signals, 6 traps, poller, prefetch, 131 new tests (1173 total)
2026-06-10 14:50:13 -04:00
builtbykev
b9084408bf
Session 7i: Stripe test coverage gaps filled, dual-provider cutover documented (1042 tests)
2026-06-10 13:55:59 -04:00
builtbykev
d4e5e76452
Session 7h: Stripe products, tier config, scan limits, response gating, free tier
2026-06-10 13:24:11 -04:00
builtbykev
4e18eb1efe
Sessions 7e-7g: Grading path unified - adapter, computeFeatures, analyzeViaEngine1, all routes migrated, dead code removed
2026-06-10 10:23:55 -04:00
builtbykev
4815ceac03
Sessions 7e+7f: Grade adapter, normalize consolidation, computeFeatures, analyzeViaEngine1, scan/parlay migrated to engine1
2026-06-10 09:28:30 -04:00
builtbykev
012c0ef47e
Session 7e: Grade adapter, normalize consolidation, ARCH-2 banners
2026-06-10 03:37:07 -04:00
builtbykev
6f4a353de9
Session 7d: Audit fixes - rate limiting, error leak, parallel parlays, analyze cache, bundle analyzer
2026-06-10 03:12:20 -04:00
builtbykev
d954e4d952
Session 7c: Code audit - system manifest, env var documentation, 11 findings catalogued
2026-06-10 02:26:21 -04:00
builtbykev
1fa04dc776
Sessions 5-7a: 955 tests, deployment ready
2026-06-08 18:35:13 -04:00