Commit Graph

2 Commits (2277dfe4cb7edcbeec2fc74ade23e1dbae544e34)

Author SHA1 Message Date
nexxo 4e3beca759 Close the domain page to packages that may not have one
The rule was decided in CustomDomainAccess but nothing asked it on the way
in: /domain answered every customer on every package, so the entry package
could set a domain it is not sold and cannot keep.

The guard sits in mount(), not on the route. A Livewire component answers
POSTs to /livewire/update by itself, so a route-only check would have left
save() and the rest reachable to exactly the customers it was meant to stop.

The sidebar asks the same question through a gate rather than a second copy
of the rule — a customer holds no permissions at all (R21 puts all seventeen
on the operator guard), so can() had nothing to filter on and the tab was
shown to everyone, leading straight into the 403 the page now raises.

Customer::forUser() carries the resolution the Livewire concern used to own,
because the gate has to answer outside any component and a second copy of
its email fallback is how the two would drift apart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 16:20:21 +02:00
nexxo a321d963d7 fix(portal): no silent no-ops without a customer; maintenance visible per instance; maintenance form redesign
- ResolvesCustomer trait replaces 5 duplicated customer() lookups; portal actions
  now SAY why nothing happened (operator accounts have no Customer) instead of
  returning silently — the actual cause of 'dead buttons', '0/0 seats' and
  'settings not saving' when signed in as admin
- portal layout: explicit notice for a login without a linked customer
- /cloud: per-instance maintenance badge + window details; seat note 'owner = seat 1'
- maintenance form: sectioned card, hints, placeholder, styled datetime fields,
  grouped host picker with per-datacenter select-all + selection counter

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 19:10:44 +02:00