وثائق بوابة القرار

تقييم بوابة حتمي وقابل لإعادة التشغيل مع قرارات قابلة للتدقيق.

وثائق Asset Core

دليل تطوير المزود

نظرة سريعة

ما: بناء مزودي أدلة مخصصين لبوابة القرار لماذا: توسيع مصادر الأدلة دون تعديل النواة من: مطورو المزودين، مهندسو التكامل المتطلبات المسبقة: provider_protocol.md، JSON-RPC 2.0


بنية المزود

مزود هو خادم MCP يقوم بتنفيذ أداة واحدة: evidence_query.

Provider
  - Provider Contract (JSON)
    - provider_id, name, description
    - transport = "mcp"
    - config_schema
    - checks (params schema, result schema, comparators, examples)
    - notes
  - MCP Server
    - tools/call -> evidence_query

Decision Gate
  - Loads contract from capabilities_path
  - Validates ScenarioSpec conditions against contract
  - Calls evidence_query during scenario_next

قرار بوابة القرار لا يستخدم tools/list أثناء التشغيل. قم بتنفيذه من أجل توافق MCP، ولكن احتفظ بملف العقد كمرجع موثوق.


أنواع المزودين

النوعالإعداداتالنقلحالة الاستخدام
مدمجtype = "builtin"داخل العمليةtime, env, json, http
MCP خارجيtype = "mcp"stdio أو HTTPمزودون مخصصون

يتم تكوين مزودي MCP الخارجيين مع إما:

  • command = ["/path/to/provider", "arg"] (stdio)
  • url = "https://provider/rpc" (HTTP)

capabilities_path مطلوب لجميع مزودي MCP. يجب أن تكون أسماء المزودين فريدة؛ المعرفات المدمجة (time, env, json, http) محجوزة لـ type = "builtin" فقط.


بدء سريع: مزود الحد الأدنى

الخطوة 1: استخدم قالب SDK

تعيش القوالب في decision-gate-provider-sdk/ (بايثون، TypeScript، Go). إنها تنفذ:

  • إطار طول المحتوى (stdio)
  • tools/list و tools/call
  • تحليل JSON-RPC

الخطوة 2: تنفيذ evidence_query

يجب على المعالج الخاص بك إرجاع كائن EvidenceResult (ليس خطأ JSON-RPC) للفشل العادي.

مثال (كود زائف):

def handle_evidence_query(query, context):
    if query["check_id"] != "file_exists":
        return {
            "value": None,
            "lane": "verified",
            "error": {
                "code": "unsupported_check",
                "message": "unknown check",
                "details": {"check_id": query["check_id"]}
            },
            "evidence_hash": None,
            "evidence_ref": None,
            "evidence_anchor": None,
            "signature": None,
            "content_type": None
        }

    rel_path = query.get("params", {}).get("path")
    if not rel_path:
        return {
            "value": None,
            "lane": "verified",
            "error": {
                "code": "params_missing",
                "message": "missing path",
                "details": {"param": "path"}
            },
            "evidence_hash": None,
            "evidence_ref": None,
            "evidence_anchor": None,
            "signature": None,
            "content_type": None
        }

    root = CONFIG["root"]
    root_id = CONFIG["root_id"]
    abs_path = os.path.normpath(os.path.join(root, rel_path))
    exists = os.path.exists(abs_path)
    return {
        "value": {"kind": "json", "value": exists},
        "lane": "verified",
        "error": None,
        "evidence_hash": None,
        "evidence_ref": {"uri": f"dg+file://{root_id}/{rel_path}"},
        "evidence_anchor": {
            "anchor_type": "file_path_rooted",
            "anchor_value": json.dumps({"root_id": root_id, "path": rel_path}, separators=(",", ":"), sort_keys=True)
        },
        "signature": None,
        "content_type": "application/json"
    }

الخطوة 3: إنشاء عقد مزود الخدمة

جميع الحقول أدناه مطلوبة بموجب مخطط العقد.

{
  "provider_id": "file-provider",
  "name": "File Provider",
  "description": "File existence checks",
  "transport": "mcp",
  "config_schema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {}
  },
  "checks": [
    {
      "check_id": "file_exists",
      "description": "Check if a file exists",
      "determinism": "external",
      "params_required": true,
      "params_schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": { "path": { "type": "string" } },
        "required": ["path"]
      },
      "result_schema": { "type": "boolean" },
      "allowed_comparators": ["equals", "not_equals"],
      "anchor_types": ["file_path_rooted"],
      "content_types": ["application/json"],
      "examples": [
        {
          "description": "Check a report file",
          "params": { "path": "report.json" },
          "result": true
        }
      ]
    }
  ],
  "notes": [
    "External: depends on the local filesystem state."
  ]
}

قواعد العقد المهمة:

  • allowed_comparators يجب أن تكون غير فارغة وفي ترتيب قياسي.
  • params_required يجب أن يتطابق مع ما إذا كان params_schema يتطلب حقولًا.
  • transport يجب أن يكون "mcp" لمقدمي الخدمات الخارجيين.

الخطوة 4: تكوين بوابة القرار

[[providers]]
name = "file-provider"
type = "mcp"
command = ["python3", "/path/to/provider.py"]
capabilities_path = "contracts/file-provider.json"

مهلات

تطبق بوابة القرار فقط مهلات HTTP على مزودي HTTP MCP:

[[providers]]
name = "cloud"
type = "mcp"
url = "https://provider.example.com/rpc"
capabilities_path = "contracts/cloud.json"
timeouts = { connect_timeout_ms = 2000, request_timeout_ms = 10000 }

لا يوجد وقت انتهاء لبوابة القرار لمزودي MCP من نوع stdio؛ حافظ على سرعة محدداتهم وموثوقيتها.


دليل التوقيع

عندما trust.default_policy = { require_signature = { keys = [...] } }، يجب على المزودين تضمين التوقيعات:

"signature": {
  "scheme": "ed25519",
  "key_id": "/etc/decision-gate/keys/provider.pub",
  "signature": [1, 2, 3, 4]
}

خوارزمية التوقيع (بالضبط):

  1. Compute evidence_hash from the evidence value.
    • قيمة JSON -> بايتات JSON القياسية -> sha256
    • قيمة البايت -> sha256
  2. قم بتسلسل كائن HashDigest كـ JSON قياسي.
  3. قم بتوقيع تلك البايتات باستخدام Ed25519.

تتحقق بوابة القرار من التوقيع مقابل ملف المفتاح العام المكون. إذا كان evidence_hash مفقودًا، تقوم DG بحسابه قبل التحقق. إذا كان evidence_hash موجودًا، يجب أن يتطابق مع التجزئة القياسية لقيمة الدليل أو يتم رفض الاستجابة.


معالجة الأخطاء

  • ارجع EvidenceResult.error للأخطاء المتوقعة.
  • استخدم أخطاء JSON-RPC فقط لفشل البروتوكول (JSON-RPC غير صالح، أعطال داخلية). يقوم DG بتحويل أخطاء JSON-RPC إلى provider_error.

أكواد الخطأ محددة من قبل المزود. يجب أن تبقى مستقرة وقابلة للقراءة من قبل الآلات (على سبيل المثال، params_missing, file_not_found).


مرجع

  • مخطط عقد المزود: crates/decision-gate-contract/src/schemas.rs (provider_contract_schema)
  • عقود مزودي الخدمة المدمجة: providers.json
  • قوالب SDK: decision-gate-provider-sdk/

معجم

EvidenceQuery: طلب { provider_id, check_id, params }. EvidenceResult: قيمة استجابة المزود + البيانات الوصفية. Provider Contract: وثيقة JSON تصف الفحوصات، المخططات، المقارنات، والأمثلة. Signature: توقيع Ed25519 على JSON القياسي لـ evidence_hash.