assertSame('simulator_fiscal_delta_20261021_test', $identity->name); $this->assertSame(55441, (int) $identity->port); $this->withoutVite(); $this->withoutMiddleware(ThrottleRequests::class); config(['portal.profile_access_enabled' => true, 'portal.managers' => [], 'investor-path.enabled' => true, 'suitecrm.enabled' => false, 'investmoz_ai.enabled' => false]); $this->actor = User::factory()->create(['two_factor_secret' => Crypt::encryptString('JBSWY3DPEHPK3PXP'), 'two_factor_confirmed_at' => now()]); $other = User::factory()->create(); DB::table('portal_superuser_pair')->updateOrInsert(['id' => 1], ['first_user_id' => $this->actor->id, 'second_user_id' => $other->id, 'approved_by' => $other->id]); $this->territory = DB::table('geo_geometries as g')->join('geo_locations as l', 'l.id', '=', 'g.geo_location_id') ->where('g.source_system', 'ine-cod-ab')->where('g.data_classification', 'internal')->where('l.location_type', 'province')->value('l.id'); $this->assertNotEmpty($this->territory); } public function test_general_consumer_uses_existing_authenticated_read_access_without_the_legacy_gate(): void { $this->assertFalse($this->actor->can('manage-portal')); $before = $this->fingerprint(); $this->actingAs($this->actor)->getJson('/api/v1/investment/territory-geometries?territory_id='.$this->territory) ->assertOk()->assertJsonPath('selected_geometry_available', true)->assertJsonPath('geometry_scope', 'authorized_internal') ->assertJsonPath('areas.0.territory_id', $this->territory)->assertHeader('Cache-Control', 'no-store, private'); $this->assertSame($before, $this->fingerprint()); } public function test_existing_administration_reaches_the_same_geometry_with_its_completed_mfa_session(): void { $this->actingAs($this->actor)->withSession(['portal.mfa_actor' => $this->actor->id, 'portal.mfa_at' => time(), 'portal.access_revision' => (int) $this->actor->portal_access_revision]); $this->getJson('/management/territory-geometries?territory_id='.$this->territory)->assertOk()->assertJsonPath('selected_geometry_available', true); session()->forget(['portal.mfa_actor', 'portal.mfa_at']); $this->getJson('/management/territory-geometries?territory_id='.$this->territory)->assertForbidden(); } public function test_anonymous_and_ordinary_accounts_do_not_receive_or_publish_internal_layers(): void { $before = $this->fingerprint(); $url = '/api/v1/investment/territory-geometries?territory_id='.$this->territory; $this->getJson($url)->assertOk()->assertJsonPath('geometry_scope', 'public')->assertJsonPath('selected_geometry_available', false)->assertJsonCount(0, 'areas'); $this->actingAs(User::factory()->create())->getJson($url)->assertOk()->assertJsonPath('geometry_scope', 'public')->assertJsonCount(0, 'areas'); $this->getJson('/management/territory-geometries?territory_id='.$this->territory)->assertForbidden(); $this->assertSame($before, $this->fingerprint()); } public function test_saved_territory_is_recovered_in_dossier_and_simulator_and_the_map_uses_that_identity(): void { $this->actingAs($this->actor); $id = $this->postJson('/investimentos', ['title' => 'SYNTHETIC QA - mapa recuperado', 'client_key' => (string) Str::uuid(), 'reuse_consent' => true])->assertCreated()->json('id'); $body = ['version' => $this->getJson('/investimentos/'.$id.'/contexto')->json('case.version'), 'selection' => ['territory' => 'territory:'.$this->territory]]; $preview = $this->postJson('/investimentos/'.$id.'/contexto/previa', $body)->assertOk()->json(); $this->postJson('/investimentos/'.$id.'/contexto/confirmar', [...$body, 'preview_hash' => $preview['preview_hash'], 'operation_key' => (string) Str::uuid(), 'confirm' => true])->assertOk(); $view = $this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->json(); $this->assertSame($this->territory, $view['context']['selection']['territory']['id']); $this->assertSame($this->territory, $view['prefill']['simulator']['province_id']); $this->getJson('/api/v1/investment/territory-geometries?territory_id='.$view['prefill']['simulator']['province_id']) ->assertOk()->assertJsonPath('selected_geometry_available', true)->assertJsonPath('areas.0.selected_territory', true); $this->assertSame($this->territory, $this->getJson('/investimentos/'.$id.'/contexto')->json('context.selection.territory.id')); } public function test_only_the_approved_unchanged_snapshot_is_public_without_reclassifying_the_original(): void { $before = $this->fingerprint(); $row = DB::table('geo_geometries as g')->where('geo_location_id', $this->territory)->first([ 'g.id', 'g.geo_location_id', DB::raw("encode(sha256(ST_AsEWKB(g.geom)),'hex') as geometry_sha256"), DB::raw("encode(sha256(convert_to(g.properties::text,'UTF8')),'hex') as properties_sha256"), ]); // The QA import has its own identities; never copy or replace production rows. $approved = $this->partialMock(ApprovedAdministrativeBoundaries::class); $approved->shouldReceive('snapshots')->andReturn([$row->id => [ 'territory_id' => $row->geo_location_id, 'geometry_sha256' => $row->geometry_sha256, 'properties_sha256' => $row->properties_sha256, ]]); $url = '/api/v1/investment/territory-geometries?territory_id='.$this->territory; $this->getJson($url)->assertOk()->assertJsonPath('selected_geometry_available', true) ->assertJsonPath('areas.0.data_classification', 'public')->assertJsonPath('investment_site', false); $this->actingAs(User::factory()->create())->getJson($url)->assertOk()->assertJsonPath('selected_geometry_available', true); $this->assertSame($before, $this->fingerprint()); $this->assertSame('internal', DB::table('geo_geometries')->where('id', $row->id)->value('data_classification')); DB::table('geo_geometries')->where('id', $row->id)->update(['properties' => DB::raw("properties || '{\"qa_changed\":true}'::jsonb")]); $this->getJson($url)->assertOk()->assertJsonPath('selected_geometry_available', false)->assertJsonCount(0, 'areas'); $this->actingAs($this->actor)->getJson($url)->assertOk()->assertJsonPath('selected_geometry_available', true); } public function test_public_manifest_has_the_exact_approved_scope_and_immutable_hash(): void { $items = app(ApprovedAdministrativeBoundaries::class)->snapshots(); $this->assertCount(408, $items); $this->assertCount(408, array_unique(array_column($items, 'territory_id'))); $this->assertSame(['2019-06-07'], array_values(array_unique(array_column($items, 'source_version')))); } private function fingerprint(): string { return DB::selectOne("select md5(string_agg(row_to_json(g)::text,E'\\n' order by id)) as hash from geo_geometries g")->hash; } }