Skip to content

feat(plans): first-class self_serve flag to hide plans from the customer portal - #15

Merged
rrader26 merged 1 commit into
mainfrom
feat/plan-self-serve-portal-visibility
Jul 1, 2026
Merged

feat(plans): first-class self_serve flag to hide plans from the customer portal#15
rrader26 merged 1 commit into
mainfrom
feat/plan-self-serve-portal-visibility

Conversation

@rrader26

@rrader26 rrader26 commented Jul 1, 2026

Copy link
Copy Markdown

What

Adds a self_serve boolean to plans (default true, non-breaking). When false, the plan is hidden from the customer-portal self-serve list (AvailablePlansResolver) but stays fully assignable by operators — for contract-only tiers like enterprise / white-label.

This replaces the interim hidden_in_portal metadata hack with a proper, toggleable field that the lago-front admin can expose as a checkbox.

Changes

  • migration add_self_serve_to_plansadd_column :plans, :self_serve, :boolean, default: true, null: false
  • AvailablePlansResolver — base scope now .where(self_serve: true) (portal-only; operator assignment is unaffected)
  • Plans::CreateService / UpdateService — persist self_serve (editable even when attached to subscriptions — it's not a billing attribute)
  • REST — permit :self_serve + expose in V1::PlanSerializer
  • GraphQLPlans::Object field + Create/Update input arguments

Not done here (needs a Ruby/CI env)

These generated artifacts must be regenerated in CI / locally:

  • db/structure.sqlrails db:migrate
  • schema.graphql → the GraphQL schema-dump task

(I deliberately did not hand-edit those generated files.)

Notes

  • Default true keeps every existing plan self-serve.
  • Pairs with a lago-front PR adding the admin checkbox, and with the parent app's provision-lago setting self_serve from its catalog.

🤖 Generated with Claude Code

…mer portal

Adds a `self_serve` boolean to plans (default true, non-breaking). When false,
the plan is excluded from the customer-portal self-serve list
(AvailablePlansResolver) but stays fully assignable by operators — for
contract-only tiers like enterprise / white-label. Replaces the ad-hoc
`hidden_in_portal` metadata approach with a proper, toggleable field.

- migration: add_column :plans, :self_serve, :boolean, default: true, null: false
- AvailablePlansResolver: base scope now `.where(self_serve: true)`
- Plans::CreateService / UpdateService: persist self_serve (editable even when
  attached to subscriptions — it's not a billing attribute)
- REST: permit :self_serve param + expose in V1::PlanSerializer
- GraphQL: Plans::Object field + Create/Update input arguments

Post-merge / CI must regenerate the checked-in artifacts (env-dependent, not
done here): `structure.sql` via `rails db:migrate`, and `schema.graphql` via
the GraphQL schema dump task.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rrader26
rrader26 merged commit 19d7235 into main Jul 1, 2026
0 of 12 checks passed
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.

2 participants