vibes-plug 2.11.0 → 2.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.cursor/rules/vibes-plug-core.mdc +3 -3
  2. package/.cursorrules +3 -3
  3. package/AGENTS.md +4 -4
  4. package/BLUEPRINT.md +16 -6
  5. package/CHANGELOG.md +37 -0
  6. package/CLAUDE.md +8 -8
  7. package/README.md +85 -115
  8. package/index.js +1 -1
  9. package/package.json +2 -2
  10. package/plugin.json +2 -2
  11. package/scripts/check-anti-slop.js +53 -0
  12. package/scripts/generate_swarm_gif.py +2 -2
  13. package/skills/ai-llm-integration-expert/SKILL.md +22 -15
  14. package/skills/ai-prompt-engineering-expert/SKILL.md +133 -83
  15. package/skills/anti-slop/SKILL.md +133 -0
  16. package/skills/async-queue-temporal-expert/SKILL.md +135 -158
  17. package/skills/authentication-identity-expert/SKILL.md +172 -278
  18. package/skills/brainstorming/SKILL.md +26 -26
  19. package/skills/database-orm-expert/SKILL.md +164 -303
  20. package/skills/deep-research-analyst/SKILL.md +136 -0
  21. package/skills/design-system-architect/SKILL.md +31 -1
  22. package/skills/email-notification-expert/SKILL.md +31 -4
  23. package/skills/error-resilience-expert/SKILL.md +21 -0
  24. package/skills/fullstack-expert/SKILL.md +183 -260
  25. package/skills/glsl-shader-expert/SKILL.md +190 -107
  26. package/skills/graph-rag-knowledge-expert/SKILL.md +42 -1
  27. package/skills/mcp-server-architect/SKILL.md +15 -1
  28. package/skills/prd-architect/SKILL.md +181 -206
  29. package/skills/production-ready-hardener/SKILL.md +16 -19
  30. package/skills/pwa-offline-first-expert/SKILL.md +42 -1
  31. package/skills/pydantic-ai-expert/SKILL.md +161 -0
  32. package/skills/saas-architect/SKILL.md +154 -0
  33. package/skills/senior-frontend/SKILL.md +9 -11
  34. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1 -1
  35. package/skills/session-memory-manager/SKILL.md +128 -0
  36. package/skills/synthetic-data-finetuning-expert/SKILL.md +155 -0
  37. package/skills/ui-ux-pro-max/SKILL.md +4 -2
  38. package/skills/vercel-ai-sdk-expert/SKILL.md +181 -0
  39. package/skills/voice-ai-realtime-agent/SKILL.md +41 -1
  40. package/skills/web-3d-graphics-expert/SKILL.md +313 -137
  41. package/skills/web-game-engine-expert/SKILL.md +329 -102
  42. package/skills/webxr-ar-vr-expert/SKILL.md +162 -123
  43. package/skills/zero-to-prod-orchestrator/SKILL.md +26 -24
  44. package/skills/ai-cost-token-optimizer/SKILL.md +0 -82
  45. package/skills/ai-evals-benchmark-expert/SKILL.md +0 -188
  46. package/skills/asisten-ramah/SKILL.md +0 -47
  47. package/skills/auto-doc-updater/SKILL.md +0 -220
  48. package/skills/autonomous-chaos-monkey/SKILL.md +0 -63
  49. package/skills/background-jobs-queue-expert/SKILL.md +0 -235
  50. package/skills/database-migration-versioning-expert/SKILL.md +0 -90
  51. package/skills/edge-serverless-db-expert/SKILL.md +0 -99
  52. package/skills/mcp-client-orchestrator/SKILL.md +0 -76
  53. package/skills/mobile-push-notification-expert/SKILL.md +0 -71
  54. package/skills/monday-design-aesthetic/SKILL.md +0 -73
  55. package/skills/project-context-mapper/SKILL.md +0 -85
  56. package/skills/saas-mvp-launcher/SKILL.md +0 -260
  57. package/skills/saas-transformer/SKILL.md +0 -500
  58. package/skills/saas-transformer/references/billing_integration_guide.md +0 -401
  59. package/skills/self-evolving-memory-graph/SKILL.md +0 -91
  60. package/skills/session-context-loader/SKILL.md +0 -83
  61. package/skills/session-handoff-resume/SKILL.md +0 -164
  62. package/skills/skill-baru/SKILL.md +0 -178
  63. package/skills/supabase-migration/SKILL.md +0 -91
  64. package/skills/token-saver/SKILL.md +0 -119
  65. package/skills/ui-components-expert/SKILL.md +0 -166
  66. package/skills/vibe-code-gardener/SKILL.md +0 -181
  67. /package/skills/{saas-transformer → saas-architect}/references/feature_gating_patterns.md +0 -0
  68. /package/skills/{saas-transformer → saas-architect}/references/saas_transformation_checklist.md +0 -0
  69. /package/skills/{saas-transformer → saas-architect}/scripts/saas_transformation_scanner.py +0 -0
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: async-queue-temporal-expert
3
- description: "Expert guide for Durable Workflow Engines (Temporal.io, Trigger.dev v3, Inngest, BullMQ v5) and fault-tolerant background sagas / Panduan ahli workflow engine tahan-gagal (Temporal, Trigger.dev, Inngest, BullMQ)."
3
+ description: "Unified expert guide for async job queues & durable workflows: BullMQ v5 (Redis queues), Trigger.dev v3 (serverless tasks), Inngest, and Temporal.io (distributed sagas) / Panduan ahli terpadu untuk antrean job asinkron & workflow tahan-gagal: BullMQ v5, Trigger.dev v3, Inngest, dan Temporal.io."
4
4
  author: "Roedy Rustam"
5
5
  ---
6
6
 
7
- # Async Queue & Durable Workflow Expert (Temporal & Sagas 2026)
7
+ # Async Queue & Durable Workflow Expert (2026 Unified Edition)
8
8
 
9
9
  [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
10
 
@@ -14,103 +14,112 @@ author: "Roedy Rustam"
14
14
  ## English
15
15
 
16
16
  ### Purpose & Overview
17
- Production-grade architectural guide for designing durable, fault-tolerant background execution pipelines, asynchronous job queues, and distributed state machines using **Temporal.io**, **Trigger.dev v3**, **Inngest**, and **BullMQ v5**. Guarantees eventual completion across long-running sagas, API rate limits, worker crashes, and network partitions.
18
-
19
- ### Key Capabilities
20
- 1. **Durable State Machines**: Workflows survive process restarts, deployments, and database blips without losing state or re-executing completed side-effects.
21
- 2. **Distributed Saga Pattern**: Multi-step transactions paired with automated compensating activities (rollbacks) whenever a downstream service permanently fails.
22
- 3. **Idempotency & Deduplication**: Ensuring unique idempotency keys per transaction to prevent double billing or duplicate emails.
23
- 4. **Queue Concurrency & Rate Limiting**: Token-bucket throttles, exponential backoff with jitter, and dead-letter queues (DLQ) for poison-pill isolation.
17
+ Unified production-grade guide for background execution pipelines, async job queues, and distributed state machines. Covers the full spectrum from simple Redis-backed task queues to complex multi-service sagas with compensating rollbacks.
18
+
19
+ ### 3-Tier Execution Model
20
+ | Tier | Engine | Best For |
21
+ |------|--------|----------|
22
+ | **Tier 1: Redis Task Queues** | BullMQ v5 | High-throughput worker jobs, priority queues, rate limiting, DLQ |
23
+ | **Tier 2: Serverless Durable Tasks** | Trigger.dev v3 / Inngest | Step-checkpointed tasks, automatic resume across crashes, zero infra |
24
+ | **Tier 3: Distributed Sagas** | Temporal.io | Multi-service orchestration, compensating rollbacks, long-running workflows |
25
+
26
+ ### Core Capabilities
27
+ 1. **Idempotency & Deduplication**: Deterministic `jobId` keys prevent double billing or duplicate emails.
28
+ 2. **Dead Letter Queues (DLQ)**: Auto-relocate permanently failing jobs for audit and alerting.
29
+ 3. **Exponential Backoff with Jitter**: Prevents thundering herds on upstream services.
30
+ 4. **Tenant Priority Queues**: VIP/enterprise tiers get lower BullMQ priority numbers (higher throughput).
31
+ 5. **Durable State Machines**: Workflows survive restarts, deployments, and network partitions.
32
+ 6. **Saga Compensations**: Multi-step transactions with automated reverse-order rollbacks.
24
33
 
25
34
  ---
26
35
 
27
- ### Production Implementation Recipes
36
+ ### Tier 1: BullMQ v5 — Redis Task Queues (TypeScript)
28
37
 
29
- #### Recipe 1: Temporal.io Saga Pattern with Compensations (TypeScript SDK)
30
38
  ```typescript
31
- import { proxyActivities, ApplicationFailure } from '@temporalio/workflow';
32
- import type * as activities from './activities';
39
+ import { Queue, Worker, Job } from 'bullmq';
40
+ import Redis from 'ioredis';
33
41
 
34
- // Proxy activities with aggressive retry policies
35
- const { chargeCustomer, provisionLicense, sendWelcomeEmail, refundCustomer, revokeLicense } =
36
- proxyActivities<typeof activities>({
37
- startToCloseTimeout: '1 minute',
38
- retry: {
39
- initialInterval: '1s',
40
- backoffCoefficient: 2,
41
- maximumAttempts: 5,
42
- nonRetryableErrorTypes: ['InvalidCardError', 'AccountSuspendedError'],
43
- },
44
- });
42
+ const redisConnection = new Redis(process.env.REDIS_URL!, {
43
+ maxRetriesPerRequest: null, // Required by BullMQ
44
+ });
45
45
 
46
- export interface SubscriptionWorkflowInput {
47
- customerId: string;
48
- planId: string;
49
- amountCents: number;
46
+ export interface NotificationPayload {
47
+ tenantId: string;
48
+ userId: string;
49
+ type: 'email' | 'webhook';
50
+ payload: Record<string, unknown>;
51
+ idempotencyKey: string;
50
52
  }
51
53
 
52
- /**
53
- * Distributed Subscription Saga with Compensating Rollbacks
54
- */
55
- export async function subscriptionSagaWorkflow(input: SubscriptionWorkflowInput): Promise<{ status: string }> {
56
- const compensations: Array<() => Promise<void>> = [];
57
-
58
- try {
59
- // Step 1: Charge Customer
60
- const chargeResult = await chargeCustomer(input.customerId, input.amountCents);
61
- compensations.unshift(() => refundCustomer(chargeResult.chargeId));
54
+ // Main Queue
55
+ export const notificationQueue = new Queue<NotificationPayload>('notifications', {
56
+ connection: redisConnection,
57
+ defaultJobOptions: {
58
+ attempts: 5,
59
+ backoff: { type: 'exponential', delay: 1500 },
60
+ removeOnComplete: { age: 86400, count: 5000 },
61
+ removeOnFail: false, // Preserved for DLQ audit
62
+ },
63
+ });
62
64
 
63
- // Step 2: Provision License
64
- const licenseResult = await provisionLicense(input.customerId, input.planId);
65
- compensations.unshift(() => revokeLicense(licenseResult.licenseId));
65
+ // Dead Letter Queue
66
+ export const notificationDLQ = new Queue('notifications-dlq', {
67
+ connection: redisConnection,
68
+ });
66
69
 
67
- // Step 3: Send Welcome Notification
68
- await sendWelcomeEmail(input.customerId, licenseResult.licenseKey);
70
+ // Enqueue with deduplication & priority
71
+ export async function enqueueNotification(data: NotificationPayload, isVip = false) {
72
+ return await notificationQueue.add('send_notification', data, {
73
+ jobId: `notif_${data.idempotencyKey}`, // Deterministic dedup key
74
+ priority: isVip ? 1 : 10,
75
+ });
76
+ }
69
77
 
70
- return { status: 'COMPLETED' };
71
- } catch (error) {
72
- // Execute compensating activities in reverse order
73
- for (const compensate of compensations) {
74
- try {
75
- await compensate();
76
- } catch (compError) {
77
- console.error('Compensation failed, alerting on-call engineer:', compError);
78
- }
79
- }
80
- throw ApplicationFailure.create({
81
- message: `Subscription saga failed and rolled back: ${(error as Error).message}`,
82
- nonRetryable: true,
78
+ // Worker with concurrency & rate limiting
79
+ export const notificationWorker = new Worker<NotificationPayload>(
80
+ 'notifications',
81
+ async (job: Job<NotificationPayload>) => {
82
+ if (job.data.type === 'email') await deliverEmail(job.data);
83
+ },
84
+ {
85
+ connection: redisConnection,
86
+ concurrency: 20,
87
+ limiter: { max: 100, duration: 1000 },
88
+ }
89
+ );
90
+
91
+ // DLQ forwarding on retry exhaustion
92
+ notificationWorker.on('failed', async (job, error) => {
93
+ if (job && job.attemptsMade >= (job.opts.attempts || 5)) {
94
+ await notificationDLQ.add('failed_notification', {
95
+ originalJobId: job.id, failedReason: error.message,
96
+ data: job.data, exhaustedAt: new Date().toISOString(),
83
97
  });
84
98
  }
85
- }
99
+ });
86
100
  ```
87
101
 
88
- #### Recipe 2: Trigger.dev v3 Durable Task with Idempotency
102
+ ---
103
+
104
+ ### Tier 2: Trigger.dev v3 — Serverless Durable Tasks
105
+
89
106
  ```typescript
90
107
  import { task } from '@trigger.dev/sdk/v3';
91
108
 
92
- export const generateEnterpriseAnalyticsReport = task({
109
+ export const generateReport = task({
93
110
  id: 'generate-enterprise-report',
94
- retry: {
95
- maxAttempts: 4,
96
- minTimeoutInMs: 2000,
97
- factor: 2,
98
- randomize: true, // Jitter
99
- },
111
+ retry: { maxAttempts: 4, minTimeoutInMs: 2000, factor: 2, randomize: true },
100
112
  run: async (payload: { tenantId: string; month: string }, { ctx }) => {
101
- // Automatic checkpointing: each step runs durably
113
+ // Each step is a durable checkpoint — survives crashes
102
114
  const data = await ctx.run('fetch-telemetry', async () => {
103
115
  return await fetchTelemetryFromWarehouse(payload.tenantId, payload.month);
104
116
  });
105
-
106
117
  const pdfUrl = await ctx.run('render-pdf', async () => {
107
118
  return await generateReportPdf(data);
108
119
  });
109
-
110
120
  await ctx.run('dispatch-webhook', async () => {
111
121
  return await sendWebhookNotification(payload.tenantId, pdfUrl);
112
122
  });
113
-
114
123
  return { success: true, pdfUrl };
115
124
  },
116
125
  });
@@ -118,123 +127,91 @@ export const generateEnterpriseAnalyticsReport = task({
118
127
 
119
128
  ---
120
129
 
121
- ### Implementation Checklist
122
- - [ ] Implement Saga rollback handlers for multi-step distributed payments and user provisioning.
123
- - [ ] Enforce deterministic code inside Temporal workflows (never use `Math.random()`, `Date.now()`, or direct DB calls in workflow files; run them inside activities).
124
- - [ ] Store large payloads in object storage (S3/R2); pass only IDs and signed URLs through queues.
125
- - [ ] Configure DLQ (Dead Letter Queue) and alert thresholds for persistent failures.
126
-
127
- ## Orchestration & Integration
128
- - Integrates with: `js-backend-expert`, `background-jobs-queue-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`.
129
-
130
- ---
131
-
132
- <a name="bahasa-indonesia"></a>
133
- ## Bahasa Indonesia
134
-
135
- ### Tujuan & Gambaran Umum
136
- Panduan arsitektur tingkat produksi untuk merancang pipeline eksekusi background yang tahan-gagal (durable execution), antrean tugas asinkron, dan state machine terdistribusi menggunakan **Temporal.io**, **Trigger.dev v3**, **Inngest**, dan **BullMQ v5**. Menjamin penyelesaian mutlak tugas berdurasi panjang terhadap pembatasan rate limit API, kegagalan worker, dan partisi jaringan.
137
-
138
- ### Kemampuan Utama
139
- 1. **State Machine Tahan-Gagal (Durable Execution)**: Alur kerja (workflow) tetap bertahan saat restart server, deployment, atau gangguan database tanpa kehilangan progres state.
140
- 2. **Pola Transaksi Terdistribusi (Saga Pattern)**: Transaksi multi-langkah yang dilengkapi dengan aktivitas kompensasi (rollback otomatis) jika langkah lanjutan gagal permanen.
141
- 3. **Idempotensi & Anti-Duplikasi**: Menjamin kunci idempotensi unik pada setiap transaksi guna mencegah duplikasi penagihan atau email berulang.
142
- 4. **Pembatasan Rate Limit & DLQ**: Throttling berbasis token bucket, exponential backoff dengan jitter acak, dan dead-letter queue (DLQ) untuk mengisolasi tugas beracun (*poison pills*).
143
-
144
- ---
145
-
146
- ### Resep Implementasi Produksi
130
+ ### Tier 3: Temporal.io — Distributed Saga with Compensations
147
131
 
148
- #### Resep 1: Pola Saga Temporal.io dengan Logika Kompensasi (TypeScript)
149
132
  ```typescript
150
133
  import { proxyActivities, ApplicationFailure } from '@temporalio/workflow';
151
134
  import type * as activities from './activities';
152
135
 
153
- const { tagihPelanggan, aktifkanLisensi, kirimEmailSambutan, kembalikanDana, cabutLisensi } =
136
+ const { chargeCustomer, provisionLicense, sendWelcomeEmail, refundCustomer, revokeLicense } =
154
137
  proxyActivities<typeof activities>({
155
138
  startToCloseTimeout: '1 minute',
156
139
  retry: {
157
- initialInterval: '1s',
158
- backoffCoefficient: 2,
159
- maximumAttempts: 5,
140
+ initialInterval: '1s', backoffCoefficient: 2, maximumAttempts: 5,
141
+ nonRetryableErrorTypes: ['InvalidCardError', 'AccountSuspendedError'],
160
142
  },
161
143
  });
162
144
 
163
- export interface InputWorkflowLangganan {
164
- customerId: string;
165
- planId: string;
166
- amountCents: number;
167
- }
168
-
169
- export async function workflowSagaLangganan(input: InputWorkflowLangganan) {
170
- const kompensasi: Array<() => Promise<void>> = [];
171
-
145
+ export async function subscriptionSagaWorkflow(input: {
146
+ customerId: string; planId: string; amountCents: number;
147
+ }) {
148
+ const compensations: Array<() => Promise<void>> = [];
172
149
  try {
173
- // Langkah 1: Tagih Pembayaran
174
- const hasilTagihan = await tagihPelanggan(input.customerId, input.amountCents);
175
- kompensasi.unshift(() => kembalikanDana(hasilTagihan.chargeId));
176
-
177
- // Langkah 2: Aktifkan Lisensi
178
- const hasilLisensi = await aktifkanLisensi(input.customerId, input.planId);
179
- kompensasi.unshift(() => cabutLisensi(hasilLisensi.licenseId));
150
+ const charge = await chargeCustomer(input.customerId, input.amountCents);
151
+ compensations.unshift(() => refundCustomer(charge.chargeId));
180
152
 
181
- // Langkah 3: Kirim Notifikasi
182
- await kirimEmailSambutan(input.customerId, hasilLisensi.licenseKey);
153
+ const license = await provisionLicense(input.customerId, input.planId);
154
+ compensations.unshift(() => revokeLicense(license.licenseId));
183
155
 
184
- return { status: 'SELESAI' };
156
+ await sendWelcomeEmail(input.customerId, license.licenseKey);
157
+ return { status: 'COMPLETED' };
185
158
  } catch (error) {
186
- // Eksekusi kompensasi rollback secara berurutan mundur
187
- for (const compensate of kompensasi) {
188
- try {
189
- await compensate();
190
- } catch (err) {
191
- console.error('Kompensasi gagal:', err);
192
- }
159
+ for (const compensate of compensations) {
160
+ try { await compensate(); } catch (e) { console.error('Compensation failed:', e); }
193
161
  }
194
162
  throw ApplicationFailure.create({
195
- message: `Saga gagal dan dilakukan rollback: ${(error as Error).message}`,
196
- nonRetryable: true,
163
+ message: `Saga rolled back: ${(error as Error).message}`, nonRetryable: true,
197
164
  });
198
165
  }
199
166
  }
200
167
  ```
201
168
 
202
- #### Resep 2: Tugas Background Tahan-Gagal Trigger.dev v3
203
- ```typescript
204
- import { task } from '@trigger.dev/sdk/v3';
205
-
206
- export const buatLaporanAnalitik = task({
207
- id: 'buat-laporan-analitik',
208
- retry: {
209
- maxAttempts: 4,
210
- factor: 2,
211
- randomize: true, // Jitter
212
- },
213
- run: async (payload: { tenantId: string; bulan: string }, { ctx }) => {
214
- const data = await ctx.run('ambil-data', async () => {
215
- return await ambilDataWarehouse(payload.tenantId, payload.bulan);
216
- });
169
+ > **Temporal Determinism Rule**: Never use `Math.random()`, `Date.now()`, or direct DB calls inside workflow files. Run them inside activities.
217
170
 
218
- const urlPdf = await ctx.run('buat-pdf', async () => {
219
- return await renderDokumenPdf(data);
220
- });
171
+ ---
221
172
 
222
- await ctx.run('kirim-webhook', async () => {
223
- return await notifikasiWebhook(payload.tenantId, urlPdf);
224
- });
173
+ ### Implementation Checklist
174
+ - [ ] Configure `maxRetriesPerRequest: null` on ioredis for BullMQ v5.
175
+ - [ ] Use deterministic `jobId` from business logic (`order_${orderId}`) for deduplication.
176
+ - [ ] Forward permanently dead jobs to DLQ via `worker.on('failed')` listener.
177
+ - [ ] Implement rate limiting via worker `limiter` to protect third-party APIs.
178
+ - [ ] Enforce deterministic code inside Temporal workflows (activities for side-effects).
179
+ - [ ] Store large payloads in S3/R2; pass only IDs through queues.
180
+ - [ ] Implement Saga rollback handlers for multi-step distributed payments.
225
181
 
226
- return { sukses: true, urlPdf };
227
- },
228
- });
229
- ```
182
+ ## Orchestration & Integration
183
+ - Integrates with: `js-backend-expert`, `cron-scheduler-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`, `data-telemetry-expert`.
230
184
 
231
185
  ---
232
186
 
187
+ <a name="bahasa-indonesia"></a>
188
+ ## Bahasa Indonesia
189
+
190
+ ### Tujuan & Gambaran Umum
191
+ Panduan terpadu tingkat produksi untuk pipeline eksekusi latar belakang, antrean job asinkron, dan state machine terdistribusi. Mencakup spektrum penuh dari antrean Redis sederhana hingga saga multi-layanan dengan rollback kompensasi.
192
+
193
+ ### Model Eksekusi 3-Tier
194
+ | Tier | Engine | Cocok Untuk |
195
+ |------|--------|-------------|
196
+ | **Tier 1: Antrean Redis** | BullMQ v5 | Job worker throughput tinggi, prioritas, rate limiting, DLQ |
197
+ | **Tier 2: Task Serverless** | Trigger.dev v3 / Inngest | Task dengan checkpoint, resume otomatis, tanpa infra |
198
+ | **Tier 3: Saga Terdistribusi** | Temporal.io | Orkestrasi multi-layanan, rollback kompensasi, workflow jangka panjang |
199
+
200
+ ### Kemampuan Utama
201
+ 1. **Idempotensi & Deduplikasi**: Kunci `jobId` deterministik mencegah duplikasi penagihan atau email.
202
+ 2. **Dead Letter Queue (DLQ)**: Pemindahan otomatis job gagal total untuk audit.
203
+ 3. **Backoff Eksponensial + Jitter**: Mencegah thundering herd pada server hilir.
204
+ 4. **Prioritas Tenant**: Tier VIP/enterprise mendapat prioritas lebih tinggi (angka lebih kecil di BullMQ).
205
+ 5. **State Machine Tahan-Gagal**: Workflow bertahan saat restart, deployment, dan partisi jaringan.
206
+ 6. **Kompensasi Saga**: Transaksi multi-langkah dengan rollback otomatis urutan mundur.
207
+
233
208
  ### Checklist Implementasi
234
- - [ ] Terapkan penanganan rollback (Saga) untuk alur transaksi pembayaran dan provisi akun bertahap.
235
- - [ ] Pastikan kode di dalam alur Temporal selalu deterministik (jangan gunakan `Math.random()` atau kueri DB langsung di dalam workflow, tempatkan di dalam activities).
236
- - [ ] Pindahkan berkas besar ke S3/R2 dan hanya teruskan referensi ID melalui queue.
237
- - [ ] Pasang konfigurasi DLQ (Dead Letter Queue) dan notifikasi peringatan jika ada job yang macet.
209
+ - [ ] Atur `maxRetriesPerRequest: null` pada ioredis untuk BullMQ v5.
210
+ - [ ] Gunakan `jobId` deterministik dari ID bisnis (`invoice_${invoiceId}`) untuk deduplikasi.
211
+ - [ ] Pasang listener `worker.on('failed')` untuk forward job gagal ke DLQ.
212
+ - [ ] Terapkan rate limiter pada worker untuk stabilitas API eksternal.
213
+ - [ ] Pastikan kode Temporal selalu deterministik (side-effect hanya di activities).
214
+ - [ ] Simpan file besar di S3/R2; kirim hanya referensi ID melalui queue.
238
215
 
239
216
  ## Integrasi Orkestrasi
240
- - Terintegrasi dengan: `js-backend-expert`, `background-jobs-queue-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`.
217
+ - Terintegrasi dengan: `js-backend-expert`, `cron-scheduler-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`, `data-telemetry-expert`.