הבידוד בין ארגונים הוא האינווריאנט המבני של 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 שאלות:
- אם יופיע ארגון backoffice שני, האם הקוד שלי מתנהג כראוי?
- אם אשנה שורת shared, האם כל הקאשים per-org יתבטלו?
- האם הסודות שלי נשארים בקפדנות server-side?
- האם ה-GET שלי מאפשר ל-pickers של ארגונים אחרים לרשום את המשאב, מבלי לחשוף את הסוד?
אם תשובה אחת היא לא — המשאב אינו נמסר.