fail('Invalid write accepted'); } catch (QueryException $e) { $this->assertSame($state, $e->getCode()); } finally { DB::statement('ROLLBACK TO SAVEPOINT invalid_skills_case'); } } public function test_master_types_private_defaults_and_immutable_audit(): void { $this->assertSame(24, DB::table('pg_tables')->where('schemaname', 'skills_edu')->count()); $missing = DB::selectOne(<<<'SQL' SELECT count(*) AS n FROM pg_constraint c JOIN pg_namespace ns ON ns.oid=c.connamespace WHERE ns.nspname='skills_edu' AND c.contype='f' AND NOT EXISTS ( SELECT 1 FROM pg_index i JOIN pg_class ix ON ix.oid=i.indexrelid JOIN pg_am am ON am.oid=ix.relam WHERE i.indrelid=c.conrelid AND i.indisvalid AND i.indisready AND i.indpred IS NULL AND am.amname='btree' AND i.indnkeyatts>=cardinality(c.conkey) AND ARRAY(SELECT x FROM unnest(i.indkey::smallint[]) WITH ORDINALITY k(x,p) WHERE p<=cardinality(c.conkey) ORDER BY p)=c.conkey) SQL); $this->assertSame(0, (int) $missing->n); $this->assertNull(DB::selectOne("SELECT to_regclass('skills_edu.skills') AS id")->id); $this->assertSame('bigint', DB::selectOne("SELECT format_type(atttypid,atttypmod) AS type FROM pg_attribute WHERE attrelid='skills_edu.professional_profiles'::regclass AND attname='user_master_id'")->type); $this->rejected("INSERT INTO skills_edu.skill_details(id,category) VALUES(gen_random_uuid(),'technical')", '23503'); $this->rejected("INSERT INTO skills_edu.professional_profiles(full_name,registration_mode,user_master_id) VALUES('Synthetic','individual',9223372036854775807)", '23503'); $profile = DB::selectOne("INSERT INTO skills_edu.professional_profiles(full_name,registration_mode) VALUES('Synthetic','individual') RETURNING id,visibility_level,status"); $this->assertSame('private', $profile->visibility_level); $this->assertSame('draft', $profile->status); $this->rejected("INSERT INTO skills_edu.profile_experiences(profile_id,job_title,started_on,ended_on) VALUES('$profile->id','Synthetic','2026-02-02','2026-01-01')", '23514'); DB::statement("INSERT INTO skills_edu.audit_events(action,object_type,result,correlation_id) VALUES('synthetic','test','success',gen_random_uuid())"); foreach (['UPDATE skills_edu.audit_events SET action=action', 'DELETE FROM skills_edu.audit_events', 'TRUNCATE skills_edu.audit_events'] as $sql) { $this->rejected($sql, '23514'); } } public function test_reverse_order_rollback_reapply_and_nonempty_refusal(): void { $files = glob(database_path('migrations/2026_09_30_*_skills_education_*.php')); foreach (array_reverse($files) as $file) { (require $file)->down(); } $this->assertNull(DB::selectOne("SELECT to_regnamespace('skills_edu') AS id")->id); foreach ($files as $file) { (require $file)->up(); } $this->assertSame(24, DB::table('pg_tables')->where('schemaname', 'skills_edu')->count()); DB::statement("INSERT INTO skills_edu.audit_events(action,object_type,result,correlation_id) VALUES('synthetic','test','success',gen_random_uuid())"); $this->expectException(\RuntimeException::class); $this->expectExceptionMessage('destructive rollback refused'); (require end($files))->down(); } }