تخطَّ إلى المحتوى
netrewind
صندوق أسود للشبكة

كيف يعمل

سِجلّ واحد، وساعة واحدة، وسلسلة تُسمّي كل حلقة فيها

كل ما يسجّله NetRewind حدَث. وهذا البناء الواحد هو العقد الذي يقوم عليه النظام كلّه: المجمّعات تُنتجه، والمخزن يحفظه، ومحرّك الترابط يقرؤه، وسطر الأوامر يعرضه. وله رقم نسخة، وهو الآن schema v1.

خمسة مبادئ حدّدت شكله، وكلٌّ منها قيدٌ تُحاسَب عليه الشيفرة فعلًا، لا شعار يُرفع.

  1. 01

    الحدث تغيّرُ حالة أو قياسٌ مرصود، وليس حزمة قط

    تسجيل الفروق بدل حركة المرور هو ما يجعل أسبوعًا من التاريخ يسع في جيجابايتات لا تيرابايتات.

    وهو أيضًا سبب أن معظم المحفوظ نافعٌ مباشرةً أثناء العطل، لا مادةً خامًا يُنقَّب فيها عن جواب والانقطاع ما زال قائمًا.

  2. 02

    كل حدث قابل للربط

    كل حدث يحمل هويّات يمكن مطابقتها عبر المصادر. وبغير ذلك لا توجد سلسلة سببية، بل كومة سجلّات تشترك في ساعة واحدة لا غير.

    وهذا هو الفرق بين خمس أدوات يُبلّغ كلٌّ منها عن عَرَض، وسِجلٍّ واحد يمكن أن تُوصل فيه الأعراض بعضها ببعض.

  3. 03

    كل حدث يحمل دليله

    يُحفَظ على الحدث من الرصد الخام ما يكفي ليُري الإنسانَ لماذا صدّقناه، دون الرجوع إلى أداة أخرى.

    والدعوى التي لا تستطيع التحقّق منها إشاعة. وفي أثناء العطل، في الثالثة فجرًا، الإشاعة أسوأ من لا شيء: تكلّف ساعةً قبل أن يخطر لأحد أن يشكّ فيها.

  4. 04

    مفهوم واحد صارم للزمن

    الساعة المدنية والساعة المطّردة، كلتاهما بالنانوثانية، وكلتاهما بتوقيت UTC. وكل حدث يحملهما معًا، دائمًا.

    وهذا هو الحقل الذي تُخطئ فيه معظم الأنظمة على غير اكتراث، وهو الذي يقرّر هل يجوز الوثوق بالخط الزمني أصلًا أم لا.

  5. 05

    المسجّل يُقرّ بمواضع عماه

    الفجوة التي لا تُسجَّل لا تُميَّز عن مدّةٍ لم يقع فيها شيء.

    وهذا هو الفرق بين سجلٍّ ودليل. فـsystem.gap يقول بالضبط كم بقي المسجّل غير ناظر، مقيسًا على نبضة تُكتب كل عشر ثوانٍ. وsystem.drop يقول كم حدثًا اضطرّت النواة إلى إسقاطه حين فاضت الحلقة العازلة في eBPF.

    ومسجّلٌ يُسقط ما فاته في صمت ليس دليلًا على شيء: سيُظهر السِّجلّ شبكةً هادئة، والهدوء هو ما يستنتجه المشغّل حين لا يكون ثمّة خطب.

الظرف المشترك

يحمله كل حدث بلا استثناء، أيًّا كان ما أنتجه.

الحقلالنوعالمعنى
event_idULIDمُعرّف فريد، يترتّب معجميًّا بترتيب الإنشاء
schema_vuint16نسخة الظرف
ts_wallint64نانوثوانٍ منذ مبدأ يونكس، بتوقيت UTC
ts_monoint64نانوثوانٍ على الساعة المطّردة للراصد
observer_idstringأيُّ مسجّل رأى هذا
sourceenumnetlink · ebpf · conntrack · nftables · dhcp · dns · lldp · snmp · probe · config · internal
kindstringfamily.action، مثل l2.arp_binding_changed
severityenuminfo · notice · warn · error
confidenceuint8100 عند الرصد المباشر، وأقلّ عند الاستنتاج
subjectEntityRefالكيان الذي يدور الحدث حوله
relatedEntityRef[]الكيانات الأخرى الداخلة فيه
attrsobjectحقول تخصّ هذا النوع وحده
evidenceobjectالرصد الخام بعد تشذيبه
dedup_keystringيطوي تكرارات الحقيقة الواحدة في سطر واحد
countuint32كم تكرارًا طُوي

لماذا ساعتان

لأن السؤالين اللذين على الخط الزمني أن يجيب عنهما ليسا سؤالًا واحدًا، وما من ساعة واحدة تجيب عنهما معًا.

ts_wall

متى وقع هذا؟ وبه يستعلم الإنسان.

قد يقفز. فـNTP يصحّحه، ويُستأنف جهاز افتراضي، ويضبط أحدهم التاريخ بيده.

ts_mono

بأيّ ترتيب وقع هذا؟ وهو لا يقفز أبدًا.

لا معنى له عبر إعادة إقلاع، ولا يُقارَن بين جهازين.

تسجيلهما معًا هو ما يُبقي ترتيب الخط الزمني صحيحًا عبر تصحيحٍ للساعة، بدل أن يُعيد ترتيب نفسه في صمت — وذاك عطبٌ يُنتج روايةً للانقطاع معقولةً تمامًا وخاطئةً تمامًا.

وبه أيضًا يُكتشَف system.clock_step: حركةٌ في الساعة المدنية لم ترها الساعة المطّردة.

العنوان ليس هويّة

كيف تقول «الجهاز نفسه» على امتداد أسبوع؟

هذا أصعب قرار في المخطّط، وكل جواب سهل عنه خطأ. فعنوان الـIP ينتقل، وعنوان الـMAC يُزوَّر، والهواتف الحديثة تُعشّيه لكل شبكة، واسم المضيف قد لا يكون له وجود أصلًا.

فلا يُحفَظ العنوان بوصفه هويّةً لشيء. بل تشير الأحداث إلى host_id ثابت، يُحسَم عند الاستقبال بمطابقته على جدول هويّات زمني — جدولٍ لا يسجّل أيَّ صفةٍ كانت لأيّ جهاز فحسب، بل متى كانت له.

مخرَج مسجَّل
identity_binding
host_id ULID ثابت
attr_type mac | ipv4 | ipv6 | hostname | switch_port | dhcp_client_id
attr_value نصّ
valid_from طابع زمني
valid_to طابع زمني | NULL -- NULL تعني أنها ما زالت سارية
confidence uint8
جدول الهويّات الزمني
  • الحقل EntityRef.ID يحمل المُعرّف بعد حسمه، ويبقى فارغًا حتى يجري الحسم.
  • والحقل EntityRef.Label هو ما ينبغي أن يقرأه الإنسان.
  • والحقل EntityRef.Attrs يحفظ الأرصاد الخام — mac وip وifindex — فيبقى الحدث مفهومًا حتى لو تبيّن بعد حين أن الحسم كان خطأ.

مضيفواجهةجهازشبكة فرعية / VLANخدمةتدفّقراصد

والعائد استعلامٌ لا سبيل إلى كتابته بغير ذلك: أن تسأل عن عنوانٍ كما كان الثلاثاء الماضي فيعود إليك الجهاز الذي كان يحمله حينها، لا الذي يحمله الآن — ودون أن يجرّ معه أحداث الجهاز الذي صار العنوان له اليوم.

والحسم يقع عند الاستقبال لا عند الاستعلام، فلا يتبدّل الجواب تبعًا لوقت طرح السؤال.

قيد معلوم

تعشية عناوين MAC تكسر تتبّع الأجهزة المحمولة على المدى الطويل. ويضيّق dhcp client-id والبصمةُ السلوكية الفجوةَ ولا يسدّانها. وهذا يُقال صراحةً بدل أن يُموَّه عليه.

العائلات التسع

كل حدث واحدٌ من هذه، والعائلة هي ما قبل النقطة. تقول العائلة أيَّ طبقة من الشبكة يصف الحدث، ويقول الفعل الذي بعدها أيُّ تغيّر حالةٍ وقع.

وسبعةُ أنواع موزّعة على أربعٍ من هذه العائلات مُعلَنة في المخطّط ولا يُنتجها شيء، وعائلة change.* لا يُنتجها شيء البتّة. وقد أُدرجت مع ذلك وسُمّيت بما هي، لأن فهرسًا يُخفي ثغراته هو عين ما يحاجّ هذا المشروع ضدّه.

والمصادر أدناه مصادر لينكس. ولعائلة link.*، ومداخل الجيران تحت l2.*، ومداخل المسارات والعناوين تحت l3.*، مصدرٌ على Windows أيضًا — عبر IP Helper API بدل netlink. أما flow.* وpolicy.* وعائلات dhcp./dns./metric. فلا مصدر لها على Windows في هذا الإصدار؛ ويذكر تقرير قدرات المسجّل بدقة ما يراقبه بناءٌ معيّن.

link.*

الطبقة الأولى · netlink

  • link.up
  • link.down
  • link.flap
  • link.mtu_changed
  • link.error_rate_high

تُميَّز الحالة الإدارية — أن أحدهم أطفأ المنفذ — من الحالة التشغيلية — أن الحامل سقط — عبر attrs.cause. والإبلاغ عنهما معًا بوصفهما «الواجهة ساقطة» هو ما يجعل معظم الأدوات عديمة الجدوى في خضمّ العطل: للحالتين سببان مختلفان تمامًا وعلاجان مختلفان تمامًا. ولا يَعُدّ link.flap إلا سقوط الحامل، دون الإطفاء الإداري أبدًا: فتوالي الانقطاعات أمرٌ غير انقطاعٍ واحد، لكنّ مهندسًا يُطفئ منفذًا مرارًا إنما يعمل، وعدُّ ذلك ارتجافًا تحميلٌ للكابل وزرَ المهندس. أما link.error_rate_high فليس تغيّر حالة أصلًا: مصدره عدّادات أخطاء الواجهة حين تتجاوز نسبةً من مجموع الحزم.

l2.*

الطبقة الثانية · جدول الجيران في netlink

  • l2.arp_binding_new
  • l2.arp_binding_changed
  • l2.mac_moved
  • l2.duplicate_ip
  • l2.neighbor_failed

يفتح l2.arp_binding_changed من الحوادث أكثر مما يفتحه أيّ حدث آخر في هذه الطبقة: فانتقال ربطٍ تحت شبكة عاملة هو بعينه ما يبدو عليه الاختطاف والتحويل عند العطل والمدخلُ الساكن المضبوط خطأً، كلُّها من هنا سواء. وإذا كان العنوان الذي انتقل تحته هو البوّابة الافتراضية رُفعت خطورته إلى error بدل warn — الرصد نفسه، وعاقبةٌ أكبر بكثير. أما l2.lldp_neighbor_changed وl2.vlan_seen ففي المخطّط، ومُجمِّع LLDP لم يُكتب، فطوبولوجيا جهة السويتش أكبر ما لا يزال هذا المسجّل عاجزًا عن رؤيته.

l3.*

الطبقة الثالثة · مسارات netlink وعناوينه، وICMP من مقبس الحزم

  • l3.route_added
  • l3.route_removed
  • l3.route_changed
  • l3.default_route_changed
  • l3.addr_added
  • l3.addr_removed
  • l3.icmp_unreachable
  • l3.mtu_blackhole

لا يُبلَّغ عن تغيّر إلا حين يتبدّل المسار الفائز فعلًا لوجهةٍ ما، فلا يُخلَط تركيبُ مسار احتياطي بانتقال حركة المرور إليه. والأخيران مصدرهما قراءة ICMP لا netlink: وl3.mtu_blackhole هو الجدير بالمعرفة منهما، لأن مسارًا يُسقط الحزم الكبيرة في صمت بينما تمرّ الصغيرة سالمةً هو العطل الذي يُشخَّص خطأً على أنه خلل في التطبيق أكثر من غيره.

flow.*

الطبقة الرابعة · eBPF على sock/inet_sock_set_state وtcp/tcp_receive_reset

  • flow.first_failure_for_pair
  • flow.handshake_fail
  • flow.reset
  • flow.timeout_no_close
  • flow.rollup

إشارة flow.first_failure_for_pair أقوى إشارةٍ مفردة في النظام. فاتصالٌ لا يُجاب عنه أمرٌ عادي بذاته — المنافذ المغلقة مغلقة. أما اتصالٌ لا يُجاب عنه بين جهازين كانا يتحادثان قبل لحظة فمعناه أن شيئًا تغيّر. والاتصالات الفردية ليست أحداثًا: القطاع المزدحم يفتح آلافًا منها في الثانية، فيُجمَّع كل ما هو عادي في flow.rollup كل عشر ثوانٍ، ولا يستحقّ سطرًا إلا الشاذّ. وثمّة tracepoint ثانٍ يفصل الاتصال المرفوض صراحةً عن الاتصال الذي كفّ عن الجواب فحسب، وهما عطلان مختلفان بعَرَضٍ واحد. ولذلك أيضًا لا وجود لـflow.open ولا flow.close عن قصد: فسطرٌ لكل اتصال لن يخبر المشغّل بشيء لا يخبره به عدّاد. أما flow.retransmit_spike فمُعلَن ولا يُنتَج بعد.

dhcp.* · dns.*

التسمية والعنونة · مقبس حزم مُرشَّح

  • dhcp.server_seen
  • dhcp.offer
  • dhcp.ack
  • dhcp.nak
  • dhcp.lease_changed
  • dns.resolver_changed
  • dns.query_fail
  • dns.latency_spike

بيانات وصفية لا محتوى، أبدًا: فمُرشِّح cBPF مربوط بالمقبس لا يأذن إلا لـICMP على IPv4 وUDP على ثلاثة منافذ، وما عدا ذلك لا يُنسَخ إلى فضاء المستخدم قط. وهو مكتوب تعليماتٍ في المستودع لا مُترجَمًا وقت التشغيل من نصّ tcpdump، لأن مُرشِّحًا يقرّر ما الذي تُسلَّمه العمليةُ أصلًا حدٌّ أمني، وحقُّه أن يكون قابلًا للمراجعة بوصفه كذلك. وحدث dhcp.server_seen — خادم DHCP ثانٍ يُجيب على قطاع — من أكثر الأحداث ترجيحًا لفتح حادثة، وهو أعسر الأعطال على الكشف اليدوي، لأن الأجهزة التي أخذت العقد الخطأ ليست هي الجهاز المسيء.

policy.*

قرارات الترشيح · nftables، باستطلاع دوري

  • policy.rule_changed

تُقرأ مجموعة القواعد كل خمس ثوانٍ وتُقارَن ببصمتها، فيقع تغيّرُ ما يسمح به جدار الحماية على الخط الزمني نفسه الذي تقع عليه عواقبه — وهذا ما يتيح لتغيير في الترشيح أن يظهر بوصفه الحلقة الأولى في سلسلة سببية. وكل قاعدة مُقيَّدة بالجدول والسلسلة اللذين يحتويانها، فيقرأ الدليل: table inet filter / chain input :: tcp dport 9300 drop — إذ إن مقارنة نصّ القاعدة مجرّدًا تجعل قاعدةً نُقلت بين سلسلتين بلا تغيير البتّة، وذاك بالضبط نوع التعديل الذي يكسر الشبكة في صمت. والغائب هنا عن قصد هو نتيجةُ تغيير الترشيح. فزوجٌ توقّف عن الاتصال أمرٌ يُرصَد أيًّا كان الحاجب — قاعدةٌ على هذا الجهاز، أو ACL على سويتش، أو جدار حماية على بُعد ثلاث قفزات — فمكانُ ذلك flow.first_failure_for_pair؛ ولو كان حدثًا هنا لما رأى إلا أوّل الثلاثة، وتلك أضيقُ الحالات في ثوب الحالة العامّة. أما policy.drop_burst فمُعلَن ويحتاج عدّادات لا تُقرأ بعد.

metric.*

سلاسل مقيسة · مجسّات نشطة

  • metric.anomaly

المُجمِّع الوحيد الذي يضع حزمةً على الشبكة. فكلُّ ما عداه هنا سلبيّ، وذاك يترك ثغرة: الفقدُ غيابٌ، ولا شيء يُعلن عن غياب. فتذهب حفنةُ مجسّات صغيرة في الدقيقة إلى أهدافٍ أُعطيها أو استخرجها من جدول التوجيه، ويُطلَق metric.anomaly حين تكفّ الأجوبة عن العودة أو تبدأ في التأخّر كثيرًا عمّا اعتادته — مقيسًا على خطّ أساس ذلك الهدف نفسه لا على عتبة ثابتة، لأن وصلةً جرت دائمًا على 40 مللي ثانية ليست في ضيق عند 40 مللي ثانية. أما عدّادات الواجهات وحجم جدول conntrack فموصوفة سلاسلَ ولا تُجمَع بعد.

change.*

تغييرات مقصودة · تغذية خارجية

  • change.config_applied
  • change.device_reboot
  • change.admin_action

العائلة الوحيدة التي لا تُرصَد، والوحيدة التي لا شيء يغذّيها. وستأتي من NetIntent، أو من مقارنة إعدادات الأجهزة عبر SSH أو SNMP. وهي العائلة التي تُمكّن الخط الزمني من الإجابة عن سؤال «ماذا كنّا نفعل حين انكسر»، وقاعدة change-broke-a-path تُطابِق عليها بالفعل — فيوم يغذّيها شيءٌ تتحسّن تلك القاعدة دون أن تُعدَّل.

system.*

المسجّل على نفسه · داخلي

  • system.gap
  • system.drop
  • system.clock_step
  • system.start
  • system.stop

لا تُزال هذه أبدًا. فـsystem.gap يُقاس على نبضة تُكتب كل عشر ثوانٍ ويقول بالضبط كم بقي المسجّل أعمى. وsystem.drop يقول كم حدثًا وجب إسقاطه حين وصل أسرع مما يمكن قراءته. والخمسة كلّها تُنتَج اليوم، ومن القواعد التسع عشرة المشحونة قاعدتان لا وجود لهما إلا لإظهارها: واحدة لثقبٍ في السِّجلّ، وأخرى لمُجمِّع واحد مات بينما بقيت البقيّة تعمل — وهذه أخطر الاثنتين، لأن الخط الزمني يظلّ يبدو سليمًا.

محرّك الإسناد

سُمّي على منهج الإسناد في علوم الحديث، حيث تُبنى سلسلةُ نقلٍ يُسمّى فيها كل راوٍ ويمكن التحقّق من كل حلقة. وذاك هو المعيار الذي يُحاسَب عليه المحرّك: يفرّق بين ما يُسبِّب وما يُقارِن وما يَسبِق فحسب، ولا يدّعي رابطًا سببيًّا لا يستطيع إبراز دليله.

الحوادث يُنتجها المحرّك لا المجمّعات. فالمجمّع يُبلّغ بما رأى، والمحرّك وحده هو المأذون له أن يقول ما الذي عناه.

مخرَج مسجَّل
incident_id, opened_at, closed_at, status
title, severity, confidence
root_cause { kind, entity_ref, confidence }
chain[] { seq, event_id, relation, why, evidence_ref }
victims[] host_id[]
rule_id
ما هي الحادثة

وصل العَرَض. فما الذي تغيّر قُبَيله؟

القاعدة تسلسلٌ مرتَّب من البنود، لا مجموعة. وأول بندٍ لازمٍ فيها هو مرساتها: الحدث الذي يدفع المحرّك إلى تقييم القاعدة من الأساس.

والبنود التي بعد المرساة تُطابَق إلى الأمام في الزمن، والتي قبلها تُطابَق إلى الوراء، الأقربُ فالأقرب. وهذا التفاوت وحده هو ما يتيح للقاعدة أن تطرح السؤال الذي وُجد هذا المشروع من أجله.

ذلك أن العَرَض هو الواصل — زوجٌ توقّف عن الاتصال، أو مسارٌ اختفى — والسؤال النافع ليس أبدًا ما الذي تلاه، بل ما الذي تغيّر قُبَيله.

مخرَج مسجَّل
match:
- as: change # اختياري، ويُبحث عنه إلى الوراء
kinds: [l2.arp_binding_changed, l3.route_changed, link.down]
optional: true
why: هذا آخر ما تغيّر على المسار قبل أن ينقطع.
 
- as: breakage # لازم — وهو المرساة
kinds: [flow.first_failure_for_pair]
relation: causes
why: جهازان كانا يتصلان لم يعودا يُتِمّان المصافحة.
rules/change-broke-a-path.yaml

وإن لم يكن داخل النافذة تغيّرٌ سابق، أطلقت القاعدة مع ذلك، بسلسلةٍ من حلقة واحدة: يقف العَرَض وحده بدل أن يُعلَّق على تخمين.

واختيار أقرب تغيّر مقصود. فالأبعد منه تخمينٌ أسوأ يلبس الدعوى نفسها — ولهذا بالذات وجب على قاعدةٍ بُنيت هكذا أن تقول في نصيحتها إن التغيّر المُسمّى هو الأقرب زمنًا، لا سببًا مثبتًا.

مفاتيح الربط تُبقي الأعطال غير المترابطة متفرّقة

يُسمّي correlate_on حقولًا يجب أن تتّفق عليها كل الأحداث المطابِقة. وبدونه يُنسَج عطلان وقعا في اللحظة نفسها على جهازين مختلفين في حادثةٍ واحدة لم تقع قط. ومع correlate_on: [subject] لا يمكن أن يُوصَل منفذٌ يرتجف على سويتش بجارٍ يسقط على سويتش آخر.

الثقة حدٌّ أعلى لا درجة

الرقم في القاعدة هو مبلغ ثقة كاتبها باستنتاجه. ثم يخفضه المحرّك إلى أقلّ أحداث السلسلة يقينًا. فالحادثة القائمة على استنتاج لا يمكن أن تكون أوثق من الاستنتاج نفسه.

الحادثة تنمو ولا تتكرّر

إذا وصل بندٌ اختياري بعد أن أطلقت القاعدة، حلّت الروايةُ الأوفى محلّ الأنقص بدل أن تظهر إلى جانبها شبيهةً بها. حادثةٌ واحدة، مرويّةٌ على وجه أحسن.

النتيجة لا تسبق سببها

البنود تسلسل. يبحث المحرّك عن الأول، ثم عن الثاني بعده، وكلّ ذلك داخل النافذة. وسلسلةٌ تُقرأ إلى الوراء ليست الشكل الذي تصفه القاعدة، ولن يتظاهر المحرّك بغير ذلك.

الإشارة التي تتعلّق بها السلسلة

flow.first_failure_for_pair

جهازان كانا يتصلان قبل لحظة لم يعودا قادرين

هذه أقوى إشارة مفردة في النظام، وهي سبب وجود ما تتعلّق به السلسلة السببية أعلاه.

اتصالٌ لا يُجاب عليه وحده أمر عاديّ: المنافذ المغلقة مغلقة. أما اتصال لا يُجاب عليه بين جهازين كانا يتحادثان قبل قليل فيعني أن شيئًا تغيّر — قاعدة ترشيح، أو ACL، أو مسار، أو خدمة.

عاديّ
محاولة اتصال تفشل بجهاز لم يُتصل به من قبل. لا شيء يُستنتج منها.
دليل
محاولة اتصال تفشل بجهاز نجح الاتصال به قبل دقائق. هنا تغيّر شيء بينهما.
  • الزوج هو (المصدر، الوجهة، منفذ الوجهة) — ومنفذ المصدر العابر ليس جزءًا من العلاقة.
  • يُحفظ النجاح أربعًا وعشرين ساعة، لأن خدمةً آخر عهدها بالعمل قبل شهر ليست دليلًا على أن شيئًا تغيّر للتوّ.
  • يُبلَّغ عن الانقطاع مرة واحدة، ويُعاد التسليح فور نجاح الزوج ثانيةً، فالعطل الذي يتكرّر بعد تعافٍ يُبلَّغ عنه من جديد لا يُبتلع.

قيد معلوم. ذاكرة الأزواج التي نجحت داخل العملية نفسها. بعد إعادة تشغيل المسجّل لا يملك خطَّ أساس، فيُبلِّغ عن handshake_fail عاديّ حتى يرى زوجًا ينجح مرة أخرى.

الانضباط

الفرق بين ادّعاء السبب وملاحظة التزامن

العمود الأوسط في السلسلة أعلاه ليس زخرفة. «الذي سبّب» ادّعاء عن آلية؛ و«وفي الوقت نفسه» تزامنٌ لا أكثر — والمحرّك يقول لك بذلك إنه لا يعرف.

أداة تخلط بين الاثنين تُعلّم مشغّلها ألّا يثق بها، والمشغّل الذي لا يثق بالخط الزمني يعود إلى التخمين.

causes
which caused
ادّعاء عن آلية: هذا أدّى إلى ذاك. لا تُطبع إلا حين تصف القاعدة سببًا معروفًا، لا مجرد تجاور في الزمن.
correlates
and at the same time
وقعا معًا. لا ادّعاء أبعد من ذلك. هذا هو المحرّك وهو يقول صراحةً إنه لا يعرف، بدل أن يخمّن نيابةً عنك.
precedes
and then, without a known link
ترتيب زمني فحسب. أضعف ما يمكن قوله، ويُقال حين لا يصحّ ما هو أقوى منه.

ولا يمكن لحادثة أن تكون أوثق من المشاهدات التي تقوم عليها: تُخفَّض ثقة القاعدة لتطابق ثقة الأحداث التي طابقتها.

الطريق الذي يسلكه الرصد

تُنمّط المجمّعاتُ ما رأته في الظرف المشترك. ثم يُلحق حسمُ الهويّة بالحدث host_id ثابتًا. ويحفظه المخزن طاويًا تكراراته. ثم يقرؤه محرّك الترابط فيُنتج حوادث بسلسلة سببية صريحة.

وكل مرحلة لا تملك إلا أن تُضعف الدعوى، لا أن تقوّيها — ولهذا تنحدر الثقة عبر المسار ولا ترتفع فيه أبدًا.

الطريق الذي يسلكه الرصدتُغذّي المصادرُ في الأعلى مجمّعاتِ الأحداث، فتُنمّط ما رأته في الظرف المشترك. ثم يُلحق حسمُ الهويّة مُعرّفَ مضيفٍ ثابتًا. ويحفظ المخزنُ الحدث. ثم يقرؤه محرّك الإسناد للترابط فيُنتج حوادث بسلسلة سببية صريحة، يعرضها سطرُ الأوامر وواجهةُ الويب ومُصدِّرا المقاييس.netlink · eBPF · nftables · مقبس حزم · مجسّات · IP Helperمجمّعات الأحداثinternal/collectالظرف المشتركinternal/eventحسم الهويّةinternal/identityمخزن الأحداثinternal/storeمحرّك الإسناد للترابطinternal/correlateحوادث بسلسلة سببية صريحةinternal/incidentCLIويبPrometheus / OTLP

ثلاثة مخارج من المخزن الواحد: سطر الأوامر، وواجهة ويب للقراءة فقط تُولَّد على الخادم وتُربط بالعنوان المحلي (netrewind serve)، وتصدير إلى Prometheus وOpenTelemetry.