# R5 capability census — BATCH 2 evidence (read-only)

Census date: 2026-06-15. Donor = multideal (primary); cross-checks noted inline. No verdicts.

---

## notifications
### Donor capabilities (mature) — what the donor actually has in this domain
- Tiered event registry (critical/optional/marketing + durable/pushFallback flags) — multideal/apps/web/src/server/notifications/event-registry.ts:12 — `EVENT_REGISTRY` maps ~80 events to delivery metadata.
- Write durable notification + outbox enqueue — multideal/apps/web/src/server/notifications/send.ts:14 — `writeNotification` persists inbox row and queues `notification.deliver` when `durable`.
- Live topic publish via Durable Object — multideal/apps/web/src/server/notifications/send.ts:63 — `publishLive` pushes realtime envelopes to `TOPIC_DO` channels.
- Web Push offline fallback — multideal/apps/web/src/server/notifications/push-fallback.ts:14 — `sendPushFallback` fires VAPID push when user has no open WS.
- Outbox deliver handler (in-app WS then push fallback) — multideal/apps/web/src/server/workflows/outbox/handlers/notification.deliver.ts:17 — Loads `live_notifications`, delivers via `UserSessionDO`, falls back to push.
- Inbox persistence + read-state — multideal/apps/web/src/server/db/queries/live-notifications.ts:44 — `markRead`, `unreadCount`, `listInboxPage` on `readAt`.
- Tier-aware user notification prefs — multideal/apps/web/src/server/db/queries/notif-prefs.ts:43 — `allowsEvent` gates optional/marketing per-event toggles.
- Bilingual title/body render — multideal/apps/web/src/server/notifications/render.ts:10 — `renderTitle` / `renderBody` for he/en notification copy.
- Live channel authz (chat/ticket/case/admin) — multideal/apps/web/src/server/notifications/topics.ts:126 — `canSubscribe` enforces per-channel access rules.
- VAPID push with per-type toggles + 410 prune — multideal/apps/web/src/server/push/send.ts:176 — `createPushClient` checks `preferences_profile.notifications` and deletes stale subs.
- Weekly buyer digest workflow — multideal/apps/web/src/server/workflows/outbox/handlers/handle-buyer-digest-weekly.ts:28 — Marketing email digest gated on `notifPrefs.marketing.all`.
- Support notification email outbox — multideal/apps/web/src/server/workflows/outbox/handlers/support.notif.email.ts:21 — `support.notif.email` sends templated Resend mail.
- Multi-adapter fanout (`Promise.allSettled`) — zync.is/packages/notifications/src/deliver.ts:30 — `deliverNotification` runs email + telegram + web-push adapters.
- Telegram notification adapter — zync.is/packages/notifications/src/adapters/telegram.ts:49 — `TelegramNotificationAdapter` with per-type opt-in + bot token lookup.
- Email adapter with DB-backed channel prefs — zync.is/packages/notifications/src/adapters/email.ts:39 — `canDeliver` reads `user_preferences.notification_channels.email`.
- Web Push adapter + expired-sub pruning — zync.is/packages/notifications/src/adapters/web-push.ts:23 — Fans out to all subs; prunes 410 Gone endpoints.
- In-app WebSocket push seam — zync.is/packages/notifications/src/ws-push.ts:17 — `pushOverWebSocket` forwards to TenantRealtimeDO via KV session key.
- Encrypted adapter credential storage — zync.is/packages/notifications/src/credentials.ts:17 — `saveAdapterCredential` / `loadAdapterCredential` for tenant bot tokens.
- Locale-aware MJML email templates — zync.is/packages/notifications/src/email/render.ts:117 — `renderEmailTemplate` for verification/invoice/invitation variants.

### DELTA (donor HAS, module surface LACKS)
- Telegram channel adapter — zync.is/packages/notifications/src/adapters/telegram.ts:49 — Third delivery channel beyond email/webpush — sibling-overlap: notifications
- In-app/live inbox delivery (WS/DO) — multideal/apps/web/src/server/workflows/outbox/handlers/notification.deliver.ts:51 — Delivers to `UserSessionDO` before push fallback — sibling-overlap: realtime-react
- Notification read-state / inbox queries — multideal/apps/web/src/server/db/queries/live-notifications.ts:44 — `markRead` + unread counts persisted in DB — sibling-overlap: db
- Event tier registry (critical/optional/marketing) — multideal/apps/web/src/server/notifications/event-registry.ts:12 — Per-event durable/pushFallback/channel metadata — sibling-overlap: none
- Email→push fallback orchestration — multideal/apps/web/src/server/notifications/push-fallback.ts:14 — Offline users get Web Push when registry marks `pushFallback` — sibling-overlap: notifications
- Digest/batching workflow engine — multideal/apps/web/src/server/workflows/outbox/handlers/handle-buyer-digest-weekly.ts:28 — Scheduled marketing digest via outbox handler — sibling-overlap: jobs
- Concrete DB-backed preference store — multideal/apps/web/src/server/db/queries/notif-prefs.ts:13 — `loadPrefs`/`updatePrefs` on `users.notif_prefs` JSONB — sibling-overlap: db
- Live topic routing/authz — multideal/apps/web/src/server/notifications/topics.ts:126 — Chat/ticket/case/admin channel subscription guards — sibling-overlap: auth
- WebSocket in-app push (zync) — zync.is/packages/notifications/src/ws-push.ts:17 — Best-effort realtime forward when KV session exists — sibling-overlap: realtime-react
- Encrypted per-tenant adapter credentials — zync.is/packages/notifications/src/credentials.ts:17 — Stores Telegram/adapter secrets encrypted — sibling-overlap: db
- SMS channel — none found in donors — No SMS sender in multideal or zync notification packages — sibling-overlap: none

### Maturity note
- zync.is is richer for multi-channel `deliverNotification` fanout (`packages/notifications/src/deliver.ts`), Telegram adapter, WS in-app push, and encrypted credentials; multideal is richest for durable inbox + read-state + outbox workflow + live DO delivery.

---

## ledger
### Donor capabilities (mature) — what the donor actually has in this domain
- Caller-provided tx append — multideal/apps/web/src/server/referrals/ledger.ts:150 — `appendLedgerEntryTx(tx, …)` runs insert + wallet projection inside outer transaction.
- Self-wrapped tx append — multideal/apps/web/src/server/referrals/ledger.ts:229 — `appendLedgerEntry` opens `db.transaction()` when caller has no outer tx.
- Idempotent append (entry_type, source_type, source_id) — multideal/apps/web/src/server/referrals/ledger.ts:164 — `onConflictDoNothing` on unique triplet; skips balance update on duplicate.
- Multi-column wallet projection — multideal/apps/web/src/server/referrals/ledger.ts:194 — Updates `balance_agorot`, `pending_agorot`, `matured_agorot`, `lifetime_earned_agorot` per entry class.
- Typed debit/earn entry types — multideal/apps/web/src/server/referrals/ledger.ts:24 — `LedgerEntryType` enum (`referral_reward`, `redemption`, `refund_clawback`, etc.).
- Vesting `matureAt` scheduling — multideal/apps/web/src/server/referrals/maturation.ts:22 — `computeMatureAt` derives hold-until from deal kind/redemption state.
- Pending→matured sweep job — multideal/apps/web/src/server/referrals/maturation.ts:38 — `sweepMaturedCredits` promotes pending rows when `mature_at <= now`.
- Withdrawable eligibility sweep — multideal/apps/web/src/server/referrals/withdrawable-sweep.ts:14 — Sets `withdrawable_at` and recomputes `withdrawable_agorot`.
- TOCTOU-safe payout debit — multideal/apps/web/src/server/referrals/payout-debit.ts:33 — `debitPayoutInTx` locks wallet, checks withdrawable, appends redemption row atomically.
- Negative-balance carry-forward policy — multideal/apps/web/src/server/referrals/clawback.ts:165 — Matured clawbacks allow negative `balance_agorot`; pending floored at 0.
- Lifetime carve-out SQL — multideal/apps/web/src/server/referrals/ledger.ts:55 — `LIFETIME_CARVEOUT_SQL` excludes affiliate payout reversals from lifetime sum.
- Ledger→wallet reconcile CTE — multideal/apps/web/src/server/referrals/ledger.ts:77 — `reconcileWalletFromLedger` rebuilds balance/lifetime from source-of-truth in one statement.
- Cached balance read — multideal/apps/web/src/server/referrals/ledger.ts:242 — `getBalance` reads `wallet_balances` projection with optional lifetime pair.

### DELTA (donor HAS, module surface LACKS)
- Pending/matured/withdrawable wallet columns — multideal/apps/web/src/server/referrals/ledger.ts:194 — Four-bucket balance projection beyond single balance column — sibling-overlap: db
- Vesting hold scheduling — multideal/apps/web/src/server/referrals/maturation.ts:22 — `computeMatureAt` + `matureAt` on append drives pending vs instant-matured — sibling-overlap: none
- Withdrawable sweep + payout debit — multideal/apps/web/src/server/referrals/withdrawable-sweep.ts:14 — Eligibility window before funds are spendable — sibling-overlap: jobs
- Typed debit-reason enum — multideal/apps/web/src/server/referrals/ledger.ts:24 — Domain-specific `LedgerEntryType` values — sibling-overlap: none
- Negative-balance carry-forward — multideal/apps/web/src/server/referrals/clawback.ts:165 — Allows debt on matured/balance columns (module throws `InsufficientBalanceError`) — sibling-overlap: none
- Lifetime earned tracking — multideal/apps/web/src/server/referrals/ledger.ts:192 — `lifetimeEarnedAgorot` incremented on positive earns — sibling-overlap: none
- Ledger reconciliation repair — multideal/apps/web/src/server/referrals/ledger.ts:77 — Cron-safe full recompute from `credit_ledger` — sibling-overlap: jobs
- Self-wrapped transaction entrypoint — multideal/apps/web/src/server/referrals/ledger.ts:229 — `appendLedgerEntry` when host does not supply outer tx (module requires caller tx) — sibling-overlap: db
- Double-entry bookkeeping — none found — Donor uses single-entry signed-delta ledger, not paired accounts — sibling-overlap: none
- zync wallet/credit ledger — none found — No comparable balance ledger in zync.is packages — sibling-overlap: none

### Maturity note
- multideal is richest (`server/referrals/ledger.ts` + maturation/withdrawable/clawback); no meaningful zync.is ledger donor for this domain.

---

## tax
### Donor capabilities (mature) — what the donor actually has in this domain
- Israel VAT schedule in system_config — multideal/apps/web/src/server/db/queries/vat.ts:49 — `getVatSchedule` reads `il.vat_schedule` JSON array.
- Date-effective rate resolution — multideal/apps/web/src/server/db/queries/vat.ts:59 — `getVatRateForDate` picks last entry with `effectiveDateIl <= date`.
- Pure schedule lookup helper — multideal/apps/web/src/server/db/queries/vat.ts:27 — `findRateInSchedule` for pre-fetched schedules (no DB).
- Admin append VAT schedule entry — multideal/apps/web/src/server/db/queries/vat.ts:78 — `addVatEntry` rejects duplicate effective dates.
- Tax document upsert (purchase × side) — multideal/apps/web/src/server/db/queries/tax-documents.ts:16 — `upsertTaxDoc` idempotent on `(purchaseId, side)`.
- Purchase finalize issues vendor+platform tax docs — multideal/apps/web/src/server/payments/finalize.ts:41 — `issueInvoices` calls `InvoiceProvider.issueTaxDoc` per side with `vatPct`.
- Per-side line items on tax doc — multideal/apps/web/src/server/payments/finalize.ts:98 — Vendor gets deal line; platform gets platform-fee line (separate docs).
- Invoice provider VAT-id on vendor — multideal/apps/web/src/server/invoicing/provider.ts:4 — `IssueTaxDocInput` includes `vendor.vatId` optional field.
- Inclusive VAT math (extract from gross) — platform/packages/tax/src/rates-table/vat-math.ts:37 — `extractVat` documented as multideal inclusive model (module HAS this).
- Exclusive VAT math (add to net) — platform/packages/tax/src/rates-table/vat-math.ts:27 — `applyVat` documented as zync exclusive model (module HAS this).
- Per-line taxable flags + totals — zync.is/packages/db/src/queries/invoices.ts:321 — `computeTotals` sums taxable vs non-taxable lines separately.
- VAT rate from `vat_rates` table — zync.is/packages/db/src/queries/invoices.ts:289 — `getVatRateForDate` queries country-effective rate rows.
- Tax issue on invoice finalize — zync.is/packages/db/src/queries/invoices.ts:803 — Stores immutable `vat_rate` at issue time with line-level breakdown.
- Receipt tax-issue flag — zync.is/packages/db/src/queries/receipts.ts:236 — `taxIssued` marks cash-sale tax document issuance in tx.

### DELTA (donor HAS, module surface LACKS)
- Tax document persistence — multideal/apps/web/src/server/db/queries/tax-documents.ts:16 — `tax_documents` table with provider doc id + idempotency key — sibling-overlap: db
- Tax document issuance orchestration — multideal/apps/web/src/server/payments/finalize.ts:41 — `issueInvoices` composes purchase finalize + provider — sibling-overlap: billing
- Admin-mutable VAT schedule — multideal/apps/web/src/server/db/queries/vat.ts:78 — Runtime schedule append via `system_config` (module uses static datasets) — sibling-overlap: db
- Per-purchase vendor/platform doc sides — multideal/apps/web/src/server/payments/finalize.ts:57 — Separate vendor vs platform tax docs per purchase — sibling-overlap: billing
- VAT-id on vendor for invoicing — multideal/apps/web/src/server/invoicing/provider.ts:4 — Optional `vatId` passed to invoice provider — sibling-overlap: none
- Per-line vs per-invoice tax — zync.is/packages/db/src/queries/invoices.ts:321 — Line-level `taxable` flag with aggregated VAT (module is rate-table only) — sibling-overlap: billing
- Tax exemption handling — zync.is/packages/db/src/queries/invoices.ts:328 — Non-taxable lines excluded from taxable subtotal — sibling-overlap: none
- VAT-id validation — none found — Donors pass/store VAT ids but no dedicated validation routine found — sibling-overlap: none

### Maturity note
- zync.is is richer for full invoicing tax composition (`packages/db/src/queries/invoices.ts` per-line taxable + issue-time rate); multideal is richest for purchase-side tax-doc issuance tied to payments finalize.

---

## uploads
### Donor capabilities (mature) — what the donor actually has in this domain
- Upload initiate/finalize orchestration — multideal/apps/web/src/server/storage/uploads.ts:305 — `initiateUpload` creates PENDING row + HMAC token; `finalizeUpload` validates and writes R2.
- Magic-byte sniff (JPEG/PNG/WebP/AVIF/GIF) — multideal/apps/web/src/server/storage/r2.ts:50 — `validateMagicBytes` on first 16 bytes server-side.
- 5 MB size cap enforcement — multideal/apps/web/src/server/storage/r2.ts:27 — `MAX_UPLOAD_BYTES` checked during stream buffering.
- Purpose-based dimension constraints — multideal/apps/web/src/server/storage/imageDimensions.ts:27 — `PURPOSE_CONSTRAINTS` min width/height per upload purpose.
- Header-only dimension parser — multideal/apps/web/src/server/storage/imageDimensions.ts:8 — `parseDimensions` reads JPEG/PNG/WebP headers in Workers.
- HMAC upload token (worker-proxied, not S3 presign) — multideal/apps/web/src/server/storage/r2.ts:12 — Direct-through-worker pattern; token verified on complete.
- AI image moderation enqueue — multideal/apps/web/src/server/storage/uploads.ts:245 — `maybeEnqueueModeration` queues `IMAGE_APPROVAL` LLM job unless exempt.
- Client-side image encoder (Web Worker) — multideal/apps/web/src/lib/image-upload/encodeImage.ts:48 — `encodeImage` hashes + generates variant blobs via jsquash WASM.
- Client variant upload bundle — multideal/apps/web/src/lib/image-upload/uploadImage.ts:28 — `uploadEncoded` POSTs original + variants to `/api/uploads/complete`.
- Worker-side variant encoding — multideal/apps/web/src/lib/image-upload/encodeImage.worker.ts:4 — Off-main-thread resize/encode with progress events.
- Content-addressed sha256 keys — multideal/apps/web/src/server/storage/uploads.ts:455 — Finalize computes sha256 for `originals/{sha256}.*` keys.
- Variant public URL builder — multideal/apps/web/src/server/storage/uploads.ts:34 — `variantR2PublicUrl` for `/r2/variants/{sha256}/…` paths.
- R2 putObject helper — multideal/apps/web/src/server/storage/r2.ts:186 — `writeToR2` with content-type + cache headers.
- zync attachment query layer — zync.is/packages/db/src/queries/attachments.ts:27 — Attachment rows with `uploader_id` (storage orchestration lives in app routes).
- zync R2 env binding — zync.is/packages/types/src/env.ts:10 — `STORAGE: R2Bucket` typed binding (no shared upload module package).

### DELTA (donor HAS, module surface LACKS)
- Client-side image encoder/resizer — multideal/apps/web/src/lib/image-upload/encodeImage.ts:48 — Web Worker + jsquash variant pipeline (known gap) — sibling-overlap: none
- Upload lifecycle orchestration (initiate/finalize) — multideal/apps/web/src/server/storage/uploads.ts:305 — DB row + token + stream validation + R2 write — sibling-overlap: db
- AI/abuse scan gate — multideal/apps/web/src/server/storage/uploads.ts:245 — `IMAGE_APPROVAL` LLM moderation enqueue on finalize — sibling-overlap: ai
- Image variant/derivative generation — multideal/apps/web/src/lib/image-upload/encodeImage.worker.ts:4 — thumb/card/hero/og variants encoded client-side — sibling-overlap: none
- Proxied worker upload flow — multideal/apps/web/src/server/storage/r2.ts:12 — HMAC token + server-side stream (module ships S3-compat presign instead) — sibling-overlap: none
- Purpose-specific dimension enforcement — multideal/apps/web/src/server/storage/imageDimensions.ts:27 — Min dimensions per purpose on server finalize — sibling-overlap: none
- Upload approval status tracking — multideal/apps/web/src/server/storage/uploads.ts:340 — `approvalStatus`/`scanStatus` columns on `image_uploads` — sibling-overlap: db
- zync dedicated uploads package — none found — Storage is app-level + `attachments` queries only — sibling-overlap: none

### Maturity note
- multideal is richest (`server/storage/` + `lib/image-upload/` client encoder); zync.is has attachment DB helpers and R2 binding types but no comparable upload pipeline module.

---

## billing
### Donor capabilities (mature) — what the donor actually has in this domain
- Stripe webhook verify + dedup claim — multideal/apps/web/src/pages/api/payments/stripe/webhook.ts:56 — Signature check; `claimWebhookEvent` single-winner processing.
- Purchase finalize chokepoint — multideal/apps/web/src/server/payments/finalize.ts:286 — `finalizePurchase` from webhook, redirect poll, or reconcile DO.
- Tax doc issuance in finalize — multideal/apps/web/src/server/payments/finalize.ts:349 — Step 1 issues vendor+platform invoices with VAT rate from DB.
- Referral earn + ledger append in finalize — multideal/apps/web/src/server/payments/finalize.ts:372 — Idempotent referral commission via dynamic import of referrals service.
- Stripe charge (interactive + off-session) — multideal/apps/web/src/server/payments/stripe-provider.ts:119 — PaymentIntent create with saved card or client-secret path.
- 3DS/SCA interactive path — multideal/apps/web/src/server/payments/stripe-provider.ts:124 — `automatic_payment_methods` + `clientSecret` for browser confirmation.
- Hold/capture/release idempotency — multideal/apps/web/src/server/payments/stripe-provider.ts:282 — Reservation holds with `idempotency.hold/captureHold/releaseHold`.
- Refund with stable idempotency key — multideal/apps/web/src/server/payments/stripe/idempotency.ts:6 — `refund(purchaseId, amountAgorot)` keyed per claim.
- Platform fee percentage source — multideal/apps/web/src/server/payments/platform-fee.ts:5 — `getPlatformFeePct` from env for Stripe split math.
- Stripe Connect vendor onboarding — multideal/apps/web/src/server/payments/connect/affiliate-onboarding.ts:97 — Account/link/session creation for affiliates.
- Stripe Connect affiliate payout transfer — multideal/apps/web/src/server/payments/connect/affiliate-payout.ts:13 — Transfer + payout with idempotency per payout id.
- Refund policy calculator (pure) — multideal/apps/web/src/server/payments/refund.ts:64 — Deal-type-specific refund/fee/platform/vendor split rules.
- Stripe reconcile backstop — multideal/apps/web/src/server/payments/stripe/reconcile.ts:130 — Handles `payment_intent_unexpected_state` edge cases.
- zync subscription lifecycle — zync.is/packages/db/src/queries/subscriptions.ts:23 — `getSubscriptionByTenantId`, trial expiry, cancel/activate/downgrade.
- zync billing history queries — zync.is/packages/db/src/queries/index.ts:681 — Re-exports `billing` module helpers (plans, payment methods).
- zync invoice auto-charge — zync.is/packages/db/src/queries/invoices.ts:1678 — Transactional auto-charge flow skipping intermediate states.

### DELTA (donor HAS, module surface LACKS)
- Purchase finalize orchestration — multideal/apps/web/src/server/payments/finalize.ts:286 — QR, tax docs, referral, push, outbox in one chokepoint — sibling-overlap: ledger
- Platform-fee routing in Stripe PI — multideal/apps/web/src/server/payments/platform-fee.ts:5 — Env-driven fee % applied in provider math — sibling-overlap: none
- Stripe Connect payouts — multideal/apps/web/src/server/payments/connect/affiliate-payout.ts:90 — Transfer + payout to connected accounts — sibling-overlap: none
- Domain refund policy calculator — multideal/apps/web/src/server/payments/refund.ts:64 — Deal-type refund splits (module has generic refund funnel) — sibling-overlap: none
- Ledger+tax composition in finalize — multideal/apps/web/src/server/payments/finalize.ts:349 — Issues tax docs and referral ledger in same finalize path — sibling-overlap: tax
- 3DS/SCA client-action branch — multideal/apps/web/src/server/payments/stripe-provider.ts:147 — Returns `clientSecret` for browser confirmation (module has `requires_client_action` shape) — sibling-overlap: none
- Subscription/recurring billing — zync.is/packages/db/src/queries/subscriptions.ts:58 — Tenant subscription tiers/trials/grace (not in module) — sibling-overlap: billing
- Dunning / failed-payment retry — none found — No dedicated dunning workflow located in multideal payments tree — sibling-overlap: jobs
- Concrete Stripe webhook route — multideal/apps/web/src/pages/api/payments/stripe/webhook.ts:56 — App-level handler with purchase/outbox side-effects (module ships generic `ingestWebhook`) — sibling-overlap: none

### Maturity note
- multideal is richest for Stripe charge/refund/webhook/finalize + Connect payouts; zync.is is richer for subscription/recurring tenant billing (`packages/db/src/queries/subscriptions.ts`).

---

## helpdesk
### Donor capabilities (mature) — what the donor actually has in this domain
- Support ticket CRUD — multideal/apps/web/src/server/db/queries/support-tickets.ts:9 — `insert`, `findById`, `listByOpener`, `updateStatus`, `assignAgent`.
- Transaction case CRUD — multideal/apps/web/src/server/db/queries/support-cases.ts:9 — Separate `transaction_cases` entity with vendor/customer roles.
- KB article search — multideal/apps/web/src/server/db/queries/support-kb.ts:109 — `search` ILIKE on title/body with locale fallback.
- KB slug/category listing — multideal/apps/web/src/server/db/queries/support-kb.ts:43 — `findBySlug`, `listByCategory`, translated article views.
- Support messages query layer — multideal/apps/web/src/server/db/queries/support-messages.ts:1 — Thread messages for tickets/cases (app queries; not platform export).
- Support attachments query layer — multideal/apps/web/src/server/db/queries/support-attachments.ts:1 — File metadata linked to support parents.
- State transition audit log — multideal/apps/web/src/server/db/queries/support-state-transitions.ts:9 — `insert` + `listByParent` for ticket/case status history.
- Dual SLA due timestamps on cases — multideal/apps/web/src/server/db/queries/support-cases.ts:63 — `setSlaDueAt` for `ai` vs `human` targets.
- Admin atomic ticket close + transition — multideal/apps/web/src/server/db/queries/support-tickets.ts:99 — `adminCloseTicket` wraps status + audit row.
- AI tool: get ticket — multideal/apps/web/src/server/ai/agents/support/tools/get-ticket.ts:19 — Loads ticket status/category/priority/opener.
- AI tool: get case — multideal/apps/web/src/server/ai/agents/support/tools/get-case.ts:1 — Loads transaction case context for agent.
- AI tool: search KB — multideal/apps/web/src/server/ai/agents/support/tools/search-kb.ts:17 — Calls `kbQ.search`, returns top-5 snippets.
- AI tool: post message — multideal/apps/web/src/server/ai/agents/support/tools/post-message.ts:1 — Agent posts support thread message.
- AI tool: close ticket — multideal/apps/web/src/server/ai/agents/support/tools/close-ticket.ts:1 — Terminal close with transition.
- AI tool: escalate to human — multideal/apps/web/src/server/ai/agents/support/tools/escalate-to-human.ts:121 — Sets escalated state + notifies.
- AI tool: set category/priority — multideal/apps/web/src/server/ai/agents/support/tools/set-category.ts:1 — Mutates ticket metadata.
- AI tool: list attachments — multideal/apps/web/src/server/ai/agents/support/tools/list-attachments.ts:1 — Lists ticket/case attachment metadata.
- AI tool: request evidence — multideal/apps/web/src/server/ai/agents/support/tools/request-evidence.ts:1 — Prompts user for supporting documents.
- AI support agent orchestrator — multideal/apps/web/src/server/ai/agents/support/agent.ts:40 — Tool loop with terminal tools (`escalate_to_human`, `close_ticket`).
- zync CRM ticket queries — zync.is/packages/db/src/queries/support.ts:30 — Tenant-scoped `TicketObject` with cursor pagination, categories, messages.
- zync ticket list cursor codec — zync.is/packages/db/src/queries/support.ts:100 — `encodeTicketCursor` / `decodeTicketCursor` for stable paging.
- ForumZone moderation flows — ForumZone/apps/web/e2e/moderation.spec.ts:259 — Thread/report/moderator actions (community moderation parallel, not tickets).

### DELTA (donor HAS, module surface LACKS)
- Ticket entity CRUD — multideal/apps/web/src/server/db/queries/support-tickets.ts:9 — Dedicated `support_tickets` table ops (module exports `SupportCase` interface only; polymorphic `parentType:'ticket'` in tests) — sibling-overlap: db
- Knowledge-base search — multideal/apps/web/src/server/db/queries/support-kb.ts:109 — `search` for AI `search_kb` tool (no KB module surface) — sibling-overlap: search
- AI agent tool: get-ticket — multideal/apps/web/src/server/ai/agents/support/tools/get-ticket.ts:23 — Reads ticket row for agent context — sibling-overlap: ai
- AI agent tool: search-kb — multideal/apps/web/src/server/ai/agents/support/tools/search-kb.ts:17 — KB lookup composed into support agent — sibling-overlap: search
- AI agent tool: post-message — multideal/apps/web/src/server/ai/agents/support/tools/post-message.ts:1 — Agent-authored thread messages beyond generic `postMessage` — sibling-overlap: ai
- AI agent tool: close-ticket — multideal/apps/web/src/server/ai/agents/support/tools/close-ticket.ts:1 — Ticket-specific close + transition wiring — sibling-overlap: helpdesk
- AI agent tool: escalate — multideal/apps/web/src/server/ai/agents/support/tools/escalate-to-human.ts:121 — Escalation side-effects + notifications — sibling-overlap: notifications
- AI agent tool: set-category/set-priority — multideal/apps/web/src/server/ai/agents/support/tools/set-category.ts:1 — Ticket metadata mutations — sibling-overlap: db
- AI agent tool: list-attachments — multideal/apps/web/src/server/ai/agents/support/tools/list-attachments.ts:1 — Attachment listing for agent context — sibling-overlap: uploads
- AI agent tool: request-evidence — multideal/apps/web/src/server/ai/agents/support/tools/request-evidence.ts:1 — Evidence request workflow step — sibling-overlap: notifications
- Transaction case entity (separate from ticket) — multideal/apps/web/src/server/db/queries/support-cases.ts:9 — Purchase-linked cases with vendor window + dual SLA — sibling-overlap: db
- Ticket opener/assignee/reopen semantics — multideal/apps/web/src/server/db/queries/support-tickets.ts:84 — `incrementReopen`, `assignAgent`, opener-scoped lists — sibling-overlap: db
- zync tenant ticket CRM — zync.is/packages/db/src/queries/support.ts:30 — Full ticket/message/category model with tenant guards — sibling-overlap: tenancy

### Maturity note
- multideal is richest (tickets + cases + KB + full AI agent tool registry); zync.is is richer for tenant-scoped CRM ticket cursor pagination (`packages/db/src/queries/support.ts`); ForumZone has thread moderation parallels only.
