'user'], ['name' => ['ko' => '사용자', 'en' => 'User']]); $this->user = User::factory()->create(['email' => 'mw@example.com']); Route::middleware(['auth:sanctum', 'identity.policy:test.mw.policy']) ->get('/api/test/idv-guarded', fn () => response()->json(['ok' => true])); } public function test_policy_not_found_passes_through(): void { Sanctum::actingAs($this->user); $response = $this->getJson('/api/test/idv-guarded'); $response->assertStatus(200); } public function test_enabled_policy_without_verified_log_returns_428(): void { Sanctum::actingAs($this->user); IdentityPolicy::create([ 'key' => 'test.mw.policy', 'scope' => 'route', 'target' => 'api.test.mw', 'purpose' => 'sensitive_action', 'grace_minutes' => 0, 'enabled' => true, 'source_type' => 'admin', 'source_identifier' => 'admin', 'applies_to' => 'both', 'fail_mode' => 'block', ]); $response = $this->getJson('/api/test/idv-guarded'); $response->assertStatus(428) ->assertJsonPath('error_code', 'identity_verification_required') ->assertJsonPath('verification.policy_key', 'test.mw.policy'); } public function test_grace_window_with_recent_verified_allows_request(): void { Sanctum::actingAs($this->user); IdentityPolicy::create([ 'key' => 'test.mw.policy', 'scope' => 'route', 'target' => 'api.test.mw', 'purpose' => 'sensitive_action', 'grace_minutes' => 5, 'enabled' => true, 'source_type' => 'admin', 'source_identifier' => 'admin', 'applies_to' => 'both', 'fail_mode' => 'block', ]); IdentityVerificationLog::create([ 'id' => (string) Str::uuid(), 'provider_id' => 'g7:core.mail', 'purpose' => 'sensitive_action', 'channel' => 'email', 'user_id' => $this->user->id, 'target_hash' => hash('sha256', $this->user->email), 'status' => IdentityVerificationStatus::Verified->value, 'verified_at' => now(), 'expires_at' => now()->addMinutes(15), ]); $response = $this->getJson('/api/test/idv-guarded'); $response->assertStatus(200); } public function test_disabled_policy_passes_through(): void { Sanctum::actingAs($this->user); IdentityPolicy::create([ 'key' => 'test.mw.policy', 'scope' => 'route', 'target' => 'api.test.mw', 'purpose' => 'sensitive_action', 'grace_minutes' => 0, 'enabled' => false, 'source_type' => 'admin', 'source_identifier' => 'admin', 'applies_to' => 'both', 'fail_mode' => 'block', ]); $response = $this->getJson('/api/test/idv-guarded'); $response->assertStatus(200); } }