تكامل عميل AeroNyx Chat Relay

AeroNyx19 يونيو 20264 دقيقة قراءة34 مشاهدة

عقد العميل لـ blind relay وpresence بين جهات الاتصال المتبادلة وread receipts المتكافئة وreactions المشفرة وoffline queue والوسائط القابلة للاستئناف.

العقد الرسمي للـ frames وmedia API لفرق App وfrontend وbackend ووكلاء البرمجة الذين ينشئون عميل AeroNyx. يقوم relay بتوجيه ciphertext فقط ولا يفسر المحتوى.

ثابت الخصوصية غير القابل للتفاوض

لا يجوز لـ relay تحليل أو تخزين أو استنتاج chat/reaction plaintext أو voice/media أو keys أو nonces أو waveform أو filenames أو transcripts أو MemChain أو packet payload أو DNS أو destinations أو URLs أو history أو wallet traffic أو private seeds. ينفذ client تشفير E2E قبل النقل.

يوجد E2E content في payload_b64 وpayload_sig. تقتصر visible metadata على type وIDs وreceiver/group وtimestamps وdelivery state وblob size/expiry وaccess mode وcounters.

ثابت خصوصية حالة الاتصال

لا يظهر online وlast seen إلا إذا كان P2PContact فعالاً في الاتجاهين. يتحقق backend من الطرفين لمنع scan للمفاتيح العامة. ويمكن تعطيل presence وlast seen الدقيق كل على حدة.

لا يتضمن hidden result online أو last_seen_ts؛ reason هو not_mutual_contact أو presence_hidden.

واجهة خصوصية الملف الشخصي

يقرأ client profile privacy flags بعد الاتصال ويجعل UI متوافقاً مع backend enforcement. يقبل PATCH كائن privacy والحقول top-level القديمة.

http
GET /api/relay/profile/
PATCH /api/relay/profile/
Authorization: Relay <pubkey>:<timestamp>:<signature>
json
{
  "privacy": {
    "presence_enabled": true,
    "last_seen_enabled": false,
    "read_receipts_enabled": false
  }
}

إطارات حالة الاتصال

أرسل presence_subscribe لجهات الاتصال فقط. عند last_seen_enabled=false اعرض حالة تقريبية أو أخف الوقت، ولا تستنتج وقتاً دقيقاً من إشارات أخرى.

json
{
  "type": "presence_subscribe",
  "pubkeys": ["contact-pubkey-a", "contact-pubkey-b"]
}
json
{
  "type": "presence_subscribe_ack",
  "updates": [{
    "pubkey": "contact-pubkey-a",
    "visible": true,
    "presence_visible": true,
    "last_seen_visible": true,
    "online": true,
    "last_seen_ts": 1780000000,
    "reason": "allowed"
  }],
  "server_ts": 1780000001
}

قاعدة إيصالات القراءة المتبادلة

Read receipts متبادلة: من يعطلها لا يرسل message_read ولا يعرض peer read. إذا عطلها أحد الطرفين أو لم توجد mutual contact يقوم backend بـ suppress للـ frame. وهي metadata فقط.

json
{
  "type": "message_read",
  "msg_id": "message-id",
  "receiver_pubkey": "original-sender-pubkey",
  "timestamp": 1780000200
}
json
{
  "type": "message_read_ack",
  "msg_id": "message-id",
  "delivered": false,
  "suppressed": true,
  "reason": "receiver_read_receipts_disabled"
}

Reasons: client_disabled, not_mutual_contact, reader_read_receipts_disabled, receiver_read_receipts_disabled؛ نفس gate في offline pull.

تفاعلات الرموز التعبيرية

Reaction هي أيضاً E2E ciphertext. يوجهها relay حسب receiver أو membership ويزيل التكرار عبر reaction_id ويستخدم store-and-forward عند offline. يحتفظ client بالحالة المجمعة.

json
{
  "type": "message_reaction",
  "msg_id": "target-message-id",
  "receiver_pubkey": "peer-pubkey",
  "reaction_id": "unique-reaction-event-id",
  "timestamp": 1780000300,
  "payload_b64": "e2e-ciphertext",
  "payload_sig": "ed25519-signature"
}

Discriminant هو 12؛ reaction_id مفتاح idempotency/offline ACK. ACK هو message_reaction_ack؛ group يستخدم group_message_reaction وgroup_id وkey_version.

نموذج كائن الوسائط المشفر

تُشفّر voice وimages وvideo وfiles قبل upload. يبقى blob_id وkey وnonce وduration وwaveform وdisplay filename وpreview metadata داخل relay_send.payload_b64، لا كحقول واضحة في blob API.

json
{
  "kind": "voice",
  "blob_id": "blob-uuid",
  "key_b64": "inside-e2e-envelope",
  "nonce_b64": "inside-e2e-envelope",
  "duration_ms": 43000,
  "waveform": [0, 3, 8, 6, 2],
  "media_type": "audio/ogg; codecs=opus",
  "file_size": 7340032
}

رفع بسيط لكائن مشفر

استخدم multipart للرسائل الصوتية القصيرة والصور الصغيرة. يقبل server encrypted bytes فقط؛ TTL افتراضي 7 أيام وسياسة 1–30. Download عبر capability غير قابل للتخمين أو authenticated P2P key.

http
POST /api/relay/blob/
Authorization: Relay <pubkey>:<timestamp>:<signature>
Content-Type: multipart/form-data
fieldrequiredvalue
filetrueciphertext
media_kindfalsevoice, image, video, file, avatar, other
media_typefalseMIME
ttl_daysfalse1..30
access_modefalsecapability, authenticated
allowed_downloadersfalseJSON P2P pubkey array

Simple limit هو 10 MB؛ التجاوز يعيد HTTP 413 وerror_code=blob_too_large وchunked_max_bytes=104857600.

رفع قابل للاستئناف لكائن مشفر

بعد simple limit استخدم chunk session. الحد الإجمالي للـ ciphertext هو 100 MB ويمكن إعادة نفس chunk index بأمان. خزّن upload_id وchunk_size وcompleted indexes محلياً.

1. إنشاء جلسة رفع

http
POST /api/relay/blob/session/
Authorization: Relay <pubkey>:<timestamp>:<signature>
Content-Type: application/json
json
{
  "total_size": 7340032,
  "chunk_size": 1048576,
  "media_type": "audio/ogg",
  "media_kind": "voice",
  "ttl_days": 7,
  "access_mode": "authenticated",
  "allowed_downloaders": ["receiver-pubkey"]
}

2. رفع الأجزاء

http
PUT /api/relay/blob/session/{upload_id}/chunk/{chunk_index}/
Authorization: Relay <pubkey>:<timestamp>:<signature>
Content-Type: application/octet-stream

Default chunk هو 1 MB والحد 4 MB؛ retry لنفس index يستبدل القديم وهو idempotent.

3. الاستئناف بعد انقطاع الشبكة

http
GET /api/relay/blob/session/{upload_id}/
Authorization: Relay <pubkey>:<timestamp>:<signature>

اقرأ missing_chunks وأرسل الفهارس الناقصة فقط. Session صالحة 24 ساعة.

4. إكمال الرفع

http
POST /api/relay/blob/session/{upload_id}/complete/
Authorization: Relay <pubkey>:<timestamp>:<signature>

Complete يتحقق من chunks وtotal bytes؛ safe retry يعيد final blob الموجود بلا duplicate.

5. إلغاء الرفع

http
DELETE /api/relay/blob/session/{upload_id}/
Authorization: Relay <pubkey>:<timestamp>:<signature>

تنزيل الكائن المشفر

Capability لا يحتاج RelayAuth لأن UUID هو bearer capability. Authenticated يحتاج توقيعاً ويسمح لـ uploader أو allowed_downloaders. يُحذف expired blob عند الوصول إليه.

http
GET /api/relay/blob/{blob_id}/
HTTPerror_code
400blob_id_invalid
401auth_required
403download_forbidden
404blob_not_found
410blob_expired
413blob_too_large, blob_total_size_too_large, chunk_too_large
409upload_incomplete

إرشادات تجربة العميل

استخدم simple upload للملفات الصغيرة وchunks بعد max_bytes. بعد restart اقرأ missing_chunks. اترك secrets داخل E2E وحوّل 410 blob_expired إلى إجراء resend.

ترتيب تكامل وكيل الذكاء الاصطناعي

يطبق agent بالتسلسل RelayAuth وprofile privacy وpresence UI وreciprocal read receipts وreaction idempotency وsimple blob وchunk resume ثم reference داخل relay_send. لا ينشئ server-side chat search.

تسليم موثق عبر قفزتين

يمكن لـ ChatRelay المؤهل اختيار network-diverse two-hop path. لا يحسب source التسليم إلا بعد تحقق signed receipt من terminal المتوقع؛ middle node يوجه ciphertext فقط.

اكتشاف العقد والتسليم المشفر القابل للتحقق