Commit Graph

4 Commits (v1.3.51)

Author SHA1 Message Date
nexxo e8bd8268fd Stop a disabled operator from bypassing the hidden-site gate
PublicSiteGate let anyone through on a bare Auth::guard('operator')->check(),
which stays true for a disabled operator's live session — disabling
someone does not sign them out, so it never stopped this gate from
showing them the real site indefinitely, even though EnsureAdmin
already treats them as inactive. Now requires the same thing EnsureAdmin
does: an active operator holding a console role.

Chosen to merely ignore an invalid operator session here rather than log
it out. This gate only decides what one request sees; logging out would
ripple into whatever else that session is doing (a concurrent console
tab, mid-task), a bigger side effect than a visibility check exists to
have. EnsureAdmin sets the precedent — it also rejects a disabled
operator per request without touching their session.
2026-07-28 14:42:29 +02:00
nexxo 87c49de6e5 Move the console's identity out of the customer table 2026-07-28 10:31:43 +02:00
nexxo 2b70c9226a fix(traffic): release the throttle at month end; close the Livewire bypass
Two from Codex:

- A throttled instance kept its NIC limit into the new month: the new period
  row starts unthrottled, so neither branch of enforce() fired and nothing ever
  took the limit off. A customer would have stayed slow through a month they
  had already paid for.
- PublicSiteGate exempted livewire/* wholesale. That endpoint is shared by the
  console and the portal, so a signed-in customer could keep driving portal
  components — billing included — while the portal was supposed to be offline.
  Operators pass the normal check anyway, which is all the console needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 23:36:38 +02:00
nexxo e2b4cdbac4 feat(site): switch the public website and portal off from the console
While the product is still being built, the marketing site and the customer
portal should not be reachable — but they must stay reachable for us.

- A toggle in the console (site.manage, Owner/Admin) stored in a new
  app_settings table, because this has to be flippable without a deploy.
- Outsiders get a placeholder with 503 + noindex, not 200: a 200 invites search
  engines to index the placeholder as the site's content, which is far harder
  to undo than to prevent.
- Anyone on the management VPN, and any signed-in operator, sees the real site.
  The console, Livewire's endpoint, the Stripe webhook and the health check are
  always reachable — otherwise the switch could only be flipped once.
- robots.txt is generated by the app and follows the switch. It had to stop
  being a static file: nginx short-circuited it and Laravel's stock file said
  'Disallow:' with an empty value, so crawlers were never told anything.
- Settings reads fall back to the default when the table is unavailable. The
  gate reads one on every request, so a deploy running new code before migrate
  would otherwise answer the entire site with a 500.

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