Database Engineering

بناء سجلات تدقيق جنائية باستخدام PostgreSQL

في مجال هندسة قواعد البيانات، الثقة ليست خياراً؛ بل هي الأساس. عند التعامل مع المعاملات المالية أو السجلات الصحية أو الوثائق القانونية، يعد القدرة على إثبات ما حدث بالضبط، ومتى حدث، ومن قام به أمراً حاسماً. هنا تأتي سجلات التدقيق الجنائية في حيّز التنفيذ. غالباً ما تفشل طرق التسجيل التقليدية لأن السجلات قابلة للتغيير ويمكن تعديلها بسهولة. لتحقيق النزاهة الحقيقية، يجب علينا اعتماد نموذج مصدر أحداث غير قابل للتغيير مدعوم بقاعدة بيانات علائقية قوية مثل PostgreSQL.

يستكشف هذا المقال كيفية تنفيذ مخزن أحداث غير قابل للتغيير باستخدام PostgreSQL، مما يضمن أن بيانات التدقيق الخاصة بك قابلة للكشف عن التلاعب ومتوافقة مع معايير تنظيمية صارمة.

لماذا تعتبر عدم القابلية للتغيير أمراً بالغ الأهمية للامتثال

تتطلب أطر الامتثال مثل اللائحة العامة لحماية البيانات (GDPR)، وقانون نقل التأمين الصحي والمحاسبة (HIPAA)، ومعايير SOC 2 من المنظمات الحفاظ على سلامة البيانات. يمكن تفسير عملية التحديث أو الحذف القياسية على سجل التدقيق على أنها محاولة للتستر، حتى لو كانت خطأً إدارياً. من خلال جعل سجل التدقيق غير قابل للتغيير، نضمن أنه بمجرد تسجيل حدث، لا يمكن تغييره أو إزالته. هذا يخلق "سلسلة حيازة" لتغييرات البيانات، مما يوفر للمطورين والمراجعين مصدراً واحداً للحقيقة.

يتطلب تنفيذ ذلك في PostgreSQL تحولاً من عمليات CRUD التقليدية (إنشاء، قراءة، تحديث، حذف) إلى استراتيجية الإضافة فقط (Append-Only). سنستخدم ميزات PostgreSQL مثل AFTER المحفزات وUNLOGGED الجداول بعناية، ولكن لأغراض جنائية، سنلتزم بالجداول القياسية الدائمة ذات القيود الصارمة.

تصميم مخطط مخزن الأحداث

في صلب حلنا توجد جدول مخصص لتخزين الأحداث. يمثل كل حدث تغييراً في الحالة داخل منطق الأعمال. لضمان إمكانية التتبع، يجب أن يتضمن كل سجل معرفاً فريداً، وطابعاً زمنياً، والمستخدم أو النظام المسؤول، وحالة التغيير.

CREATE TABLE audit_events (
    event_id BIGSERIAL PRIMARY KEY,
    timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    user_id UUID NOT NULL,
    action VARCHAR(50) NOT NULL,
    entity_type VARCHAR(50) NOT NULL,
    entity_id VARCHAR(100) NOT NULL,
    old_state JSONB,
    new_state JSONB,
    metadata JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Ensure no updates or deletes are possible on this table
ALTER TABLE audit_events 
  DROP CONSTRAINT IF EXISTS audit_events_pkey,
  ADD CONSTRAINT audit_events_pkey PRIMARY KEY (event_id);

-- Disable all update and delete permissions for standard roles
REVOKE UPDATE, DELETE ON audit_events FROM PUBLIC;
GRANT INSERT, SELECT ON audit_events TO app_user;

من خلال سحب صلاحيات UPDATE وDELETE على مستوى قاعدة البيانات، نفرض عدم القابلية للتغيير حتى إذا فشل منطق التطبيق. هذه استراتيجية دفاع متعددة الطبقات وهي أمر بالغ الأهمية للنزاهة الجنائية.

تنفيذ محفز التدقيق

بدلاً من كتابة عبارات الإدراج يدوياً لكل حدث تدقيقي، يمكننا الاستفادة من محفزات PostgreSQL لالتقاط التغييرات تلقائياً. يقلل هذا من الكود النمطي ويقلل من الأخطاء البشرية. على سبيل المثال، إذا قام مستخدم بتحديث سجل في جدول users، يمكن لمحفز أن يعمل تلقائياً، التقاط الحالات القديمة والجديدة.

CREATE OR REPLACE FUNCTION capture_user_changes()
RETURNS TRIGGER AS $$
BEGIN
    IF (TG_OP = 'UPDATE') THEN
        INSERT INTO audit_events (user_id, action, entity_type, entity_id, old_state, new_state)
        VALUES (
            NEW.updated_by,
            'UPDATE',
            'users',
            NEW.id::TEXT,
            row_to_json(OLD)::jsonb,
            row_to_json(NEW)::jsonb
        );
        RETURN NEW;
    ELSIF (TG_OP = 'DELETE') THEN
        INSERT INTO audit_events (user_id, action, entity_type, entity_id, old_state)
        VALUES (
            NEW.updated_by,
            'DELETE',
            'users',
            OLD.id::TEXT,
            row_to_json(OLD)::jsonb
        );
        RETURN OLD;
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER audit_user_changes
    AFTER UPDATE OR DELETE ON users
    FOR EACH ROW
    EXECUTE FUNCTION capture_user_changes();

استعلام السجل غير القابل للتغيير

أحد نقاط قوة PostgreSQL هو دعمه لـ JSONB. يمكننا استعلام سجل التدقيق الخاص بنا بكفاءة للتغييرات المحددة دون مسح الصفوف بأكملها. على سبيل المثال، العثور على جميع التغييرات لحقل معين أمر بسيط:

SELECT *
FROM audit_events
WHERE entity_type = 'users'
  AND entity_id = '123e4567-e89b-12d3-a456-426614174000'
  AND new_state->>'email' != old_state->>'email';

يتيح هذا الاستعلام لمسؤولي الامتثال تحديد متى تم تغيير عنوان البريد الإلكتروني بالضبط، ومن قبل من، وما كانت القيمة السابقة.

الخاتمة

بناء سجلات تدقيق جنائية ليس مجرد تخزين للبيانات؛ بل هو إقامة الثقة. من خلال الجمع بين القدرات المعاملية القوية لـ PostgreSQL مع نمط مصدر الأحداث غير القابل للتغيير، يمكن للمطورين إنشاء أنظمة مرنة ضد التلاعب ومتوافقة مع أشد اللوائح صرامة. بينما يضيف هذا النهج تعقيداً للعمليات الكتابة، فإن راحة البال التي يوفرها للأمن والامتثال لا تقدر بثمن. مع تزايد مخاوف خصوصية البيانات، ستصبح السجلات غير القابلة للتغيير مطلباً قياسياً، وليس مجرد أفضل ممارسة.

Share: