תיעוד

מולטי-טננט קפדני

כיצד betool מבודדת את הנתונים, הסודות וההרצות שלכם מארגונים אחרים: בסיס הנתונים, הקבצים, המטמונים וההרצה.

הבידוד בין ארגונים הוא האינווריאנט המבני של betool. כך הוא מיושם — שכבה אחר שכבה.

ברמת מסד הנתונים

טבלאות העסק נושאות עמודת org_id המשייכת כל שורה לארגון שלה (על פי רוב עם אילוץ מפתח זר אל organisation(id)).

כל שאילתות השרת עוברות דרך store methods המסננות באופן שיטתי לפי org_id של הסשן הפעיל. אין נתיב שחושף שאילתה שרירותית; אף לקוח אינו יכול לכפות org_id אחר.

עבור משאבים נדירים הניתנים לשיתוף (בדרך כלל חשבונות LLM משותפים ברמת הפלטפורמה), עמודת is_shared BOOLEAN NOT NULL DEFAULT FALSE מאפשרת opt-in מפורש. כללים:

  • כל קריאה מותרת עם WHERE org_id = %s OR is_shared = TRUE.
  • כל מוטציה של שורת is_shared = TRUE מחייבת תפקיד hyperadmin (מפעיל פלטפורמה).
  • כל מוטציה מבטלת את הקאש גלובלית — אין סטייה per-org.

ברמת אחסון הקבצים

הקבצים מאוחסנים באחסון אובייקטים (דיסק מקומי או bucket בענן, בהתאם לפריסה), תחת מרחב ייעודי לכל ארגון:

orgs/
└── <org_id>/
    ├── files/<channel>/<exchange_id>/<file>    ← קבצים שהתקבלו דרך הערוצים
    └── fixtures/                               ← fixtures של benchmark

המפתחות נבנים בצד השרת (שם קובץ מנוקה, הגנה מפני path-traversal). כל קריאה של קובץ בשם משתמש, tool או סוכן עוברת אימות שדוחה מפתח שנמצא מחוץ למרחב orgs/<org_id>/files/ של הארגון הנוכחי.

ברמת הקאש

הקאשים האפליקטיביים (למשל פתרון ה-providers של LLM) ממופתחים לפי ארגון. כאשר משאב is_shared = TRUE מתעדכן, הקאש מתבטל גלובלית — אין חלון שבו ארגון יראה ערך ישן.

ברמת הסודות

ה-credentials (מפתחות LLM, טוקני auth של מפעיל, סודות webhook) מאוחסנים בצד השרת, משויכים לכל ארגון. הם לעולם אינם מוחזרים בטקסט גלוי על ידי ה-API: נתיבי GET מציינים רק את קיומם (למשל has_api_key: bool).

ברמת ההרצה

כאשר pipeline מתבצע:

  • למפעילים יש גישה רק לחשבונות החיצוניים שהוגדרו בארגון.
  • מודלי ה-LLM שבשימוש נפתרים בסדר own > shared (fallback auto) — תמיד.
  • קבצים מצורפים קריאים רק במרחב האחסון של הארגון הנוכחי.

אם מפעיל מנסה לגשת למשאב מחוץ לפרימטר, הגישה נדחית עם שגיאה מפורשת — לא timeout שקט.

מבחן מעשי

בכל הוספת משאב ניתן-לשיתוף חדש, הצוות עונה על 4 שאלות:

  1. אם יופיע ארגון backoffice שני, האם הקוד שלי מתנהג כראוי?
  2. אם אשנה שורת shared, האם כל הקאשים per-org יתבטלו?
  3. האם הסודות שלי נשארים בקפדנות server-side?
  4. האם ה-GET שלי מאפשר ל-pickers של ארגונים אחרים לרשום את המשאב, מבלי לחשוף את הסוד?

אם תשובה אחת היא לא — המשאב אינו נמסר.