Skip to content

feat: Add plan features and gating middleware#12

Open
kofimokome wants to merge 4 commits into
mainfrom
feat/entitlement
Open

feat: Add plan features and gating middleware#12
kofimokome wants to merge 4 commits into
mainfrom
feat/entitlement

Conversation

@kofimokome

@kofimokome kofimokome commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Fixes #8

Depends on #11

@kofimokome kofimokome marked this pull request as ready for review July 6, 2026 20:27
@sourceant

sourceant Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code Review Summary

This PR adds subscription gating, Stripe integration via Cashier, and feature entitlement logic. It introduces a custom BillingCustomer model and middleware to protect routes based on plan features.

🚀 Key Improvements

  • Implemented a structured Entitlements system via CloudEntitlements.php.
  • Added comprehensive OpenAPI documentation for the new checkout endpoint.
  • Integrated Stripe webhooks to handle cache busting when subscription status changes.

💡 Minor Suggestions

  • Fix inconsistent spacing in CloudController.
  • Move config(['cashier.model' => ...]) to a boot method or the cashier config file.

🚨 Critical Issues

  • Removal of debug_backtrace in CloudEntitlements is highly recommended to avoid brittle logic.
  • Sensitive Stripe IDs should be moved to .env.

@sourceant sourceant Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

Comment thread config/cloudplans.php
'us' => [
'name' => 'United States',
'currency' => 'USD',
'monthly_price_id'=>'plan_id', // from stripe

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sensitive IDs and configuration values should not be hardcoded in the config file. They should be loaded via env() to ensure environment-specific values and better security.

Suggested change
'monthly_price_id'=>'plan_id', // from stripe
'monthly_price_id' => env('STRIPE_MONTHLY_PRICE_ID'),

*/
private function getCurrentChatMessageId(): ?int
{
foreach (debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using debug_backtrace for business logic (idempotency) is highly fragile and a performance anti-pattern. If the job class is renamed or the call stack changes, token consumption will fail. Pass the messageId explicitly to the consume method instead.

Suggested change
foreach (debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {
// Pass message context explicitly in the consume signature if possible.
return null;

{
Schema::create('subscriptions', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained('billing_customers')->cascadeOnDelete();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The foreign key references billing_customers, but the migration name suggests it's linked to the user_id. Ensure consistency with Laravel Cashier expectations where the billable model is typically the User model directly, or explicitly define the owner relationship.

Suggested change
$table->foreignId('user_id')->constrained('billing_customers')->cascadeOnDelete();
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();

@kofimokome kofimokome requested a review from nfebe July 6, 2026 20:29

@nfebe nfebe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seem to have same commits as #11... I am a bit confused just 11 has 1 extra commit.

@kofimokome

Copy link
Copy Markdown
Collaborator Author

@nfebe it depends on #11. so you would have to review #11 first before this one.
I also added in the description that it depends on #11.

@kofimokome

Copy link
Copy Markdown
Collaborator Author

it's not possible to work on this without the changes in #10 (stripe integration) and #11 (entitlements integration)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cloud): Implement Entitlements with plan features and gating middleware

2 participants