Commit Graph

23 Commits (79da7502cda122db78cb075c3d5bb1cded77c4e6)

Author SHA1 Message Date
boban a3930b5d25 test(security): assert Permissions-Policy header 2026-05-16 07:52:20 +02:00
boban 3f6b281c62 feat(security): add HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy headers 2026-05-16 07:51:33 +02:00
boban c8a6325a77 feat(webhooks): outgoing webhooks with HMAC signature, SSRF protection, retry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 07:46:57 +02:00
boban 3568e67ca0 fix(api): use DeleteLink action for cache invalidation, fix validation, add delete tests 2026-05-16 07:42:56 +02:00
boban 1375519cdb feat(api): REST API v1 — links CRUD with Sanctum auth
Adds /api/v1/workspaces/{ulid}/links endpoints (index, store, destroy)
protected by Sanctum token auth; adds HasApiTokens to User model and
AuthorizesRequests to base Controller; wires routes/api.php into bootstrap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 07:38:45 +02:00
boban 8f1398380f fix(billing): pm_type/pm_last_four migration, narrow CSRF exclusion, EU paper size
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:46:54 +02:00
boban 06dbb1dffb feat(billing): Cashier Billable on Workspace, Stripe webhook route
- Add Laravel\Cashier\Billable trait to Workspace model
- Register Workspace as Cashier customer model in AppServiceProvider
- Publish cashier config with EUR currency and de_DE locale defaults
- Add CSRF exclusion for stripe/* in bootstrap/app.php
- Add StripeWebhookTest verifying endpoint exists and rejects bad signatures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:35:11 +02:00
boban 5c5ddbbe83 fix(i18n): remove stale redis del pattern, drop dead singleton 2026-05-16 01:29:45 +02:00
boban b121520ed6 fix(i18n): include namespace in cache key/query, clean up singleton, test isolation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:27:10 +02:00
boban ce9e53d206 feat(i18n): database-backed translation loader with Redis cache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:20:48 +02:00
boban 15f4b2c0d8 fix(qr): wifi/vcard injection protection, remove dead code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:16:47 +02:00
boban d3b777d8e8 feat(qr): QR code renderer (SVG + PNG), model, generate action
Implements QrRenderer using chillerlan/php-qrcode v6 API (outputInterface
instead of deprecated outputType constants), QrCode Eloquent model with
ULID auto-generation and soft deletes, and GenerateQrCode action.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:13:41 +02:00
boban dd89ee395c feat(billing): plan limits service, plan factory, seeder (free/pro/business/agency) 2026-05-16 01:06:01 +02:00
boban e06db03320 feat(routing): smart routing engine with condition evaluator (device, country, UTM) 2026-05-16 01:01:47 +02:00
boban 66e559173c feat(analytics): click recording job with IP hashing, device detection, Redis counters
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:56:52 +02:00
boban ebdcd141bb feat(redirect): hot-path redirect controller with Redis cache, 302/404/410
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:52:16 +02:00
boban b59dbfd95b fix(link): nullable field update, redis test key isolation 2026-05-16 00:48:15 +02:00
boban 69e6318db5 feat(link): cache service, create/update/delete actions, slug generation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:46:06 +02:00
boban 49f2e3b00f feat(workspace): create action, middleware, policies
- CreateWorkspace action: creates workspace + owner member + sets default_workspace_id
- ResolveWorkspace middleware: resolves workspace by ULID, 404s for non-members
- WorkspacePolicy: owner/admin/editor/viewer role-based gates
- Register WorkspacePolicy in AppServiceProvider
- Add ulid string cast to Workspace model to ensure scalar after create()
- Feature test: CreateWorkspaceTest (4 assertions, passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:41:32 +02:00
boban ee0824302a fix(auth): remove dummy login route, validate locale allowlist
- Remove no-op POST /login route that caused named-route collision and
  was testing throttle:5,1 middleware against a null handler.
- Rewrite LoginRateLimitTest to drive the real Volt login component via
  Volt::test(), verifying the RateLimiter blocks the 6th attempt with
  auth.throttle message; throttle is Laravel core, test confirms wiring.
- Add supported_locales allowlist to config/app.php ['de', 'en'].
- LocaleFromUser middleware now validates user locale against allowlist
  and falls back to app.locale for unknown/unsupported values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:38:32 +02:00
boban 9d5d5af24d feat(auth): argon2id hashing, locale middleware, login rate limiting
Switch default password hashing from bcrypt to argon2id, add
LocaleFromUser middleware appended to web stack, and add HTTP-level
throttle:5,1 on POST /login to satisfy the 429 rate-limit test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:32:26 +02:00
boban d0bb8f92ee feat(models): add core domain models
Creates Workspace, WorkspaceMember, WorkspaceInvitation, Link,
LinkVariant, Click (append-only), Plan, and Domain Eloquent models with
correct relationships. Updates User model with SoftDeletes, ULID
auto-generation on create, guarded/casts, and workspace relationships.
Fixes ProfileTest assertion to match SoftDeletes behavior on User.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:19:51 +02:00
boban 25dddf5293 feat: initial Nimuli scaffold with Laravel 12, Livewire 3, Octane, Reverb, Docker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:51:57 +02:00