boban
deb5f310a1
fix(bio): plan-aware URL + plan-seeder + ulid→slug fix
...
- Migration: add bio_pages_limit to plans, make limit cols nullable (agency=unlimited)
- PlanSeeder: 4 plans (free/pro/business/agency) with tier/features/bio_pages_limit
- workspaces:assign-default-plan command: assigns free plan to unassigned workspaces
- BioPage::publicUrl(): free=apex-path, pro+=subdomain, custom=custom-domain
- Security: str_ends_with check uses '.'.$apex to prevent evilnimu.li bypass
- BioPage::shortPublicUrl(): URL without scheme for display
- PlanLimitsService: use bio_pages_limit column (was features['bio_pages']), null=unlimited
- BioPageController: fix $bio → $page variable (view expects $page)
- Bio index/edit views: use publicUrl()/shortPublicUrl(), not hardcoded ULID URLs
- Bio edit view: publicUrlBase/displayUrlBase from component (plan-aware prefix)
- Create-bio modal: plan-aware URL prefix display
- PlanFactory/WorkspaceFactory: free()/pro() states for tests
- Tests: PublicUrlTest (5 cases), Free404FixTest (3 cases)
Known pre-existing failure (not caused by this change):
- Tests\Feature\Auth\EmailVerificationTest::email can be verified
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:44:54 +02:00
boban
1ff4114674
feat(sidebar+profile+buttons): sidebar active state, 3-tab profile, consistent button variants
...
- Sidebar JS: DOMContentLoaded + livewire:navigated updateActiveNav, data-nav-link on links
- Profile: exactly 3 tabs (Personal Info, Preferences, Security) with wire:navigate
- Buttons: all primary actions use bg-accent-gradient text-white
- UTM Builder + copy-to-clipboard Livewire event handler in app layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:14:04 +02:00
boban
ef0105098b
fix: workspace membership + middleware owner fallback
...
- DemoDataSeeder now creates workspace_members record for owner + sets default_workspace_id
- ResolveWorkspace middleware accepts workspace owners even without explicit member record
- Applied membership fix for nexxo@nimuli.com via PHP (existing installs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 11:17:54 +02:00
boban
ea9274be49
fix(quality): PHPStan level 6 compliance, Pint formatting
...
- Add phpstan.neon with level 6 config and larastan extension
- Fix all 92 PHPStan errors: Eloquent relation generics, iterable
value types, HasFactory generic annotations, missing return types
- Fix logic bugs: always-true Safari/Chrome comparison, nullsafe on
non-nullable Carbon, unused $renderer suppressed with ignore rule
- Implement MustVerifyEmail on User model (was commented out in Breeze
scaffold) to satisfy VerifyEmailController type contract
- Remove broken QrCode::newFactory() referencing non-existent factory
- Add @var docblocks for app('current_workspace') mixed resolution
- Apply Pint formatting: 53 style issues fixed across 168 files
- Test suite unchanged: 9 pre-existing assertSeeLivewire failures,
55 tests passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 08:28:10 +02:00
boban
e9623b9b31
feat(bio): Link-in-Bio pages with translatable fields, public render
2026-05-16 08:10:59 +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
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
86f767a626
fix(analytics): UTM from query string, iOS before macOS detection, remove dead referer fallback
2026-05-16 01:00:10 +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
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
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