---
id: w6/m1/t005
title: "Enforce plan limits in Core: 25-service Hobby cap on create; Hobby single-member guard"
worker: worker6
status: done
estimate: 25m
depends_on: [w6/m1/t003]
---

## Objective

Make the t002 plan limits real at the enforcement points: `Core.Create` (service create, built in w2/m4) refuses the 26th service in a Hobby workspace (count includes suspended services, matching Render); and a Hobby workspace refuses growing beyond 1 member — a guard w4/m12's membership verbs will call rather than reimplement.

## Context

- Render verified numbers: Hobby = 25 services incl. suspended, 1 member; paid = unlimited members (RESEARCH-workspaces.md finding 4).
- Service create path: `lego/backend/internal/core/` (`Core.Create` from w2/m4); apps listable per tenant via the store/CR layer.
- The member guard is an exported check (e.g. `CanAddMember(tenant)`) — w4/m12 t001 is its consumer; keep it in core so both milestones share one rule.

## Steps

1. Add a per-tenant service count (live + suspended) and check it in `Core.Create` when the workspace plan is `hobby`.
2. Add the exported single-member guard keyed on plan.
3. Typed limit errors with the plan + limit in the message (surfaces map them to 4xx).

## Files

- `lego/backend/internal/core/`
- `lego/backend/internal/store/` or `internal/apps/` (count query)

## Acceptance criteria

- [ ] 26th service create in a Hobby workspace returns a limit error; the same create in a `pro` workspace succeeds
- [ ] Suspended services count toward the 25
- [ ] `CanAddMember` returns false for a Hobby workspace with 1 member, true for paid plans

## Out of scope

- Member-add verbs themselves (w4/m12).
- Plan upgrade/downgrade flows (follow-up note if needed).
