Enforces Nazim database migration patterns. Use when creating new tables, adding columns, or writing SQL migrations. Covers UUID primary keys, organization_id, school_id, RLS, search_path, policy naming, and Laravel migration format.
All migrations must follow these patterns for security, consistency, and multi-tenancy.
ALL tables use UUID primary keys.
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
$table->uuid('id')->primary()->default(DB::raw('gen_random_uuid()'));
public $incrementing = false;
protected $keyType = 'string';
// In boot(): static::creating() with Str::uuid() if not set
organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADEschool_id UUID (for school-scoped resources)organization_id and school_idSchema::create('your_table', function (Blueprint $table) {
$table->uuid('id')->primary()->default(DB::raw('gen_random_uuid()'));
$table->uuid('organization_id')->nullable();
$table->foreign('organization_id')->references('id')->on('organizations')->onDelete('cascade');
$table->uuid('school_id')->nullable(); // if school-scoped
// ... other columns
$table->timestamps();
$table->timestamp('deleted_at')->nullable();
$table->index('organization_id');
$table->index('school_id');
});
ALWAYS set search_path = public to prevent injection:
CREATE OR REPLACE FUNCTION public.your_function()
RETURNS TRIGGER
LANGUAGE plpgsql
SET search_path = public
AS $$
BEGIN
-- body
RETURN NEW;
END;
$$;
DROP IF EXISTS (no NOTICE noise)SET search_path = public