Skip to content

1.0.2

Choose a tag to compare

@tdrabikdev tdrabikdev released this 15 Jul 14:00
049f328

A contact form that actually sends, and a security gate that can finally report.

1238 tests pass (11 added). Verified end-to-end against a real SMTP inbox, not mocks.

Versioning note. Continues the v1 line. The release before v1.0.0 was v13.0.0, which tracked the Laravel major, and Composer still orders 13.0.0 above this tag — so composer create-project resolves v13.0.0 unless you pin 1.0.2 explicitly. The v1 tag now points here.

The contact form now sends

It previously sent nothing, anywhere. The page was Preline's SaaS template pasted verbatim: the <form> had no action, no method, no @csrf, and Route::view meant no handler existed to receive it — submitting just reloaded the page. A second, orphaned form component posted to /contact/send, which 404s and which nothing rendered.

Now: routes, a controller, validation, and a Mailable to the merchant's configured site_email with Reply-To set to the visitor, so replying is one click. From stays the app's own sender — sending as the visitor would fail SPF/DKIM and land in spam.

Anti-spam: a honeypot plus throttle:5,1. The honeypot is checked before validation and answers exactly as a success would — validating it would hand a bot the name of the field that caught it. It's sr-only + aria-hidden + tabindex="-1"; the tab order was verified in a browser to skip it entirely.

Fixed alongside: {{ env('APP_NAME') }} in a view (returns null under config:cache, so it rendered blank in production); field names left as the template's hs-firstname-contacts-1; placeholder-as-label, which vanishes the moment you type; and the four "Knowledgebase / Developer APIs / Contact sales" blocks — SaaS copy on a shop, all four linking to #. They're replaced by the contact details the merchant has actually configured, each shown only when set.

The security audit job works

Dependency Security Audit had failed on every run since at least 2026-07-14 and had never reported on a single dependency. It ran composer audit with no vendor/ tree and no --locked, so it died on Composer's own advice every time.

It now audits the lock file directly — the versions that actually deploy — and reports zero advisories. Which it could never have told anyone before.

A permanently-red security gate is worse than no gate: it trains everyone to scroll past the one check whose entire job is to shout. It sat red through the v1.0.1 security release.

Known issues, carried forward

  • Public registration is broken, and that bug is the only thing masking an access-control hole. CreateNewUser assigns a staff role no seeder creates, so signup rolls back. Behind it, every registrant would join the store's primary team, canAccessPanel returns true for /app, and Article/ProductCollection have no policies (Filament allows by default). Must be fixed together.
  • SVG stored XSS is latent — product upload accepts image/svg+xml onto a public disk. Unreachable today (no public/storage symlink); live the moment storage:link runs.
  • /user/profile renders only because social login defaults off; enabling a provider re-breaks it (// use HasConnectedAccounts; is commented out in User).
  • Password::default() is min 8, no complexity, no breach check.
  • The seeder sets inventory_count = 0 on every product, so the demo storefront ships sold-out.
  • The Dependency Security Audit job covers Composer only; the project also ships npm dependencies. npm audit --omit=dev reports 0 today.

Full changelog: v1.0.1...v1.0.2