Commit Graph

14 Commits (ebdcd141bbb0216a86a720d4947b58d590dbcfcb)

Author SHA1 Message Date
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 587aa09b40 fix(workspace): unique slug generation, null-safe middleware auth guard 2026-05-16 00:43:55 +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 6a96b8e0a3 fix(models): null-guard isExpired, remove FK from guarded, add return types and casts
- Add null check to WorkspaceInvitation::isExpired() to prevent null errors
- Remove foreign key columns from protected $guarded to prevent silent mass-assignment drops in Workspace, Link, and Domain models
- Add explicit return types (HasMany, BelongsTo) to User relationship methods
- Add return type to Click::link() relationship method
- Add protected $casts for LinkVariant (weight, clicks_count, conversions_count)

Fixes code quality and type safety issues in domain models.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:27:15 +02:00
boban dc6ed34357 fix(models): auto-generate ulid on creating for Workspace and Link 2026-05-16 00:23:33 +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 3b19bbe88f fix(db): null-safe unique keys on rollup tables, workspace slug unique, link slug scoping
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:11:39 +02:00
boban 23fd5a5e30 feat(db): add all Phase 1 migrations
Creates all Nimuli domain tables: plans, workspaces, workspace_members,
workspace_invitations, billing_profiles, domains, links, link_variants,
qr_codes, bio_pages, bio_blocks, clicks (+ hourly/daily/by_referrer/by_utm
aggregates), translations, webhooks, webhook_deliveries. Also extends the
users table with ulid, 2FA fields, locale, theme, default_workspace_id,
and soft deletes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:04:01 +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
boban 364d1448c7 chore: initial Nimuli design spec 2026-05-15 22:08:27 +02:00