Commit Graph

13 Commits (v1.2.0)

Author SHA1 Message Date
nexxo e6793c4dae Plan the operator identity work as nine testable steps
Re-measuring before writing found the spec's numbers had moved: seventeen
permissions now, not sixteen, because the mailbox work added mail.manage.
It also turned up something the spec did not anticipate — ConfirmsPassword
resolves the password through auth()->user(), the default guard, so all
five components using it break the moment a second guard exists. That is
now its own task.

Self-review caught two references to things that do not exist: users has
no uuid column, so the impersonation link addresses the customer instead,
and there is no layouts.guest — the auth pages use layouts.portal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 09:13:42 +02:00
nexxo c5252847bb Make the SECRETS_KEY test able to fail
The Task 2 reviewer rewired the model to Laravel's APP_KEY-based Crypt
facade and every test stayed green. Laravel's encrypter is a container
singleton resolved once from app.key, so config()->set('app.key') never
rebuilds it and the rotation the test performed was invisible.

Replaced with a positive proof — rotating SECRETS_KEY must break
decryption — plus the APP_KEY case with forgetInstance(), which is what
makes that direction mean anything.
2026-07-27 21:44:59 +02:00
nexxo c642090d97 Point the mailbox model at the UUID trait the repo already has
Seventeen models use App\Models\Concerns\HasUuid, and R11 is the reason:
URLs address records by UUID, not by integer primary key. The plan told
the implementer to hand-roll booted() instead, losing getRouteKeyName()
with it. Authoring error, corrected before the remaining tasks copy it.
2026-07-27 21:28:23 +02:00
nexxo 5cbd949bd5 Say plainly that the path comment in the plan is not code
The Task 1 implementer copied '// path/to/file.php' into the files
verbatim, which breaks Pint's blank_line_after_opening_tag and matches
no file in the repo. The annotation was mine; the constraint now says so
before the next seven tasks repeat it.
2026-07-27 21:20:37 +02:00
nexxo 576cfcafac Plan the mailbox work as eight testable steps
Self-review against the spec turned up four gaps and one latent bug in
what already ships.

The bug: Laravel 13's MailManager reads only 'scheme' when building an
SMTP transport (MailManager.php:196) — the old 'encryption' fallback is
gone — and .env carries MAIL_SCHEME=tls, which Symfony does not accept;
it knows smtp and smtps. Nothing has failed because MAIL_MAILER=log
means no connection has ever been opened. The plan stores a human-facing
tls/ssl choice and translates it where it is used, and never copies
MAIL_SCHEME through.

The gaps: the cancellation mail and the provisioning notification were
edited but not tested, secrets.manage was never proven insufficient for
the new page, and a missing SECRETS_KEY had no task making the page say
so rather than throw.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 21:03:13 +02:00
nexxo 743ba96d13 Design mailboxes as records, not as one more secret
The console offers a single mail.password pointing at one SMTP mailbox,
which is nowhere near enough for five sending addresses. A mailbox is
address, display name, username and password; five of them as registry
entries would be twenty secrets named mail.support.username, and the
question of which mail sends from which address would still have no home.

Send-only stays usable because every message carries Reply-To on its own
mailbox, so a customer's reply lands in a mailbox someone reads. That is
what makes IMAP unnecessary rather than merely deferred.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:51:03 +02:00
nexxo edaceb9597 Delete the users row once the operator has moved out of it
Decided: whoever is in operators has no business in users. A row left
behind is the same mixing the separation exists to end, only smaller.

The one case that deletes nothing is a row with a customer, a seat or an
order on it. That would mean the same person is operator and paying
customer, and a silent delete would take billing data with it — so the
migration stops and names the address instead. Neither existing account
is in that state.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:44:56 +02:00
nexxo ce970a5fac Design the console's own identity, separate from customer accounts
The operator console and the customer portal share one users table, one
login page and one guard. Three reported faults follow from that single
fact: the console serves the portal's sign-in page, that page offers
"Registrieren", and the link 404s because RestrictAdminHost::SHARED does
not list register.

Measured rather than assumed: driving the host guard directly gives
/login through and /register 404 on the console host, and all sixteen
Spatie permissions turn out to be console permissions — so RBAC moves to
the new guard rather than being duplicated across two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 20:40:22 +02:00
nexxo b9742f61ee docs: customer pipeline (Subsystem B) implementation plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 11:35:28 +02:00
nexxo 93191f5de9 fix(engine): fail on unresolvable pipeline step; make worker the WG hub
- RunRunner catches step-resolution errors (removed/renamed pipeline) and
  fails the run terminally instead of looping forever every tick.
- queue-provisioning worker gains NET_ADMIN + tun + persistent wireguard
  volume + published UDP port so LocalWireguardHub can manage wg0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 10:53:40 +02:00
nexxo ced7e6103d fix(engine): durable queueing for long provisioning steps
- Dedicated 'provisioning' queue connection (retry_after 2400) + worker
  (--timeout=2100); AdvanceRunJob tries=1, timeout=2100 on that queue.
- Run lock TTL raised to 2100s so a long step can't be run concurrently by a
  duplicate tick-dispatched job.
- StartHostOnboarding creates host+run in a transaction, dispatches after commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 10:36:49 +02:00
nexxo 7ae81d8127 docs: host-onboarding implementation plan
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 09:46:58 +02:00
nexxo 772e9d35ff docs: host-onboarding (Subsystem A) design spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 09:44:11 +02:00