feat: auth (2FA/passkeys), activity log, domain status checks, user/team management#19
Merged
Conversation
Add a Horizon navigation point to AdminSidebar. Uses a plain anchor (full-page navigation) since Horizon is a Blade-rendered dashboard, not an Inertia page. Access stays consistent with the super_admin-gated admin area and Horizon's viewHorizon gate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Share the package.json version as an Inertia prop and render it as a muted label at the bottom of the sidebar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Render the shared version prop at the AdminSidebar bottom and in the GuestLayout (branding panel on desktop, footer on mobile). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a themed confirmDelete() helper (resources/js/lib/confirm.ts) that follows the app's light/dark theme and defaults focus to Cancel, then wire it into all delete actions across links, domains, QR codes, pixels, team, and admin pages. The previously unguarded team invitation revoke now requires confirmation too. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prevents double-submission of the disable and recovery-code regeneration requests, matching the existing processing guard on the confirm button. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ings Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…led button hover Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… matching - Block SSRF in checkReachable: resolve host IPs first; refuse if empty or any IP is private/reserved/loopback/link-local using isPublicIp() (filter_var FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE); disable redirect following with allow_redirects=false. - Tighten certCoversHost wildcard matching: *.example.com now matches only hosts with the same dot-label count (one wildcard label), preventing deep.sub.example.com from matching. - Guard SystemCertificateReader::read() against openssl_x509_parse() returning false. - Add TDD tests: SSRF private IP refused, SSRF unresolvable refused, wildcard single-label match, wildcard multi-label rejection, fault isolation (throwing resolver does not abort SSL check). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… and custom model Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unused Spatie Activity import from published config - Add down() to published create_activity_log_table migration - Remove unused ActivitylogServiceProvider import from SchemaTest Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nges spatie/laravel-activitylog v5 renamed the subject hook from tapActivity to beforeActivityLogged and stores attribute diffs in $activity->attribute_changes rather than ->properties. The original trait targeted the v4 names, so it was silently inert: the project tag was never set and sensitive values were never redacted in production. Retarget the hook and redact attribute_changes (plus properties defensively). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ attribute_changes) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Array Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…erns, Support\LogOptions, dontLogEmptyChanges) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ot authenticatable) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… spacing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oject in admin feed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Spatie-published migration created subject_id/causer_id as bigint, but all subjects (Url/Domain/QrCode/Pixel/Project) and causers (User) use ULID keys. On MariaDB this truncated inserted ULIDs (demo:setup crash); SQLite's loose type affinity hid it in the test suite. Switch both morphs to nullableUlidMorphs (char 26). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
$request->ip() returned the Docker proxy's internal IP because no proxies were trusted, so X-Forwarded-For was ignored. Configure trustProxies(at: '*') to read forwarded headers, fixing client IP, geo lookup, unique-click dedup, and activity log. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Create or promote a global super admin from the CLI. Accepts --name, --email, --password flags with interactive fallback (password prompted securely with confirmation). Promotes an existing user without resetting their password; no-ops when already a super admin. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Import ordering, brace position, and unused-import cleanup across controllers, routes, config, and tests. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI copies .env.example, which sets TRAEFIK_DYNAMIC_FILE=/traefik/..., an unwritable path on the runner. Tests that create a Domain ran the synchronous RegenerateTraefikConfigJob and failed on file_put_contents. Add Queue::fake([RegenerateTraefikConfigJob::class]) in setUp() for the six affected files, matching the existing convention used across the suite. The check endpoint still persists via dispatchSync of the real CheckDomainStatusJob. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The partial Queue::fake([RegenerateTraefikConfigJob::class]) was duplicated in setUp() across 15 test files. Centralize it in Tests\TestCase::setUp() so every test inherits it and future domain-creating tests can't regress on the unwritable Traefik path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Large feature branch bringing several capabilities to Marketix. 65 commits, 130 files. Grouped by area below.
Auth & account security
laravel/passkeys) as a second factor, with login/challenge buttons and profile management UI.force_password_changecolumn, gate, dedicated page/endpoint.Activity log (Spatie activitylog v5)
ActivityRecorderhelper for manual events; project-scopedproject_idcolumn and custom model.Domains
CheckDomainStatusJob(single write path) andDomainStatusChecker./.well-known/marketixsignature route, on-demand check endpoint.Users & team
last_sent_at, expired badges, cross-project isolation test.Admin & layout
marketix:create-adminconsole command (create or promote a super admin).marketix:prefix.Stats
Test plan
docs/.🤖 Generated with Claude Code