agent = User::factory()->create(); $this->agentToken = $this->agent->createToken('fastapi-agent', TokenAbility::fastApiAgentAbilities())->plainTextToken; }); test('the agent token cannot refund a confirmed booking', function () { $booking = Booking::factory()->create(['status' => BookingStatus::Confirmed, 'price' => 15000]); Payment::factory()->completed()->create([ 'booking_id' => $booking->id, 'gateway' => PaymentMethod::KbzMiniApp, 'amount' => 15000, 'gateway_transaction_id' => 'EVB-AGENT-AUDIT-1', ]); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/refund", [ 'amount' => 15000, 'reason' => 'agent should never reach this', ]) ->assertForbidden(); expect($booking->refresh()->status)->toBe(BookingStatus::Confirmed); }); test('the agent token cannot cancel a booking it does not own', function () { $owner = User::factory()->create(); $booking = Booking::factory()->create(['user_id' => $owner->id, 'status' => BookingStatus::PendingPayment]); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel") ->assertForbidden(); expect($booking->refresh()->status)->toBe(BookingStatus::PendingPayment); }); test('catalog writes have no customer-facing route at all', function () { // These paths only exist as GET (read) routes โ€” a POST to them is // rejected as 405 (method not allowed), not routed to any write // handler, proving no write endpoint was ever registered. $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson('/api/v1/companies', ['name' => 'Should Not Exist']) ->assertStatus(405); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson('/api/v1/destinations', ['name' => 'Should Not Exist']) ->assertStatus(405); }); test('routing/pricing writes have no customer-facing route at all', function () { // Only a read-only search endpoint exists for EvRoute โ€” no create/update/ // delete route was ever registered, and the search endpoint itself // never creates records regardless of payload (it's POST because // round_trip returns two result sets, not because it writes anything). // {route} only has a GET (show) handler registered, so PUT/DELETE hit // that same URI pattern and are rejected as 405 (method not allowed). $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->putJson('/api/v1/routes/1', ['ev_company_id' => 1]) ->assertStatus(405); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->deleteJson('/api/v1/routes/1') ->assertStatus(405); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson('/api/v1/routes/search', ['ev_company_id' => 1]) ->assertSuccessful(); expect(EvRoute::count())->toBe(0); }); test('the agent token can still read routes and create/read bookings', function () { $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->postJson('/api/v1/routes/search') ->assertSuccessful(); $booking = Booking::factory()->create(['user_id' => $this->agent->id]); Payment::factory()->completed()->create(['booking_id' => $booking->id, 'gateway' => PaymentMethod::KbzMiniApp]); $this->withHeader('Authorization', "Bearer {$this->agentToken}") ->getJson('/api/v1/bookings') ->assertSuccessful() ->assertJsonPath('data.0.id', $booking->id); });