clupilot/app/bootstrap
Boban Blaskovic 555101c993 Step 1/5: Workspace multi-tenancy foundation
User accepted 5-step plan: Workspace → Sub-Sidebar → Switcher → Plan/
Quota → Billing.

This step adds the workspace layer underneath everything:
- Workspace model with HasUuids + relations (sites/servers/clusters/
  backups/members/invitations/activities) + plan-based quotas + feature
  flags + isOverQuota() + hasFeature() helpers.
- Plan presets: free/starter/pro/agency/enterprise with sites,
  servers, team, storage_gb, features map (audit/monitoring/
  email_relay/multi_workspace/white_label/reports/sso).
- BelongsToWorkspace trait: global scope filters by app('current
  Workspace'), creating-hook auto-fills workspace_id from container.
  Falls back to no-scope when no workspace bound (tests, console).
- Migrations: workspaces table + workspace_id foreignUuid added to
  all 10 domain tables (clusters/servers/sites/backups/team_members/
  invitations/security_events/certificates/activities/crons).
- users gets current_workspace_id nullable FK.
- team_members unique changed to composite (workspace_id, user_id) so
  one user can belong to multiple workspaces.
- ResolveCurrentWorkspace middleware: resolves active workspace from
  ?workspace=slug → session → user.current_workspace_id → first owned.
  Wired into web middleware group via bootstrap/app.php.
- WorkspaceFactory + workspace_id added to all 10 domain factories
  so tests/seed work without explicit workspace context.
- DatabaseSeeder rewritten: creates Marie Weber as owner of 'Acme
  Agency' (Pro plan) workspace + 'Marie · Personal' (Free) workspace
  for switcher demo. Binds app('currentWorkspace') so seeded sites/
  servers/backups/etc. land in the right workspace.
- Sidebar component reads auth user's current workspace for the ws-
  switch panel — no more hard-coded 'Acme Cluster' string.

Full Pest regression: 47/47 green. 2 workspaces seeded:
- Acme Agency (pro): 87 sites, 6 servers, 128 sec events, 102 backups
- Marie · Personal (free): 0 sites
2026-06-01 01:12:00 +02:00
..
cache Initial CluPilot stack setup 2026-05-27 23:00:14 +02:00
app.php Step 1/5: Workspace multi-tenancy foundation 2026-06-01 01:12:00 +02:00
providers.php Initial CluPilot stack setup 2026-05-27 23:00:14 +02:00