Claude/setup teos ecosystem jm u iq#2
Conversation
- Add Transaction and WebhookEvent models to Prisma schema with full index coverage; add planActivatedAt/planExpiresAt to User model - Introduce lib/billing.ts as the single provisioning authority: PLANS_MATRIX credit allocations, idempotency guard on paymentRef, Prisma $transaction atomicity (user + Transaction + AuditLog), subscription expiry computation, BillingError typed exceptions - Harden Dodo webhook: timing-safe HMAC via crypto.timingSafeEqual, 5-minute replay-attack window, WebhookEvent idempotency dedup, graceful USER_NOT_FOUND (200) so Dodo stops retrying unknown emails - Harden Pi verify: Stellar txid format validation, double-spend protection via Transaction.paymentRef uniqueness, structured trace logging throughout - Fix AuditLog userId="" bug — userId now always resolved from DB
Root causes fixed:
- Response shape mismatch: route returned 'content' but PostGenerator
reads 'data.post' and 'data.hashtags' — generation always appeared
to fail even on success
- Plan ID matching was broken: checks for "agency"/"pro"/"lifetime"
never matched DB values like "agency_monthly"/"pro_lifetime";
all paid users were silently routed to free-tier Gemini Flash
- Wrong Gemini model path: google("models/gemini-1.5-flash") rejected
by @ai-sdk/google — replaced with google("gemini-2.0-flash")
- Usage counters never incremented: appendPost() now called after
each successful generation so canUserPost limits are enforced
- Generic catch block swallowed real errors; now returns precise
error.message in 'detail' field for client-side debugging
- Free trial gate blocked all free users unconditionally; replaced
with canUserPost() which respects totalPostsUsed < 5 allowance
- Added structured JSON prompt + parseAIResponse() parser so hashtags
are returned as a proper array, not embedded in post text
Generated by npm install and tsc --noEmit during billing pipeline build.
- Design tokens: bg #060608, gold #C9A84C, bg-card #111118 per spec - Fonts: add Crimson Pro (serif headings) + Space Mono (labels/badges) - Navigation: gold-accent CTA button, underline hover, refined hamburger - Hero: Crimson Pro h1, atmospheric multi-layer glows, noise overlay, stat counter panel with glass card, gold-border ghost CTA - Social Proof: gold-tinted badge pills, Space Mono platform labels - Features: numbered cards (01–08), accent-colored icons per feature, interactive hover borders, gold rule divider - Testimonials: 3 premium quote cards with Crimson Pro body text, avatar monograms, brand trust bar - FAQ: gold-border open state, + → × animated icon, separator line - Footer: gold border-top, Space Mono section headers, gold social icons - page.tsx: all section headings use Crimson Pro, Syne → Space Mono - tailwind: recalibrated gold scale, add font-display/font-label keys https://claude.ai/code/session_01HqaVKid7fP2pB8h6J2AbHV
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Code Review
This pull request refactors the post generation endpoint to implement plan-based model routing and structured response parsing, while hardening the Dodo and Pi Network payment handlers with idempotency guards and atomic provisioning via a new unified billing engine. Additionally, the PR includes a significant UI overhaul of the landing page, updating typography, color palettes, and component styling. Feedback identifies a logic issue in the model resolution function where Agency tier users could silently fallback to lower-tier models if specific API keys are missing, recommending an explicit failure instead.
| if (isAgencyTier && process.env.ANTHROPIC_API_KEY) { | ||
| return { model: anthropic("claude-3-5-sonnet-20241022"), provider: "claude" as const }; | ||
| } | ||
| if (process.env.GOOGLE_GENERATIVE_AI_API_KEY) { | ||
| return { model: google("gemini-2.0-flash"), provider: "gemini" as const }; | ||
| } | ||
| if (process.env.ANTHROPIC_API_KEY) { | ||
| return { model: anthropic("claude-3-5-sonnet-20241022"), provider: "claude" as const }; | ||
| } | ||
| return null; |
There was a problem hiding this comment.
The resolveModel function incorrectly falls back to Gemini if the ANTHROPIC_API_KEY is missing for an Agency tier user. This should explicitly return null or throw an error to prevent unexpected behavior for premium users.
if (isAgencyTier) {
if (!process.env.ANTHROPIC_API_KEY) return null;
return { model: anthropic("claude-3-5-sonnet-20241022"), provider: "claude" as const };
}
if (process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
return { model: google("gemini-2.0-flash"), provider: "gemini" as const };
}
if (process.env.ANTHROPIC_API_KEY) {
return { model: anthropic("claude-3-5-sonnet-20241022"), provider: "claude" as const };
}
return null;
Contribution Proposal — Elmahrosa Organization
Summary
Describe the proposed change.
Repository Scope
Authority Confirmation
Risk Assessment
Checklist
Sign-off
I understand that Elmahrosa International retains final authority.