Plugin SDK والبيئة المعزولة
تتيح لك إضافات Triggerfish توسيع الوكيل بكود مخصص يتفاعل مع أنظمة خارجية -- استعلامات CRM، عمليات قواعد البيانات، تكاملات API، سير عمل متعدد الخطوات -- أثناء التشغيل داخل بيئة معزولة مزدوجة تمنع الكود من فعل أي شيء لم يُسمح له به صراحةً.
بيئة التشغيل
تعمل الإضافات على Deno + Pyodide (WASM). لا Docker. لا حاويات. لا متطلبات مسبقة سوى تثبيت Triggerfish نفسه.
- إضافات TypeScript تعمل مباشرة في بيئة Deno المعزولة
- إضافات Python تعمل داخل Pyodide (مفسّر Python مُجمّع إلى WebAssembly)، والذي يعمل بدوره داخل بيئة Deno المعزولة
هذه البنية المعزولة المزدوجة تعني أنه حتى لو احتوت إضافة على كود خبيث، لا يمكنها الوصول إلى نظام الملفات أو إجراء استدعاءات شبكة غير مُعلنة أو الهروب إلى نظام المضيف.
ما يمكن للإضافات فعله
الإضافات لديها مرونة داخلية ضمن حدود صارمة. داخل البيئة المعزولة، يمكن لإضافتك:
- تنفيذ عمليات CRUD كاملة على الأنظمة المستهدفة (باستخدام أذونات المستخدم)
- تنفيذ استعلامات معقدة وتحويلات بيانات
- تنسيق سير عمل متعدد الخطوات
- معالجة وتحليل البيانات
- الحفاظ على حالة الإضافة عبر الاستدعاءات
- استدعاء أي نقطة نهاية API خارجية مُعلنة
ما لا يمكن للإضافات فعله
| القيد | كيف يُطبّق |
|---|---|
| الوصول لنقاط نهاية شبكة غير مُعلنة | البيئة المعزولة تحظر جميع استدعاءات الشبكة غير المدرجة |
| إخراج بيانات بدون تسمية تصنيف | SDK يرفض البيانات غير المصنّفة |
| قراءة بيانات بدون نشر التلوث | SDK يلوّث الجلسة تلقائياً عند الوصول للبيانات |
| حفظ بيانات خارج Triggerfish | لا وصول لنظام الملفات من داخل البيئة المعزولة |
| التسريب عبر قنوات جانبية | حدود الموارد مفروضة، لا وصول للمقابس الخام |
| استخدام بيانات اعتماد النظام | SDK يحظر get_system_credential()؛ بيانات اعتماد المستخدم فقط |
أمان sdk.get_system_credential() محظورة بالتصميم.
يجب على الإضافات دائماً استخدام بيانات اعتماد المستخدم المُفوّضة عبر sdk.get_user_credential(). هذا يضمن أن الوكيل يمكنه فقط الوصول إلى ما يمكن للمستخدم الوصول إليه -- لا أكثر أبداً. :::
طرق Plugin SDK
يوفر SDK واجهة محكومة للإضافات للتفاعل مع الأنظمة الخارجية ومنصة Triggerfish.
الوصول لبيانات الاعتماد
typescript
// الحصول على بيانات اعتماد المستخدم المُفوّضة لخدمة
const credential = await sdk.get_user_credential("salesforce");
// التحقق مما إذا كان المستخدم قد وصل خدمة
const connected = await sdk.has_user_connection("notion");sdk.get_user_credential(service) يسترجع رمز OAuth أو مفتاح API للمستخدم للخدمة المُسمّاة. إذا لم يكن المستخدم قد وصل الخدمة، يُعيد الاستدعاء null ويجب على الإضافة التعامل مع هذا بأناقة.
عمليات البيانات
typescript
// استعلام نظام خارجي باستخدام أذونات المستخدم
const results = await sdk.query_as_user("salesforce", {
query: "SELECT Name, Amount FROM Opportunity WHERE StageName = 'Closed Won'",
});
// إخراج البيانات إلى الوكيل — تسمية التصنيف مطلوبة
sdk.emitData({
classification: "CONFIDENTIAL",
payload: results,
source: "salesforce",
});كل استدعاء لـ sdk.emitData() يتطلب تسمية classification. إذا
حذفتها، يرفض SDK الاستدعاء. هذا يضمن تصنيف جميع البيانات المتدفقة من الإضافات إلى سياق الوكيل بشكل صحيح. :::
فحص الاتصال
typescript
// التحقق مما إذا كان المستخدم لديه اتصال مباشر بخدمة
if (await sdk.has_user_connection("github")) {
const repos = await sdk.query_as_user("github", {
endpoint: "/user/repos",
});
sdk.emitData({
classification: "INTERNAL",
payload: repos,
source: "github",
});
}دورة حياة الإضافة
كل إضافة تتبع دورة حياة تضمن مراجعة أمنية قبل التفعيل.
1. إنشاء الإضافة (من قبل المستخدم أو الوكيل أو جهة خارجية)
|
v
2. بناء الإضافة باستخدام Plugin SDK
- يجب تنفيذ الواجهات المطلوبة
- يجب إعلان نقاط النهاية والقدرات
- يجب اجتياز التحقق
|
v
3. الإضافة تدخل حالة UNTRUSTED
- الوكيل لا يمكنه استخدامها
- المالك/المسؤول يُخطر: "في انتظار التصنيف"
|
v
4. المالك (شخصي) أو المسؤول (مؤسسي) يراجع:
- ما البيانات التي تصل إليها هذه الإضافة؟
- ما الإجراءات التي يمكنها اتخاذها؟
- تعيين مستوى التصنيف
|
v
5. الإضافة نشطة بالتصنيف المُعيّن
- الوكيل يمكنه الاستدعاء ضمن قيود السياسة
- جميع الاستدعاءات تمر عبر خطافات السياسةفي المستوى الشخصي، أنت المالك -- تراجع وتصنّف
إضافاتك بنفسك. في المستوى المؤسسي، يدير مسؤول سجل الإضافات ويعيّن مستويات التصنيف. :::
الاتصال بقواعد البيانات
برامج التشغيل الأصلية لقواعد البيانات (psycopg2، mysqlclient، إلخ) لا تعمل داخل البيئة المعزولة WASM. تتصل الإضافات بقواعد البيانات عبر واجهات API المبنية على HTTP بدلاً من ذلك.
| قاعدة البيانات | خيار HTTP |
|---|---|
| PostgreSQL | PostgREST، Supabase SDK، Neon API |
| MySQL | PlanetScale API |
| MongoDB | Atlas Data API |
| Snowflake | REST API |
| BigQuery | REST API |
| DynamoDB | AWS SDK (HTTP) |
هذه ميزة أمنية، وليست قيداً. جميع الوصول لقواعد البيانات يتدفق عبر طلبات HTTP قابلة للفحص والتحكم يمكن للبيئة المعزولة فرضها ولنظام التدقيق تسجيلها.
كتابة إضافة TypeScript
إضافة TypeScript بسيطة تستعلم واجهة REST API:
typescript
import type { PluginResult, PluginSdk } from "triggerfish/plugin";
export async function execute(sdk: PluginSdk): Promise<PluginResult> {
// التحقق مما إذا كان المستخدم قد وصل الخدمة
if (!await sdk.has_user_connection("acme-api")) {
return {
success: false,
error: "User has not connected Acme API. Please connect it first.",
};
}
// الاستعلام باستخدام بيانات اعتماد المستخدم
const data = await sdk.query_as_user("acme-api", {
endpoint: "/api/v1/tasks",
method: "GET",
});
// إخراج بيانات مصنّفة إلى الوكيل
sdk.emitData({
classification: "INTERNAL",
payload: data,
source: "acme-api",
});
return { success: true };
}كتابة إضافة Python
إضافة Python بسيطة:
python
async def execute(sdk):
# التحقق من الاتصال
if not await sdk.has_user_connection("analytics-db"):
return {"success": False, "error": "Analytics DB not connected"}
# الاستعلام باستخدام بيانات اعتماد المستخدم
results = await sdk.query_as_user("analytics-db", {
"endpoint": "/rest/v1/metrics",
"method": "GET",
"params": {"period": "7d"}
})
# الإخراج مع التصنيف
sdk.emit_data({
"classification": "CONFIDENTIAL",
"payload": results,
"source": "analytics-db"
})
return {"success": True}تعمل إضافات Python داخل بيئة Pyodide WASM. وحدات المكتبة القياسية متاحة، لكن امتدادات C الأصلية ليست كذلك. استخدم واجهات API المبنية على HTTP للاتصال الخارجي.
ملخص أمان الإضافات
- تعمل الإضافات في بيئة معزولة مزدوجة (Deno + WASM) مع عزل صارم
- جميع الوصول للشبكة يجب إعلانه في بيان الإضافة
- جميع البيانات المُخرجة يجب أن تحمل تسمية تصنيف
- بيانات اعتماد النظام محظورة -- فقط بيانات اعتماد المستخدم المُفوّضة متاحة
- كل إضافة تدخل النظام كـ
UNTRUSTEDويجب تصنيفها قبل الاستخدام - جميع استدعاءات الإضافات تمر عبر خطافات السياسة ويتم تدقيقها بالكامل
