Conversation
- TierService: auto-calculate tiers from paid instance count (Free→Enterprise)
- TierChange entity + repository for audit logging
- Guards on OrganizationController (3-org limit), ProjectController (project + env limits), DatabaseController (db limits)
- Trial lifecycle: 90-day trials for Plus/Pro/Business, trial_ends_at tracking
- BillingController: /billing/tier, /projects/{slug}/limits, /users/me/org-limits endpoints
- Tier recalculation on instance create/cancel/update
- TierCronCommand: trial reminders, expiry suspension, post-trial downgrade, grace period enforcement
- EmailNotificationService: trial expiring, suspension warning, deletion scheduled
- BillingLimitService: delegates to TierService
- UpgradeLimitModal: frontend modal when free limit reached, offers paid upgrade with 90-day trial
- Integrated into environments/new and databases/new pages
- Homepage: replace Free/Pro/Team/Enterprise plan cards with 6 instance size cards (Free, Starter, Plus, Pro, Business, Scale) - Updated specs: Free=0.25 vCPU/1GB RAM, Starter=Free/0.5 vCPU/2GB RAM, Plus=4GB, Pro=8GB, Business=16GB, Scale=32GB - Added 'Free 90d' trial badges on Plus/Pro/Business - Pricing page: same spec updates, Starter now Free, trial badges on table - Removed Power from homepage instance table (still on /pricing)
- Homepage: remove 'Free forever. Always-on from $19/month' from hero - Homepage: fix Most Popular badge overflow on Pro card (pt-4, overflow-visible, z-10) - Pricing page: replace plan cards with instance size cards (same 6 cards as homepage) - Pricing page: update FAQs to reflect new tier model (Free/Starter free, 90-day trials, org tiers) - Pricing page: update free tier limits table with correct specs - Pricing page: update hero/core message text - Remove all 'free forever' references (pricing FAQ, git features page)
- /security — full security page: infrastructure, encryption, auth, app security, data security, monitoring, compliance, vulnerability disclosure - /privacy — full privacy policy: 11 sections covering data collection, AI processing, data sharing, retention, GDPR/CCPA/CPA rights - /terms — full terms of service: 16 sections covering definitions, registration, use, prohibited uses, billing, IP, termination, disputes - /sla — full SLA: uptime tables, service credits, support response times, maintenance windows, exclusions All pages use MonkeysCloud Inc (not Corp), consistent styling with gradient accent bars, proper SEO metadata, and cross-links between legal pages.
About page: - Hero with tagline, full origin story - 5 core principles in card grid - Founder bio with /images/jorge-peraza.jpg photo, social links (LinkedIn, GitHub, X) - Company info (MonkeysCloud Inc, Denver CO, remote-first) - Our Stack section (MonkeysLegion, React, GCP, Go Git, WebSocket, React Native) - Timeline (2023-2026) - Join Us CTA Partners page: - 5 partner types: Agency, Technology, Education, Open Source, Referral - Agency: volume discount table (10-20% off), typical setup cost breakdown - Technology: webhooks, OAuth, marketplace listing (Q4 2026) - Education: free Team plan, $50/mo credits, unlimited student seats - Open Source: free Team plan, community visibility - Referral: 20-30% commissions with tier table - Current integrations: GCP, Stripe, Let's Encrypt, GitHub/GitLab/Bitbucket - Bottom CTA
- GDPR-compliant banner with Accept All / Essential Only buttons - Slides up from bottom after 800ms delay on first visit - Persists choice to localStorage (mc_cookie_consent) - Links to Privacy Policy - Glassmorphism design with backdrop blur - Added to marketing layout
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73c2169e59
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| UPDATE instance_subscriptions SET is_free_allocation = 1, updated_at = ? | ||
| WHERE environment_id = ? AND status IN ('active', 'past_due') | ||
| ")->execute([$now->format('Y-m-d H:i:s'), $row['id']]); |
There was a problem hiding this comment.
Update downgraded trial subscriptions to non-paid package state
This downgrade path only flips is_free_allocation but leaves the subscription on its original paid package and active status. TierService::countPaidInstances() determines paid usage from server_packages.price_monthly_cents > 0 with status IN ('active','past_due'), so these post-trial rows are still counted as paid and the org tier will not actually fall after the downgrade runs.
Useful? React with 👍 / 👎.
| if (!empty($graceData['exceeds_projects'])) { | ||
| // Suspend newest projects that exceed limit | ||
| $maxProjects = $graceData['max_projects'] ?? 2; | ||
| $this->suspendExcessProjects($orgId, $maxProjects, $now); | ||
| $count++; |
There was a problem hiding this comment.
Enforce exceeds_instances before clearing grace period
Grace enforcement currently handles only exceeds_projects; when an org exceeds per-project free-instance limits, that condition is stored as exceeds_instances but never acted on here, and the grace record is still cleared afterward. In practice, orgs that only violate free-instance limits can keep excess free instances indefinitely once grace expires.
Useful? React with 👍 / 👎.
| if ($isPaid) { | ||
| $paidGuard = $this->tierService->guardPaidInstanceCreation($packageSlug, $orgId); | ||
| if ($paidGuard) { | ||
| return $this->json($paidGuard, 402); |
There was a problem hiding this comment.
Skip payment-method rejection for trial-eligible packages
The new tier guard allows trial-capable paid sizes to proceed without a card, but this endpoint still executes the legacy paid-package payment-method check later and returns 402 when no verified method exists (unless an offer is found). That means Plus/Pro/Business trial requests are still blocked despite the new trial logic.
Useful? React with 👍 / 👎.
1. TierCronCommand — post-trial downgrade now cancels subscription + reassigns to Starter package so countPaidInstances() no longer counts downgraded trials as paid (was only flipping is_free_allocation, leaving the joined server_packages.price_monthly_cents > 0 match intact). Also clears trial_ends_at on the environment/database row. 2. TierCronCommand — grace period enforcement now handles exceeds_instances (was only handling exceeds_projects). New suspendExcessFreeInstances() suspends newest free/starter instances per project when the per-project free limit drops after a tier downgrade. 3. ProjectController — legacy payment-method check at L866-875 now skips trial-eligible sizes (Plus/Pro/Business). Previously, guardPaidInstanceCreation() correctly returned null for trial sizes, but the downstream billing block still returned 402 when no payment method was on file, blocking all trial provisioning.
No description provided.