חוזה אירועים קנוני בין Local Engine ל-Base44
1. מטרת המסמך
מסמך זה מגדיר חוזה אירועים קנוני, versioned ו-idempotent לתקשורת בין InvestIQ Local Engine לבין Base44. הוא נגזר ישירות מ-Local Engine Pilot Specification v0.31 המאושר, ואינו משנה את גבולות הסמכות שנקבעו בו.
המטרה היא למנוע payloads נקודתיים או שונים בין רכיבים. כל event הנשלח מה-Local Engine ל-Control Plane חייב לעבור דרך Envelope אחיד, validation אחיד וכללי compatibility אחידים.
2. סמכות וגבולות
- • Base44 נשאר Control Plane ו-System of Record.
- • Event הוא דיווח/עובדה תפעולית; הוא אינו מעניק סמכות ל-Risk, CIO/Decision או Execution.
- • Trigger event אינו Candidate, Decision או Trade.
- • אין AI/LLM ואין Broker integration במסגרת M1-M3.
- • אין credentials, tokens או secrets בתוך event.
- • אין hardcoded thresholds בתוך schema; threshold/policy values מגיעים מ-configuration/policy versioned.
- • כל הרחבה של event type, enum מחייב או breaking field מחייבת versioning ואישור לפי כללי מסמך זה.
3. עקרונות החוזה
| עיקרון | כלל מחייב | ||
|---|---|---|---|
| Canonical Envelope | כל event משתמש באותה מעטפת ליבה; ההבדל בין event types נמצא ב-payload. | ||
| Schema First | אין producer חדש לפני שקיים schema מאושר עבור event type. | ||
| Versioned | schema_version נמצא בכל event; שינוי breaking יוצר major version חדש. | ||
| Idempotent | idempotency_key מחייב; צרכן חייב להיות מסוגל לקבל duplicate ללא duplicate side effect. | ||
| Immutable Event | event שנשלח אינו נערך; תיקון/עדכון הוא event חדש עם correlation/reason מתאים. | ||
| UTC Time | כל timestamps מועברים ב-UTC ISO-8601; זמן מקור נשמר בנפרד כאשר רלוונטי. | ||
| Traceable | event_id, correlation_id, engine_id, user_id, engine_version ו-policy/config versions מאפשרים audit. | ||
| Fail Closed | event לא תקין אינו מקודם כאילו התקבל בהצלחה; הוא נרשם/נכנס למסלול error/retry. |
4. Canonical Event Envelope v1
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| event_id | UUID/string | כן | מזהה ייחודי immutable לאירוע יחיד. |
| event_type | enum/string | כן | סוג האירוע לפי Event Registry במסמך זה. |
| schema_version | string | כן | גרסת schema, בפורמט major.minor; v0.1 מגדיר envelope schema 1.0. |
| user_id | string | כן | מזהה פנימי של הקשר המשתמש; לא שם/דוא"ל. |
| engine_id | string | כן | מזהה Local Engine חד-משמעי. |
| source | string | כן | הרכיב המפיק, לדוגמה local_engine, market_monitor, trigger_engine. |
| occurred_at | timestamp UTC | כן | מועד התרחשות העובדה/האירוע. |
| sent_at | timestamp UTC | כן | מועד ניסיון השליחה הנוכחי. אינו מחליף occurred_at. |
| correlation_id | string | כן | קישור אירועים מאותו flow/scan/config cycle. |
| idempotency_key | string | כן | מפתח dedup יציב לאותה עובדה לוגית. |
| severity | enum | כן | INFO / WARNING / ERROR / CRITICAL. |
| status | string/enum | כן | סטטוס דומייני של event_type, לא סטטוס delivery/processing. כאשר קיים שדה מצב מקביל ב-payload, הערכים חייבים להיות עקביים; חוסר התאמה → REJECT_SCHEMA. |
| source_data_age_ms | integer/null | מותנה | גיל נתון המקור במילישניות בזמן occurred_at; null כאשר אין מקור נתונים חיצוני. |
| engine_version | string | כן | גרסת build/runtime שהפיקה את האירוע. |
| config_version | string/null | כן | גרסת configuration הפעילה; null רק אם האירוע נוצר לפני טעינת config. |
| policy_version | string/null | כן | גרסת policy הרלוונטית; null אם event אינו תלוי policy. |
| payload | object | כן | נתוני event type בלבד; חייבים לעבור validation. |
5. הבחנה בין Freshness של נתון לבין Health של Engine
בהתאם ל-v0.31, קיימים שני מושגים שונים ואסור לערבב ביניהם:
| מושג | שדה/מקור | משמעות |
|---|---|---|
| Source Data Freshness | source_data_age_ms | כמה ישן נתון המקור שעליו מבוסס event מסוים. זהו מאפיין per-event. |
| Engine Freshness/Health | health payload + Heartbeat/Freshness Policy | מצב המנוע כמערכת: LIVE / STALE / DEGRADED / OFFLINE / RECOVERING. |
אין להסיק Engine Health רק מ-source_data_age_ms, ואין להשתמש ב-health state במקום גיל נתון המקור.
6. Event Registry v0.1
| event_type | שלב ראשון | מטרה | Authority |
|---|---|---|---|
| health | M1 | Heartbeat/health/recovery state של Local Engine. | Telemetry בלבד |
| config_synced | M1 | אישור config/policy sync וגרסאות פעילות. | Acknowledgement בלבד |
| metrics_snapshot | M1 | מדדי reliability/latency/queue/cost counters. | Telemetry בלבד |
| warning | M1 | בעיה תפעולית/איכות נתונים/משאב מקומי. | Alert בלבד |
| scan_summary | M2 | סיכום deterministic monitoring/scan ב-Shadow. | Observation בלבד |
| trigger_fired | M3 | תיעוד trigger קנוני שהופעל לפי policy. | אינו Candidate/Decision/Trade |
הוספת trigger_fired ל-v0.1 נועדה לאפשר למסמך הבא — Trigger Engine Specification — להישען על חוזה קנוני מאושר, בלי להמציא event חדש מחוץ ל-schema.
7. Event Type: health
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| health_state | enum | כן | LIVE / STALE / DEGRADED / OFFLINE / RECOVERING |
| service_uptime_sec | integer | כן | זמן פעילות service מאז start/restart. |
| last_successful_sync_at | timestamp/null | כן | sync מוצלח אחרון עם Base44. |
| queue_depth | integer | כן | מספר events ממתינים מקומית. |
| storage_state | enum | כן | OK / WARNING / FULL / ERROR |
| clock_skew_ms | integer/null | כן | סטיית שעון שנמדדה; null אם טרם נמדדה. |
| reason_code | string/null | כן | קוד סיבה כאשר state אינו LIVE. |
| recovery_action | string/null | לא | פעולת recovery נוכחית/אחרונה. |
הספים המדויקים ל-LIVE/STALE/OFFLINE/DEGRADED אינם מוגדרים כאן; הם יוגדרו ב-Heartbeat/Freshness Policy v0.1 ויישארו configurable/versioned.
8. Event Type: config_synced
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| requested_config_version | string | כן | גרסה שביקש Control Plane להחיל. |
| applied_config_version | string/null | כן | גרסה שהוחלה בפועל. |
| applied_policy_version | string/null | כן | policy version פעילה לאחר sync. |
| sync_result | enum | כן | APPLIED / NO_CHANGE / REJECTED / ERROR |
| validation_errors | array | כן | ריק בהצלחה; קודי validation ללא secrets. |
| settings_digest | string | כן | digest/hash של ההגדרות הפעילות לצורכי audit; לא כולל secrets. |
SystemSettings הקיימים ב-Base44 הם מקור configuration/policy בפיילוט. Local Engine אינו רשאי להחליף threshold מוגדר ב-SystemSettings בערך hardcoded.
9. Event Type: metrics_snapshot
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| window_start | timestamp UTC | כן | תחילת חלון המדידה. |
| window_end | timestamp UTC | כן | סוף חלון המדידה. |
| events_created | integer | כן | מספר events שנוצרו. |
| events_sent | integer | כן | מספר delivery attempts ראשוניים בחלון; retries אינם נכללים כאן ונמדדים ב-events_retried. |
| events_accepted | integer | כן | מספר delivery attempts שקיבלו ACCEPTED; יחד עם events_rejected חייב להשתוות ל-events_sent עבור attempts שהושלמו בחלון. |
| events_retried | integer | כן | Retry attempts נמדדים בנפרד ואינם נכללים ב-events_sent. |
| events_rejected | integer | כן | מספר delivery attempts שקיבלו REJECTED; events_accepted + events_rejected = events_sent עבור attempts שהושלמו בחלון. |
| queue_depth_current | integer | כן | עומק queue בזמן snapshot. |
| queue_depth_max | integer | כן | מקסימום בחלון. |
| heartbeat_latency_ms | number/null | כן | latency נמדד; null אם לא ניתן למדוד. |
| event_delivery_latency_ms_p50 | number/null | לא | מדד latency אופציונלי בשלב M1. |
| event_delivery_latency_ms_p95 | number/null | לא | מדד latency אופציונלי בשלב M1. |
| base44_calls_count | integer | כן | מספר calls הניתנים לייחוס ל-Engine. |
| base44_credit_units | number/null | כן | חייב להיות null אלא אם מקור המדידה אומת מול Base44 Dashboard/מקור חשבונאי מאושר. ערך לא מאומת אסור באירוע. |
Cost/Credit metering ב-M1 הוא measurement בלבד. הוא אינו משנה תדירות, איכות או safety כדי לעמוד במכסה.
10. Event Type: warning
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| warning_code | string | כן | קוד יציב ומכונה-קריא. |
| category | enum | כן | STORAGE / CLOCK / NETWORK / CONFIG / DATA / QUEUE / SERVICE / SECURITY / OTHER |
| message | string | כן | תיאור תפעולי קצר ללא secret/PII. |
| component | string | כן | הרכיב שזיהה את הבעיה. |
| first_detected_at | timestamp UTC | כן | זיהוי ראשון. |
| current_occurrence_count | integer | כן | מספר הופעות תחת אותו correlation/dedup context. |
| action_required | boolean | כן | האם נדרשת התערבות. |
| hold_required | boolean | כן | true = Local Engine עצר capability רלוונטית. אינו מחייב action_required=true; עצירה אוטומטית שמתאוששת לבד יכולה להיות hold_required=true, action_required=false. |
warning אינו משנה Risk/Decision/Execution state. HOLD כאן הוא תפעולי ל-capability המקומית בלבד, בהתאם לסמכות שהוגדרה ב-v0.31.
11. Event Type: scan_summary
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| scan_id | string | כן | מזהה scan cycle. |
| market | enum/string | כן | US / IL או market code מאושר. |
| mode | enum | כן | SHADOW / PRODUCTION / ENFORCED. ב-M2 הערך המותר היחיד הוא SHADOW; הערכים האחרים שמורים לשלבים עתידיים לאחר Gate מפורש. |
| started_at | timestamp UTC | כן | תחילת scan. |
| completed_at | timestamp UTC | כן | סיום scan. |
| assets_evaluated | integer | כן | מספר נכסים שנבדקו. |
| checks_executed | integer | כן | מספר deterministic checks. |
| exceptions_detected | integer | כן | חריגים שזוהו. |
| data_source | string | כן | Adapter/source בפועל. |
| reference_source | string | כן | מקור הייחוס המאושר להשוואה. |
| freshness_violations | integer | כן | מספר חריגות freshness. |
| result | enum | כן | COMPLETED / PARTIAL / FAILED |
scan_summary אינו מכיל Candidate/Decision/Trade ואינו מפעיל Execution. פרטי asset-level חריגים, אם יידרשו, יוגדרו בהרחבת schema מאושרת ולא כ-payload אד-הוק.
12. Event Type: trigger_fired
| שדה | טיפוס | חובה | הערה |
|---|---|---|---|
| trigger_id | string | כן | מזהה trigger definition. |
| trigger_instance_id | string | כן | מזהה הפעלה יחידה. |
| trigger_category | enum | כן | MARKET / NEWS / STATE_RISK / OPERATIONAL — בהתאם ל-scope milestone. |
| reason_code | string | כן | סיבה מכונה-קריאה. |
| reason_text | string | כן | הסבר תפעולי קצר. |
| policy_version | string | כן | גרסת policy שהפעילה את trigger; חייב להתאים גם ל-envelope. |
| threshold_snapshot | object | כן | הערכים הרלוונטיים שהיו בתוקף; ללא hardcoding. |
| observed_values | object | כן | הערכים שנצפו והובילו להפעלה. |
| priority | enum | כן | LOW / NORMAL / HIGH / CRITICAL |
| dedup_key | string | כן | מפתח dedup ברמת trigger. |
| cooldown_until | timestamp/null | כן | מועד סיום cooldown אם קיים. |
trigger_fired הוא עובדה תפעולית בלבד. אין בו field מסוג action=BUY/SELL, order, trade_state או decision authority.
13. Idempotency, Dedup ו-Retry
- • event_id חדש נוצר פעם אחת עבור event logical instance ונשמר לאורך retry.
- • idempotency_key נשאר זהה בכל retry של אותה עובדה לוגית.
- • sent_at רשאי להשתנות בכל ניסיון שליחה; occurred_at אינו משתנה.
- • Base44/consumer חייב לשמור dedup record לפי idempotency_key או event_id בהתאם ל-event type.
- • duplicate delivery חייב להחזיר acknowledgement idempotent ולא ליצור duplicate side effect.
- • retry policy עצמה אינה מוגדרת במסמך schema; היא תישען על M1 reliability rules ו-Acceptance Plan.
- • event שנדחה בגלל schema violation אינו "מתוקן במקום"; producer יוצר event חדש רק לאחר תיקון המקור, עם trace/correlation מתאים.
14. Timestamp, Ordering ו-Clock Skew
- • כל timestamp הוא UTC ISO-8601 עם millisecond precision לפחות.
- • occurred_at מייצג זמן עובדה; sent_at מייצג זמן transport.
- • סדר arrival אינו מבטיח סדר occurrence. consumer חייב להשתמש ב-occurred_at + correlation/context ולא ב-arrival order בלבד.
- • clock_skew_ms נמדד ומדווח ב-health. חריגה מהסף העתידי תוביל ל-DEGRADED/HOLD לפי Heartbeat/Freshness Policy.
- • יעד התכנון הראשוני של 5 שניות נשאר non-binding עד Acceptance Test Plan.
15. Validation Rules
| כלל | תגובה | ||
|---|---|---|---|
| Missing required envelope field | REJECT_SCHEMA; אין קידום האירוע. | ||
| Unknown event_type | REJECT_SCHEMA אלא אם registry/version מאושר תומך בו. | ||
| Unsupported major schema version | REJECT_VERSION. | ||
| Invalid enum/value/type | REJECT_SCHEMA. | ||
| Secret/credential detected | REJECT_SECURITY + warning/audit ללא הדפסת secret. | ||
| Duplicate idempotency key | ACK_DUPLICATE; ללא side effect נוסף. | ||
| Stale source data | ה-event יכול להתקבל כעובדה אך יסומן/יטופל לפי policy; אין הצגה כ-live בניגוד ל-Freshness Policy. | ||
| Envelope status vs payload state mismatch | REJECT_SCHEMA. status הוא דומייני וחייב להיות עקבי עם שדה המצב המקביל ב-payload, כאשר קיים. | ||
| trigger_fired policy_version mismatch | REJECT_SCHEMA אם payload.policy_version שונה מ-envelope.policy_version. | ||
| Event/payload exceeds size limit | REJECT_SIZE. יעד v0.11: serialized event כולל envelope ≤ 256KB; שינוי limit הוא configuration/versioned policy ולא שינוי אד-הוק. |
16. Versioning & Compatibility
- • schema_version בפורמט major.minor. גרסת envelope הראשונה המאושרת תהיה 1.0.
- • Minor change מותר רק כאשר הוא backward-compatible, כגון optional field חדש.
- • Major change נדרש למחיקה/שינוי משמעות/שינוי type/הפיכת optional ל-required או שינוי enum שאינו backward-compatible.
- • Producer ו-consumer חייבים לדווח supported major versions.
- • במהלך rollout ניתן לתמוך זמנית ביותר מ-major אחד; deprecation דורש חלון מעבר ותיעוד.
- • אין silent coercion של type לא תקין.
17. Security & Privacy
- • אין API keys, passwords, access tokens, refresh tokens, broker credentials או OS secrets באירועים.
- • user_id הוא internal identifier; אין צורך בשם, אימייל או מידע אישי לצורך schema זה.
- • settings_digest אינו כולל secret values.
- • payload logging כפוף ל-redaction rules; raw secret לעולם אינו נרשם.
- • Transport נדרש להיות TLS בהתאם ל-v0.31.
- • Authentication של Engine Identity הוא דרישת M1 אך credential format אינו חלק מה-event schema.
18. Delivery Acknowledgement — חוזה מינימלי
| שדה response | טיפוס | משמעות | |
|---|---|---|---|
| event_id | string | ה-event שאליו מתייחס ה-ack. | |
| receipt_status | enum | ACCEPTED / DUPLICATE / REJECTED | |
| received_at | timestamp UTC | מועד קבלה ב-Control Plane. | |
| schema_version | string | הגרסה שנבדקה. | |
| error_code | string/null | קוד rejection אם קיים. | |
| retryable | boolean | האם producer רשאי לנסות שוב ללא שינוי event content. |
HTTP/API transport details, endpoint paths ו-auth headers אינם ננעלים במסמך זה; הם יוגדרו ב-M1 implementation contract. החוזה הלוגי של acknowledgement כן ננעל כאן.
19. דוגמאות קנוניות
דוגמה 1 — health event:
{
"event_id": "evt-uuid-001",
"event_type": "health",
"schema_version": "1.0",
"user_id": "usr-internal-01",
"engine_id": "eng-01",
"source": "local_engine",
"occurred_at": "2026-09-09T07:30:00.000Z",
"sent_at": "2026-09-09T07:30:00.120Z",
"correlation_id": "health-20260909-0730",
"idempotency_key": "eng-01:health:20260909T073000Z",
"severity": "INFO",
"status": "LIVE",
"source_data_age_ms": null,
"engine_version": "pilot-m1-build",
"config_version": "cfg-vX",
"policy_version": "pol-vX",
"payload": {
"health_state": "LIVE",
"service_uptime_sec": 3600,
"last_successful_sync_at": "2026-09-09T07:29:58.000Z",
"queue_depth": 0,
"storage_state": "OK",
"clock_skew_ms": 120,
"reason_code": null,
"recovery_action": null
}
}דוגמה 2 — trigger_fired event:
{
"event_id": "evt-uuid-002",
"event_type": "trigger_fired",
"schema_version": "1.0",
"user_id": "usr-internal-01",
"engine_id": "eng-01",
"source": "trigger_engine",
"occurred_at": "2026-09-09T08:00:00.000Z",
"sent_at": "2026-09-09T08:00:00.080Z",
"correlation_id": "scan-cycle-example",
"idempotency_key": "trigger-example-instance",
"severity": "WARNING",
"status": "FIRED",
"source_data_age_ms": 1500,
"engine_version": "pilot-m3-build",
"config_version": "cfg-vX",
"policy_version": "pol-vX",
"payload": {
"trigger_id": "trg-example",
"trigger_instance_id": "tri-example",
"trigger_category": "MARKET",
"reason_code": "THRESHOLD_CROSSED",
"reason_text": "Example only",
"policy_version": "pol-vX",
"threshold_snapshot": { "example_threshold": "configured-value" },
"observed_values": { "example_value": "observed-value" },
"priority": "NORMAL",
"dedup_key": "dedup-example",
"cooldown_until": null
}
}הערה: cfg-vX / pol-vX / pilot-m1-build הם placeholders תיעודיים בלבד; אין במסמך זה קביעה של גרסה תפעולית אמיתית. הדוגמה אינה מגדירה threshold, symbol, BUY/SELL או פעולה מסחרית; היא מדגימה את מבנה החוזה בלבד.
20. Error/Failure Events
v0.11 משתמש ב-warning + health לצורך failure reporting ואינו מוסיף event_type נפרד בשם error. הסיבה: למנוע כפילות בין severity לבין event type בשלב M1.
21. Derivation Trace
| דרישה ב-Canonical Event Schema | מקור מחייב | ||
|---|---|---|---|
| Canonical, versioned, idempotent events | Local Engine Pilot Specification v0.31 §4, §7, §8 | ||
| Base44 = System of Record | v0.31 §1, §2, §5 | ||
| Envelope core fields | v0.31 §8 | ||
| source_data_age נפרד מ-engine freshness | v0.31 §8-9 | ||
| health states כולל DEGRADED | v0.31 §9, §14 | ||
| config_synced + metrics_snapshot | v0.31 §8; תיקוני צוות שננעלו ב-v0.31 | ||
| Cost/Credit counters | v0.31 §7 | ||
| trigger_fired אינו Decision/Trade | v0.31 §10; נדרש כדי לאפשר את המסמך הבא | ||
| No secrets in events | v0.31 §15 | ||
| Clock skew / storage failure | v0.31 §14 | ||
| No AI/Broker in M1-M3 | v0.31 §12-13 |
New Requirement המסומן במסמך זה: acknowledgement logical contract ו-schema compatibility rules מפורטים. הם נגזרים פונקציונלית מדרישות reliability/idempotency/versioning של v0.31, אך לא פורטו שם ברמת שדות; לכן הם מובאים כאן לאישור מפורש כחלק מ-G-EVENT.
22. שאלות לצוות לפני G-EVENT
- האם Envelope fields מלאים ומינימליים, או שיש שדה חובה נוסף שחסר לפני M1?
- האם source_data_age_ms במילישניות הוא היחידה הנכונה, או להעדיף timestamp של source ולחשב age בצרכן?
- האם event types: health, config_synced, metrics_snapshot, warning, scan_summary, trigger_fired מספיקים ל-M1-M3?
- האם נכון להשאיר error כ-severity/health-warning ולא ליצור event_type נפרד בשלב זה?
- האם ACK logical contract צריך להינעל כבר ב-v0.1 כפי שמוצע?
- האם user_id + engine_id מספיקים isolation/audit לפיילוט יחיד בלי להוסיף account_id בשלב M1?
- האם metrics_snapshot צריך לכלול base44_credit_units nullable, או להסתפק ב-base44_calls_count עד שקיימת מדידת credits אמינה?
- האם threshold_snapshot ב-trigger_fired צריך להכיל רק ערכים רלוונטיים ל-trigger ולא policy מלא? ההמלצה במסמך: רק הערכים הרלוונטיים.
- האם קיימת דרישת retention/audit ב-Base44 שיש לנעול כבר ברמת schema, או להשאיר ל-M1 implementation/Acceptance Plan?
- האם יש blocker שמונע מעבר ל-Trigger Engine Specification v0.1 לאחר אישור מסמך זה?
23. Gate G-EVENT
אישור Canonical Event Schema v0.1 נועל את החוזה הלוגי שממנו ייגזר Trigger Engine Specification v0.1. האישור אינו הרשאת קוד, הרצה או שינוי ב-Base44.
לאחר אישור G-EVENT, המסמך הבא בסדר המחייב הוא Trigger Engine Specification v0.1.
24. החלטה מוצעת
לאשר את InvestIQ Canonical Event Schema v0.11 כחוזה האירועים המחייב לפיילוט M1-M3, בכפוף להערות הצוות ולנעילת G-EVENT.
InvestIQ Canonical Event Schema v0.11 | Candidate for Approval | 9 September 2026