בדיקה שלנו

בניית אפליקציה מאובטחת רב-ארגונית

בריף אחד לאפליקציית דיווח אירועים עם ארבעה תפקידים, בידוד בין ארגונים, קישורי שיתוף זמניים למבטח וגבול הרשאות למבקר - קודם מפרט, אחריו בנייה, ואז תקיפה.

  • בידוד בין ארגונים
  • תכנון וכתיבת מפרט
  • מודל איומים ואבטחה
  • פיתוח fullstack עם DB
  • הרשאות לפי תפקיד
  • קישורי שיתוף עם תפוגה

ריצה · 23 באוגוסט 2026

נתנו לשני מודלים את אותה משימת אבטחה

Fable ניצח בבירור על התוצר - בידוד שנכשל-סגור, אבטחה מבנית, בדיקות משלו ומוצר מלוטש שמתעדכן לבד - אבל שילם על זה: פי שניים בזמן, פי חמישה בטוקנים, ו-$107.83 מול $0. ox-alpha בנה אפליקציה תקינה, קריאה וזולה בהרבה, אבל עם בידוד מבוסס-משמעת שהתיעוד שלו עצמו מודה שהוא חלש יותר, בלי בדיקות, וללא ריענון אוטומטי. במשימת אבטחה, ההבדל בין 'נכשל-סגור' ל'דולף בשקט' הוא כל ההבדל.

זמן ריצה

  1. Claude Fable 5 + Claude Codeשעתיים ו-3 דקות
  2. ox-alpha + Claude Codeשעה

סך טוקנים

  1. Claude Fable 5 + Claude Code79.4 מיליון
  2. ox-alpha + Claude Code14.2 מיליון

בדיקות שנכתבו

  1. Claude Fable 5 + Claude Code87 עוברות
  2. ox-alpha + Claude Code0

המשימה

זו העבודה הקשה שאנחנו פוגשים אצל לקוחות אמיתיים: מערכת רב-ארגונית שבה כל תפקיד רואה בדיוק מה שמותר לו - נהג רואה רק את הדיווחים שלו, בקר רואה את כל הצי שלו ולא מעבר לזה, מבקר חוצה-ארגונים רואה רק נתונים מצרפיים בלי טקסט חופשי או זהויות, ומבטח בלי חשבון נכנס דרך קישור זמני בלבד. נתנו לשני מודלים את אותו בריף בדיוק, דרשנו את SPEC.md כ-commit ראשון ונפרד, אחריו הבנייה, ואז SECURITY.md - ואז תקפנו את מה שהם בנו.

איך אנחנו שופטים

אנחנו מודדים זמן, טוקנים, נפח קוד וכיסוי בדיקות - ובנפרד שופטים ארבעה צירים: חוזק הבידוד בין הארגונים, עמדת אבטחה כוללת, קפדנות התכנון והארכיטקטורה, ואיכות המוצר. לבידוד המשקל הגבוה ביותר: מנגנון שנכשל-סגור עדיף בהרבה על משמעת ידנית שדליפה אחת שוברת. את הבדיקה ההתקפית עשינו ידנית מול הקוד של כל אפליקציה.

ריצה · 23 באוגוסט 2026

נתנו לשני מודלים את אותה משימת אבטחה

איך הרצנו

הרצנו את שני המודלים דרך Claude Code בפרומפט אחד, בלי המשך אנושי: Claude Fable 5 במאמץ מקסימלי, ו-ox-alpha (stealth/ox-alpha) מנותב דרך OpenRouter באותה סביבה בדיוק. כל אחד קיבל מסד SQLite מקומי (node:sqlite), בלי dependencies נוספים. אחרי הסיום בנינו והרצנו lint על שתי האפליקציות, הרצנו semgrep, כתבנו בדיקות עקיפה מול ה-fixtures של כל אפליקציה, וצילמנו כל תפקיד. הטוקנים כוללים cached context; ל-ox-alpha אין caching דרך OpenRouter ולכן הוא שולח מחדש את הקונטקסט בכל תור.

הפרומפט המדויק

שני המודלים קיבלו את הבריף מילה במילה, מאותו commit בסיס זהה ביט-בביט. הבריף דרש את SPEC.md כ-commit ראשון ונפרד, לפני כתיבת קוד.

להצגת הפרומפט המלא
# Relay Desk — build brief

You are building **Relay Desk**, a slice of a real B2B incident-intake product for
fleet operators. This is a working application, not a mockup.

The repository you are in is a neutral Next.js baseline. Nothing product-specific
has been written yet. Everything below is yours to design and build.

---

## 1. The product

Fleet operators ("tenants") collect incident reports from their drivers, triage
them, and occasionally share a single incident with an outside insurer.

### Actors

| Actor | Belongs to | Can do |
|---|---|---|
| **Reporter** (driver) | exactly one tenant | Submit an incident. See their own submissions and nothing else. |
| **Reviewer** (fleet ops) | exactly one tenant | See every incident in their own tenant. Move incidents through the status workflow. Write internal notes. Generate a share link. |
| **Auditor** (platform staff) | no tenant — cross-tenant | See counts, status breakdowns, and SLA timings **across all tenants**. Must never see incident free text, reporter identities, or photos. |
| **Insurer** | no account at all | Open one shared incident through a link they were sent. Nothing else. |

### Incident

An incident has: a free-text description, a location, an occurrence time, one
uploaded photo, a reporter, a tenant, a status, and internal reviewer notes.

Status workflow: `new → in_review → resolved | rejected`. Transitions are
reviewer-only. Illegal transitions must be rejected.

### The share link

A reviewer can produce a link that lets an insurer — who has no account — view
**one** incident. The link must expire. A reviewer must be able to revoke it
before expiry. The insurer must never see internal notes.

### The auditor dashboard

Platform staff need to spot operational problems across tenants: which tenants
are slow to triage, where incidents are piling up, whether any tenant has an
unusual spike. Build something genuinely useful for that job — while holding the
line that the auditor never sees free text, reporter identity, or photos.

---

## 2. Required deliverables, in this order

**These are three separate commits. The order is part of the task.**

### Commit 1 — `SPEC.md`, before any implementation

Write the spec first and commit it on its own. It must contain:

1. **Data model** — tables, columns, types, keys, indexes.
2. **Roles × permissions matrix** — every actor against every operation, with the
   answer for each cell. No prose hand-waving.
3. **Threat model** — what an attacker would try against this system, and what
   stops each attempt.
4. **API / server-action contract** — every entry point, its inputs, its
   authorization requirement, and its failure modes.
5. **The isolation decision, stated explicitly.** Where is tenant isolation
   enforced, in exactly one sentence, and why there rather than elsewhere. Name
   what would have to be true for a future developer to accidentally break it.

### Commit 2 — the implementation

Working application. Seeded so it can be demonstrated immediately.

### Commit 3 — `SECURITY.md`

What you defended, how, and — honestly — what you did **not** get to. An accurate
list of residual risks is worth more here than a claim of completeness.

---

## 3. Technical constraints

- Next.js App Router + TypeScript, already scaffolded.
- **Database: `node:sqlite`** (built into Node 24 — `import { DatabaseSync } from "node:sqlite"`).
  No ORM, no database dependency.
- **Do not add dependencies** beyond what is already in `package.json`. If you
  believe something is genuinely unavoidable, write down why in `SPEC.md` first.
- Tailwind is available and configured.
- Authentication: implement your own session handling. Keep it simple and honest;
  do not pretend to production-grade identity. Seed users for each role.
- The app must run with `pnpm dev` and be demonstrable from the seed data alone.
- Uploaded photos are stored locally. Storage layout is your decision.

---

## 4. What "done" means

- All four actors can be demonstrated end to end from seeded data.
- The status workflow enforces its own rules.
- The share link works, expires, and can be revoked.
- The auditor dashboard is useful **and** leaks nothing it shouldn't.
- `pnpm build` and `pnpm lint` both pass.
- The three commits exist, in order.

---

## 5. How this will be judged

Three axes, weighted equally:

1. **Security.** The application will be attacked after you finish, with a suite
   you will not see. It probes cross-tenant access, privilege escalation between
   roles, share-link forgery and expiry, direct object references on incidents
   and attachments, upload handling, injection and stored XSS, and information
   leakage through errors and logs. `semgrep` will also be run over the result.

2. **Architecture and planning.** `SPEC.md` and the isolation design are reviewed
   directly. A single well-placed choke point that is hard to bypass scores far
   above correct-but-scattered checks that a future change could silently miss.

3. **Product quality.** Whether the four journeys actually work, and whether the
   interface is something a fleet operator could use.

Time, token usage, and code volume are recorded but are not by themselves a score.

---

## 6. Working agreement

- Ask questions when the brief is genuinely ambiguous. You are being paired with,
  not tested in silence.
- Do not commit or push anything outside this repository.
- Say plainly when you have made a trade-off, and what it cost.

התוצאות

התוצאות
Claude Fable 5 + Claude Codeox-alpha + Claude Code
זמן ריצהשעתיים ו-3 דקותשעה
תורי הסוכן237177
סך טוקניםכולל cached context ו-tool payloads. Fable משתמש ב-prompt caching (77M מזה cache-read זול); ל-ox-alpha אין caching דרך OpenRouter.79.4 מיליון14.2 מיליון
שורות קוד (ts/tsx)6,2713,469
בדיקות שנכתבואף אחד מהם לא התבקש לכתוב בדיקות. Fable כתב חבילת בדיקות; ox-alpha לא כתב אף בדיקה.87 עוברות0
עלות (מחויבת)Fable לפי חיוב Claude Code. ox-alpha חויב $0 בתקופת ה-stealth החינמית ב-OpenRouter - לכן השוואת עלות אינה משמעותית. באותם תעריפים של Fable, הטוקנים של ox-alpha היו עולים כ-$25.$107.83$0 (stealth)
Build · lint · semgrepעברעבר

מה כל מודל בנה

Claude Fable 5 + Claude Code

Claude Fable 5 הבחירה שלנו

הבידוד נאכף בתוך מנוע ה-SQLite: הקוד לעולם לא נוגע בטבלאות בסיס אלא רק ב-views מסוננים לפי ארגון ותפקיד, ו-predicate שנשכח זורק בזמן prepare במקום לדלוף - אימתנו את זה בשבע התקפות עקיפה מול ה-fixture שלו, וכולן נחסמו. הוא כתב 87 בדיקות שאיש לא ביקש, וה-UI מתעדכן אחרי כל שינוי בלי רענון. המחיר: מנגנון צפוף ולא מוכר שמרוכז בשני קבצים קריטיים לתחזוקה.

ox-alpha + Claude Code

ox-alpha מקום שני

בנה אפליקציה תקינה בחצי מהזמן ובחמישית מהטוקנים, והבידוד בין הארגונים נכתב במשמעת טובה בשכבת גישה אחת. אבל הבידוד הוא מוסכמה, לא מנגנון: connection.ts חושף query()/run() עם SQL חופשי, ו-predicate אחד של ארגון שנשכח דולף בשקט - SECURITY.md שלו עצמו מודה בזה ומצביע על התכנון של Fable כפתרון. מצאנו דליפה אמיתית אחת בדשבורד המבקר, אפס בדיקות, וה-UI לא מתעדכן בלי רענון ידני (אפס קריאות revalidate).

ניקוד

Claude Fable 5 + Claude Code

95/100הטוב ביותר

חוזק הבידוד בין ארגונים30
30/30
עמדת אבטחה כוללת25
22/25
קפדנות תכנון וארכיטקטורה25
24/25
איכות המוצר20
19/20

ox-alpha + Claude Code

62/100

חוזק הבידוד בין ארגונים30
15/30
עמדת אבטחה כוללת25
16/25
קפדנות תכנון וארכיטקטורה25
18/25
איכות המוצר20
13/20

איכות קוד

ההבדל המכריע הוא היכן נאכף הבידוד. Fable שם אותו במסד - view שנשכח פשוט לא קיים, אז אין דרך לדלוף. ox-alpha שם אותו במוסכמה בקוד - כל קריאת SQL שתשכח tenant_id דולפת, ואין test, lint או guard שיתפוס את זה. שני המודלים ייצרו token שיתוף חזק (256 ביט, SHA-256 באחסון, תפוגה וביטול נבדקים ב-SQL). semgrep נקי בשניהם.

איכות ויזואלית

בפסק הדין הוויזואלי, Fable מלוטש בהרבה: פריסה דו-טורית, מותג עקבי, תמונות שנוצרות פרוצדורלית וציר התקדמות. ox-alpha תקין ופונקציונלי אבל גנרי - טור יחיד, תמונות בצבע אחיד, 'Report #1' במקום מזהים אמיתיים. שתי האפליקציות מציגות את אותם גבולות אבטחה במפורש ב-UI.

מגבלות

זו ריצה אחת לכל מודל על משימה קשה אחת, לא אומדן סטטיסטי של יכולת כללית. ox-alpha רץ בתקופת stealth חינמית ב-OpenRouter ($0), ולכן השוואת עלות אינה משמעותית - הצגנו גם 'עלות בתעריפי Fable' כדי להשוות נפח. התכוונו לעבוד איתם אינטראקטיבית, אבל בפועל שני המודלים רצו עם פרומפט אחד בלי המשך אנושי - כלומר ריצה סגורה. הבדיקה ההתקפית נעשתה ידנית מול הקוד, לא כחבילת מבחנים אוטומטית חתומה מראש. הציונים בטבלת הדירוג הם ההערכה של DevShift, לא ביקורת עיוורת. ולבסוף - ox-alpha רץ דרך תוכנית ה-stealth של OpenRouter. בניגוד למקובל בהשקות stealth, הספק שלו מצהיר שהפרומפטים והתשובות אינם משמשים לאימון (OpenCode מכנה זאת zero data retention), כך שלפי המדיניות המוצהרת הבריף והקוד שנוצר לא נאספו לאימון.

מודלים שנבדקו