- Migration: replace 45 leaf categories (diag.scan, engine.mech…) with
17 root categories (diag, engine…); update labors.category by taking
the prefix before the first dot; delete the leaf LaborCategory rows
- ImportLaborCatalogCommand: rewritten to use root categories directly
so future imports go to the right level from the start
- LaborResource: add ->collapsible() to groups so user can collapse/
expand each category section to see only headers or only one group
- entrypoint.sh: remove one-time catalog import (was already done)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LaborResource: hide category column from data rows by default
(toggleable) so group headers span all columns cleanly; the group
header already shows the localized category name
- ImportLaborCatalogCommand: add --all flag to iterate every company,
refactor into importForCompany() helper, keep idempotent (skips
existing codes, updates only with --force)
- entrypoint.sh: run catalog:import-labors --all after each deploy so
all 386 operations + 45 categories are seeded automatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LaborResource: add titlePrefixedWithLabel(false) so group headers show
just the localized category name (not "Categorie: Шины"); remove static
cache from closure to avoid Octane cross-request locale bleed
- WorkOrderDashboard: add changeStatus() Livewire method + Alpine.js
dropdown on the status badge so status can be changed directly from
the dashboard without going to the full edit form
- New artisan command catalog:import-labors {company} that reads
database/data/labor-catalog.json (386 operations, 45 leaf categories)
and upserts labor_categories + labors for the given tenant; supports
--force to update existing records by code
- Add "Status actualizat" translation to ru/en JSON
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resend mail transport:
- composer require resend/resend-laravel (v1.4)
- Laravel 11 ships the 'resend' mailer config in config/mail.php + services
- To switch to production email: set MAIL_MAILER=resend + RESEND_API_KEY,
register the domain at resend.com/domains, and add the TXT + DKIM CNAME
records in Cloudflare. .env.example documents the required steps.
Backblaze B2 offsite backup:
- New filesystems 'b2' disk (S3-compatible, env: B2_KEY/SECRET/BUCKET/REGION/ENDPOINT)
- BackupAllTenantsCommand: after writing each tenant's zip to local disk, it
uploads the same file to the b2 disk under {YYYY-MM-DD}/{slug}.zip — only
when both B2_KEY and B2_BUCKET are set, so unconfigured installs are no-op
- Without offsite, backups live on the same VPS as production: a single
hardware failure loses everything. B2 + Resend together make the install
genuinely production-ready (people get email + offsite backup).
Tests (2 new):
- backup uploads to b2 (fake disk) when configured
- backup skips offsite when env vars not present
Full suite: 140 passed. Force-rebuild deploy required so composer install
picks up resend/resend-php.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rate limiting:
- Shop POST endpoints get per-IP throttles with distinct prefixes so login,
register, password-email, and password-reset have separate buckets:
login/register/pw-reset = 5/min, pw-email = 3/min
- OcrInvoiceService gates per-tenant via RateLimiter (30/hour) so a runaway
uploader can't burn Claude Vision spend
Health monitor (poor-man's monitoring):
- HealthCheckCommand probes DB (SELECT 1), cache write/read, public storage
write/read, and most-recent backup age. On any failure, pushes a Telegram
alert via HEALTH_ALERT_BOT_TOKEN/HEALTH_ALERT_CHAT_ID. Dedups identical
failures within a 30-min window via cache.
- Scheduled every 10 min. Pair with external uptime monitoring (UptimeRobot,
Better Stack hitting /up) for total-outage coverage.
- .env.example documents the two new env vars.
VAPID secret hygiene:
- credentials.md no longer stores the VAPID_PRIVATE_KEY; the source of truth
is the Coolify env on the autocrm app. Doc points to where to read it
(UI or API). Mitigates accidental git leak.
Tests (4 new):
- shop login throttles after 5 attempts (6th = 429); register throttle is
independent of login (separate prefix); health command runs clean; dedup
cache path exercised
Full suite: 138 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>