yadflow 2.6.0 → 2.7.0
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.
- package/CHANGELOG.md +4 -7
- package/README.md +23 -2
- package/bin/yad.mjs +22 -1
- package/cli/docs.mjs +298 -0
- package/cli/manifest.mjs +6 -1
- package/docs/index.html +4 -4
- package/package.json +2 -2
- package/skills/sdlc/config.yaml +19 -0
- package/skills/sdlc/install.sh +1 -1
- package/skills/sdlc/module-help.csv +4 -0
- package/skills/yad-connect-docs/SKILL.md +132 -0
- package/skills/yad-connect-docs/references/docs-registry.md +74 -0
- package/skills/yad-docs/SKILL.md +159 -0
- package/skills/yad-docs/references/data-mapping.md +75 -0
- package/skills/yad-docs/references/theme-map.md +69 -0
- package/skills/yad-docs/templates/app/README.md +31 -0
- package/skills/yad-docs/templates/app/eslint.config.js +23 -0
- package/skills/yad-docs/templates/app/index.html +17 -0
- package/skills/yad-docs/templates/app/package-lock.json +4030 -0
- package/skills/yad-docs/templates/app/package.json +35 -0
- package/skills/yad-docs/templates/app/public/favicon.svg +28 -0
- package/skills/yad-docs/templates/app/public/logo.svg +39 -0
- package/skills/yad-docs/templates/app/public/vite.svg +1 -0
- package/skills/yad-docs/templates/app/src/App.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/Auth/LoginPage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/AnimatedMessage.tsx +101 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/ConnectionLine.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/FlowCanvas.tsx +216 -0
- package/skills/yad-docs/templates/app/src/components/Canvas/SystemComponent.tsx +153 -0
- package/skills/yad-docs/templates/app/src/components/Controls/PlaybackBar.tsx +284 -0
- package/skills/yad-docs/templates/app/src/components/Controls/StepDetail.tsx +167 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/HandlerLogicSnippet.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RequestPayloadPreview.tsx +46 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/RightPanel.tsx +88 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/StatusCard.tsx +76 -0
- package/skills/yad-docs/templates/app/src/components/DetailPanel/TriggerEventCard.tsx +45 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocPageShell.tsx +80 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocSectionCard.tsx +55 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/DocTableOfContents.tsx +79 -0
- package/skills/yad-docs/templates/app/src/components/DocLayout/RoleCard.tsx +67 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ApiReferenceSection.tsx +108 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CancelabilitySection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/CriticalRunbookSection.tsx +177 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DataMigrationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DbSchemaSection.tsx +98 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DeploymentGuideSection.tsx +104 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/DriverIntegrationSection.tsx +127 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/ExecutiveSummarySection.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowOverviewSection.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/FlowPathsChecklistSection.tsx +96 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MiddlewareChainSection.tsx +107 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/MonitoringAlertingSection.tsx +106 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/NotificationLocalizationSection.tsx +102 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PMRoadmapSection.tsx +133 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/PerformanceTestingSection.tsx +91 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/RiderIntegrationSection.tsx +99 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/SecuritySection.tsx +74 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/StatusMachineSection.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/DocSections/TestPlanSection.tsx +163 -0
- package/skills/yad-docs/templates/app/src/components/Logs/SystemLogsTerminal.tsx +126 -0
- package/skills/yad-docs/templates/app/src/components/Navigation/TopNavBar.tsx +90 -0
- package/skills/yad-docs/templates/app/src/components/Reference/BullMQJobsList.tsx +60 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DecisionTreeView.tsx +49 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DeeplinkActionsChips.tsx +69 -0
- package/skills/yad-docs/templates/app/src/components/Reference/DriverUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/FeatureFlagMatrix.tsx +73 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RiderUIStatesTable.tsx +61 -0
- package/skills/yad-docs/templates/app/src/components/Reference/RulesLegendPanel.tsx +217 -0
- package/skills/yad-docs/templates/app/src/components/Reference/StakeholderToggle.tsx +41 -0
- package/skills/yad-docs/templates/app/src/components/Reference/TroubleshootingSection.tsx +93 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/PathSelector.tsx +148 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/SidebarFooter.tsx +40 -0
- package/skills/yad-docs/templates/app/src/components/Sidebar/StepList.tsx +234 -0
- package/skills/yad-docs/templates/app/src/components/shared/Badge.tsx +28 -0
- package/skills/yad-docs/templates/app/src/components/shared/CommandPalette.tsx +213 -0
- package/skills/yad-docs/templates/app/src/components/shared/Icon.tsx +21 -0
- package/skills/yad-docs/templates/app/src/components/shared/Tooltip.tsx +42 -0
- package/skills/yad-docs/templates/app/src/data/components.ts +74 -0
- package/skills/yad-docs/templates/app/src/data/docSections.ts +231 -0
- package/skills/yad-docs/templates/app/src/data/paths.ts +2319 -0
- package/skills/yad-docs/templates/app/src/data/referenceData.ts +392 -0
- package/skills/yad-docs/templates/app/src/data/roles.ts +145 -0
- package/skills/yad-docs/templates/app/src/data/types.ts +79 -0
- package/skills/yad-docs/templates/app/src/hooks/useAnimationQueue.ts +41 -0
- package/skills/yad-docs/templates/app/src/hooks/usePlayback.ts +100 -0
- package/skills/yad-docs/templates/app/src/hooks/useStakeholderFilter.ts +10 -0
- package/skills/yad-docs/templates/app/src/index.css +121 -0
- package/skills/yad-docs/templates/app/src/main.tsx +13 -0
- package/skills/yad-docs/templates/app/src/pages/RoleSelectPage.tsx +34 -0
- package/skills/yad-docs/templates/app/src/pages/StakeholderDocPage.tsx +98 -0
- package/skills/yad-docs/templates/app/src/pages/SubPathDetailPage.tsx +282 -0
- package/skills/yad-docs/templates/app/src/store/useAuthStore.ts +42 -0
- package/skills/yad-docs/templates/app/src/store/useFlowStore.ts +197 -0
- package/skills/yad-docs/templates/app/src/utils/iconMap.ts +46 -0
- package/skills/yad-docs/templates/app/tsconfig.app.json +28 -0
- package/skills/yad-docs/templates/app/tsconfig.json +7 -0
- package/skills/yad-docs/templates/app/tsconfig.node.json +26 -0
- package/skills/yad-docs/templates/app/vite.config.ts +10 -0
- package/skills/yad-docs-overview/SKILL.md +129 -0
- package/skills/yad-docs-overview/references/pipeline-model.md +102 -0
- package/skills/yad-docs-sync/SKILL.md +99 -0
- package/skills/yad-docs-sync/references/staleness.md +81 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import type { StakeholderView } from './types';
|
|
2
|
+
|
|
3
|
+
// ─── Stakeholder-filterable base ───
|
|
4
|
+
|
|
5
|
+
interface Filterable {
|
|
6
|
+
visibleTo: StakeholderView[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ALL: StakeholderView[] = [
|
|
10
|
+
'rider-mobile-dev', 'driver-mobile-dev', 'backend-dev',
|
|
11
|
+
'product-manager', 'engineering-manager', 'staff-engineer', 'qa-engineer',
|
|
12
|
+
];
|
|
13
|
+
const MOBILE: StakeholderView[] = ['rider-mobile-dev', 'driver-mobile-dev'];
|
|
14
|
+
const DEEP_TECH: StakeholderView[] = ['backend-dev', 'staff-engineer', 'qa-engineer'];
|
|
15
|
+
|
|
16
|
+
// ─── Decision Tree ───
|
|
17
|
+
|
|
18
|
+
export interface DecisionBranch {
|
|
19
|
+
condition: string;
|
|
20
|
+
result: string;
|
|
21
|
+
detail?: string;
|
|
22
|
+
visibleTo: StakeholderView[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const DECISION_TREE: DecisionBranch[] = [
|
|
26
|
+
{
|
|
27
|
+
condition: 'ENABLE_DRIVER_CONFIRMATION = false',
|
|
28
|
+
result: 'Push generic history entry, return',
|
|
29
|
+
detail: 'No driver confirmation flow — just records the assignment in booking_status_history',
|
|
30
|
+
visibleTo: ALL,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
condition: 'timeRemaining <= threshold (40 min)',
|
|
34
|
+
result: 'handleFastTrackAssignment',
|
|
35
|
+
detail: 'Auto-confirms driver (BOOK_DRIVER_CONFIRMED), pushes 2 history entries with fast_track reason, publishes DAC, notifies both rider + driver',
|
|
36
|
+
visibleTo: ALL,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
condition: 'timeRemaining > threshold (40 min)',
|
|
40
|
+
result: 'Normal assignment path',
|
|
41
|
+
detail: 'Pushes history entry, schedules PRE_TRIP_DRIVER_CONFIRMATION job, publishes DAC card to driver',
|
|
42
|
+
visibleTo: ALL,
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// ─── Rider UI States ───
|
|
47
|
+
|
|
48
|
+
export interface UIState extends Filterable {
|
|
49
|
+
state: string;
|
|
50
|
+
endpoint: string;
|
|
51
|
+
schemaValue: string;
|
|
52
|
+
isTerminal: boolean;
|
|
53
|
+
description: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const RIDER_UI_STATES: UIState[] = [
|
|
57
|
+
{
|
|
58
|
+
state: 'BOOK_CONFIRMED',
|
|
59
|
+
endpoint: 'PUT /rider/trips/:tripId/booking-status',
|
|
60
|
+
schemaValue: 'BOOK_CONFIRMED',
|
|
61
|
+
isTerminal: false,
|
|
62
|
+
description: 'Rider confirms the scheduled ride',
|
|
63
|
+
visibleTo: ALL,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
state: 'BOOK_UNCONFIRMED',
|
|
67
|
+
endpoint: 'PUT /rider/trips/:tripId/booking-status',
|
|
68
|
+
schemaValue: 'BOOK_UNCONFIRMED',
|
|
69
|
+
isTerminal: false,
|
|
70
|
+
description: 'Rider declines confirmation (maps to BOOK_RIDER_CANCELED)',
|
|
71
|
+
visibleTo: ALL,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
state: 'RIDER_CANCELED',
|
|
75
|
+
endpoint: 'PUT /rider/trips/:tripId/booking-status',
|
|
76
|
+
schemaValue: 'RIDER_CANCELED',
|
|
77
|
+
isTerminal: true,
|
|
78
|
+
description: 'Rider explicitly cancels the booking',
|
|
79
|
+
visibleTo: ALL,
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
export const DRIVER_UI_STATES: UIState[] = [
|
|
84
|
+
{
|
|
85
|
+
state: 'BOOK_ACCEPTED',
|
|
86
|
+
endpoint: 'PUT /b2c/driver/trips/:tripId/booking-status',
|
|
87
|
+
schemaValue: 'BOOK_ACCEPTED',
|
|
88
|
+
isTerminal: false,
|
|
89
|
+
description: 'Driver accepts the scheduled ride',
|
|
90
|
+
visibleTo: ALL,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
state: 'BOOK_DRIVER_CANCELED',
|
|
94
|
+
endpoint: 'PUT /b2c/driver/trips/:tripId/booking-status',
|
|
95
|
+
schemaValue: 'BOOK_DRIVER_CANCELED',
|
|
96
|
+
isTerminal: true,
|
|
97
|
+
description: 'Driver cancels the assigned ride',
|
|
98
|
+
visibleTo: ALL,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
// ─── BullMQ Jobs ───
|
|
103
|
+
|
|
104
|
+
export interface BullMQJob extends Filterable {
|
|
105
|
+
name: string;
|
|
106
|
+
queue: string;
|
|
107
|
+
timing: string;
|
|
108
|
+
description: string;
|
|
109
|
+
triggeredBy: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const BULLMQ_JOBS: BullMQJob[] = [
|
|
113
|
+
{
|
|
114
|
+
name: 'pre-trip-rider-confirmation',
|
|
115
|
+
queue: 'booking-trips',
|
|
116
|
+
timing: 'booked_for - 24h',
|
|
117
|
+
description: 'Sends push notification asking rider to confirm the booking',
|
|
118
|
+
triggeredBy: 'Trip creation (scheduleBookingJobs middleware)',
|
|
119
|
+
visibleTo: ALL,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'rider-confirmation-timeout',
|
|
123
|
+
queue: 'booking-trips',
|
|
124
|
+
timing: '30 min after rider confirmation sent',
|
|
125
|
+
description: 'Escalates to ops if rider has not responded',
|
|
126
|
+
triggeredBy: 'pre-trip-rider-confirmation job completion',
|
|
127
|
+
visibleTo: ALL,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'ops-rider-confirmation-window-timeout',
|
|
131
|
+
queue: 'booking-trips',
|
|
132
|
+
timing: '15 min after rider timeout',
|
|
133
|
+
description: 'System cancels booking if ops did not intervene',
|
|
134
|
+
triggeredBy: 'rider-confirmation-timeout job completion',
|
|
135
|
+
visibleTo: ALL,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: 'pre-trip-driver-confirmation',
|
|
139
|
+
queue: 'booking-trips',
|
|
140
|
+
timing: 'booked_for - 40 min',
|
|
141
|
+
description: 'Sends push notification asking driver to confirm availability',
|
|
142
|
+
triggeredBy: 'handleBookAssigned (normal path)',
|
|
143
|
+
visibleTo: ALL,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: 'driver-confirmation-timeout',
|
|
147
|
+
queue: 'booking-trips',
|
|
148
|
+
timing: '5 min after driver confirmation sent',
|
|
149
|
+
description: 'Escalates to ops if driver has not responded',
|
|
150
|
+
triggeredBy: 'pre-trip-driver-confirmation job completion',
|
|
151
|
+
visibleTo: ALL,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'ops-driver-confirmation-window-timeout',
|
|
155
|
+
queue: 'booking-trips',
|
|
156
|
+
timing: '10 min after driver timeout',
|
|
157
|
+
description: 'System cancels booking if ops did not intervene',
|
|
158
|
+
triggeredBy: 'driver-confirmation-timeout job completion',
|
|
159
|
+
visibleTo: ALL,
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
// ─── Feature Flags ───
|
|
164
|
+
|
|
165
|
+
export interface FeatureFlag extends Filterable {
|
|
166
|
+
name: string;
|
|
167
|
+
envVar: string;
|
|
168
|
+
defaultValue: boolean;
|
|
169
|
+
stagingValue: boolean;
|
|
170
|
+
productionValue: boolean;
|
|
171
|
+
description: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export const FEATURE_FLAGS: FeatureFlag[] = [
|
|
175
|
+
{
|
|
176
|
+
name: 'ENABLE_BOOKING_JOBS',
|
|
177
|
+
envVar: 'ENABLE_BOOKING_JOBS',
|
|
178
|
+
defaultValue: false,
|
|
179
|
+
stagingValue: true,
|
|
180
|
+
productionValue: false,
|
|
181
|
+
description: 'Master switch for all booking-related BullMQ jobs. When false, no scheduled jobs fire.',
|
|
182
|
+
visibleTo: ALL,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: 'ENABLE_PRE_TRIP_RIDER_CONFIRMATION',
|
|
186
|
+
envVar: 'ENABLE_PRE_TRIP_RIDER_CONFIRMATION',
|
|
187
|
+
defaultValue: false,
|
|
188
|
+
stagingValue: true,
|
|
189
|
+
productionValue: false,
|
|
190
|
+
description: 'Enables the pre-trip rider confirmation flow (24h before booked_for).',
|
|
191
|
+
visibleTo: ALL,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'ENABLE_DRIVER_CONFIRMATION',
|
|
195
|
+
envVar: 'ENABLE_DRIVER_CONFIRMATION',
|
|
196
|
+
defaultValue: false,
|
|
197
|
+
stagingValue: false,
|
|
198
|
+
productionValue: false,
|
|
199
|
+
description: 'Enables driver confirmation flow within fnUpdateBookingStatus. Controls fast-track vs normal path on assignment.',
|
|
200
|
+
visibleTo: ALL,
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
// ─── Deeplink Actions ───
|
|
205
|
+
|
|
206
|
+
export interface DeeplinkAction extends Filterable {
|
|
207
|
+
constant: string;
|
|
208
|
+
value: string;
|
|
209
|
+
target: 'rider' | 'driver';
|
|
210
|
+
category: string;
|
|
211
|
+
description: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export const DEEPLINK_ACTIONS: DeeplinkAction[] = [
|
|
215
|
+
{
|
|
216
|
+
constant: 'CONFIRM_BOOKING',
|
|
217
|
+
value: 'confirm_booking',
|
|
218
|
+
target: 'rider',
|
|
219
|
+
category: 'booking_confirmation',
|
|
220
|
+
description: 'Opens rider app to confirm scheduled ride',
|
|
221
|
+
visibleTo: ALL,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
constant: 'BOOKING_TIMEOUT',
|
|
225
|
+
value: 'booking_timeout',
|
|
226
|
+
target: 'rider',
|
|
227
|
+
category: 'booking_timeout',
|
|
228
|
+
description: 'Rider confirmation timeout notification',
|
|
229
|
+
visibleTo: ALL,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
constant: 'BOOKING_CANCELLED',
|
|
233
|
+
value: 'booking_cancelled',
|
|
234
|
+
target: 'rider',
|
|
235
|
+
category: 'booking_ops_window_timeout_cancellation',
|
|
236
|
+
description: 'System/ops cancelled the booking',
|
|
237
|
+
visibleTo: ALL,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
constant: 'BOOKING_CANCELED_BY_RIDER',
|
|
241
|
+
value: 'booking_canceled_by_rider',
|
|
242
|
+
target: 'driver',
|
|
243
|
+
category: 'booking_rider_cancellation',
|
|
244
|
+
description: 'Notifies driver that rider cancelled',
|
|
245
|
+
visibleTo: ALL,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
constant: 'CONFIRM_DRIVER_BOOKING',
|
|
249
|
+
value: 'confirm_driver_booking',
|
|
250
|
+
target: 'driver',
|
|
251
|
+
category: 'driver_booking_confirmation',
|
|
252
|
+
description: 'Opens driver app to confirm availability',
|
|
253
|
+
visibleTo: ALL,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
constant: 'DRIVER_BOOKING_TIMEOUT',
|
|
257
|
+
value: 'driver_booking_timeout',
|
|
258
|
+
target: 'driver',
|
|
259
|
+
category: 'driver_booking_timeout',
|
|
260
|
+
description: 'Driver confirmation timeout notification',
|
|
261
|
+
visibleTo: ALL,
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
constant: 'DRIVER_BOOKING_OPS_CANCELLED',
|
|
265
|
+
value: 'driver_booking_ops_cancelled',
|
|
266
|
+
target: 'driver',
|
|
267
|
+
category: 'driver_booking_ops_window_timeout_cancellation',
|
|
268
|
+
description: 'Ops cancelled the driver assignment',
|
|
269
|
+
visibleTo: ALL,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
constant: 'BOOKING_DRIVER_ASSIGNED',
|
|
273
|
+
value: 'booking_driver_assigned',
|
|
274
|
+
target: 'driver',
|
|
275
|
+
category: 'booking_driver_assignment',
|
|
276
|
+
description: 'Notifies driver of new scheduled ride assignment',
|
|
277
|
+
visibleTo: ALL,
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
constant: 'BOOKING_DRIVER_ASSIGNED_RIDER',
|
|
281
|
+
value: 'booking_driver_assigned_rider',
|
|
282
|
+
target: 'rider',
|
|
283
|
+
category: 'booking_driver_assignment',
|
|
284
|
+
description: 'Notifies rider that a driver has been assigned',
|
|
285
|
+
visibleTo: ALL,
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
constant: 'BOOKING_CANCELED_BY_DRIVER',
|
|
289
|
+
value: 'booking_canceled_by_driver',
|
|
290
|
+
target: 'rider',
|
|
291
|
+
category: 'booking_driver_cancellation',
|
|
292
|
+
description: 'Notifies rider that driver cancelled',
|
|
293
|
+
visibleTo: ALL,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
constant: 'BOOKING_DRIVER_CONFIRMED_RIDER',
|
|
297
|
+
value: 'booking_driver_confirmed_rider',
|
|
298
|
+
target: 'rider',
|
|
299
|
+
category: 'booking_driver_assignment',
|
|
300
|
+
description: 'Notifies rider that driver confirmed the ride',
|
|
301
|
+
visibleTo: ALL,
|
|
302
|
+
},
|
|
303
|
+
];
|
|
304
|
+
|
|
305
|
+
// ─── Error Codes / Troubleshooting ───
|
|
306
|
+
|
|
307
|
+
export interface ErrorCode extends Filterable {
|
|
308
|
+
code: string;
|
|
309
|
+
httpStatus?: number;
|
|
310
|
+
cause: string;
|
|
311
|
+
resolution: string;
|
|
312
|
+
severity: 'info' | 'warn' | 'critical';
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export const ERROR_CODES: ErrorCode[] = [
|
|
316
|
+
{
|
|
317
|
+
code: 'CONCURRENT_UPDATE (modifiedCount: 0)',
|
|
318
|
+
httpStatus: 409,
|
|
319
|
+
cause: 'Optimistic lock failure — another request modified the booking_status between read and write',
|
|
320
|
+
resolution: 'Retry the modification or refresh state. The middleware skips silently when modifiedCount is 0.',
|
|
321
|
+
severity: 'warn',
|
|
322
|
+
visibleTo: ALL,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
code: 'INVALID_BOOKING_STATUS_TRANSITION',
|
|
326
|
+
httpStatus: 409,
|
|
327
|
+
cause: 'Attempted transition not in VALID_RIDER_TRANSITIONS or VALID_DRIVER_TRANSITIONS map',
|
|
328
|
+
resolution: 'Check current booking_status and verify the transition is allowed. See Section 4.3/4.4 of documentation.',
|
|
329
|
+
severity: 'critical',
|
|
330
|
+
visibleTo: ALL,
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
code: 'NOT_A_BOOKED_TRIP',
|
|
334
|
+
httpStatus: 404,
|
|
335
|
+
cause: 'Trip exists but is_booked is false — booking endpoints only work for scheduled rides',
|
|
336
|
+
resolution: 'Verify the trip was created with is_booked: true and booked_for fields.',
|
|
337
|
+
severity: 'info',
|
|
338
|
+
visibleTo: ALL,
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
code: 'TRIP_NOT_CANCELABLE',
|
|
342
|
+
httpStatus: 409,
|
|
343
|
+
cause: 'Trip status is DRIVER_ARRIVED, STARTED, or FINISHED — rider cannot cancel at this stage',
|
|
344
|
+
resolution: 'This is expected behavior. The trip has progressed past the cancelable window.',
|
|
345
|
+
severity: 'info',
|
|
346
|
+
visibleTo: ALL,
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
code: 'BullMQ Job Not Found',
|
|
350
|
+
cause: 'Cleanup attempted to remove a job that doesn\'t exist (already processed or never scheduled)',
|
|
351
|
+
resolution: 'Safe to ignore — cleanup functions are fire-and-forget with .catch(log). Verify feature flags are enabled.',
|
|
352
|
+
severity: 'warn',
|
|
353
|
+
visibleTo: DEEP_TECH,
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
code: 'DAC Publish/Delete Failed',
|
|
357
|
+
cause: 'Google Cloud Pub/Sub connectivity issue or topic misconfiguration',
|
|
358
|
+
resolution: 'Check PUB_SUB_DRIVER_ACTIONS_TOPIC env var and GCP credentials. DAC operations are fire-and-forget.',
|
|
359
|
+
severity: 'critical',
|
|
360
|
+
visibleTo: DEEP_TECH,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
code: 'Notification Send Failed',
|
|
364
|
+
cause: 'FCM/APNS delivery failure or missing device token',
|
|
365
|
+
resolution: 'Check notification service logs. sendBookingNotificationWithConfig wraps errors with .catch(log) — won\'t block the response.',
|
|
366
|
+
severity: 'warn',
|
|
367
|
+
visibleTo: [...MOBILE, 'backend-dev', 'staff-engineer'],
|
|
368
|
+
},
|
|
369
|
+
];
|
|
370
|
+
|
|
371
|
+
// ─── Status Mapping (for reference display) ───
|
|
372
|
+
|
|
373
|
+
export interface StatusMapping extends Filterable {
|
|
374
|
+
tripStatus: string;
|
|
375
|
+
bookingStatus: string;
|
|
376
|
+
category: string;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export const STATUS_MAPPINGS: StatusMapping[] = [
|
|
380
|
+
{ tripStatus: 'TRIP_FINISHED', bookingStatus: 'TRIP_BOOK_FINISHED', category: 'Completion', visibleTo: ALL },
|
|
381
|
+
{ tripStatus: 'TRIP_RIDER_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_RIDER_CANCELED', category: 'Rider cancel', visibleTo: ALL },
|
|
382
|
+
{ tripStatus: 'TRIP_DRIVER_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CANCELED', category: 'Driver cancel', visibleTo: ALL },
|
|
383
|
+
{ tripStatus: 'TRIP_DRIVER_CANCELED_TIMEOUT', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CANCELED', category: 'Driver cancel', visibleTo: ALL },
|
|
384
|
+
{ tripStatus: 'TRIP_NO_DRIVER_AVAILABLE', bookingStatus: 'TRIP_BOOK_SYSTEM_CANCELED', category: 'System cancel', visibleTo: ALL },
|
|
385
|
+
{ tripStatus: 'TRIP_DRIVER_COMING_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CANCELED', category: 'Active trip cancel', visibleTo: ALL },
|
|
386
|
+
{ tripStatus: 'TRIP_DRIVER_COMING_RIDER_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_RIDER_CANCELED', category: 'Active trip cancel', visibleTo: ALL },
|
|
387
|
+
{ tripStatus: 'TRIP_DRIVER_ARRIVED_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CANCELED', category: 'Active trip cancel', visibleTo: ALL },
|
|
388
|
+
{ tripStatus: 'TRIP_DRIVER_ARRIVED_RIDER_CANCELED', bookingStatus: 'TRIP_BOOK_OPERATION_RIDER_CANCELED', category: 'Active trip cancel', visibleTo: ALL },
|
|
389
|
+
{ tripStatus: 'TRIP_BOOK_DECLINED', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CANCELED', category: 'Driver cancel', visibleTo: ALL },
|
|
390
|
+
{ tripStatus: 'TRIP_BOOK_ACCEPTED', bookingStatus: 'TRIP_BOOK_OPERATION_DRIVER_CONFIRMED', category: 'Driver confirm', visibleTo: ALL },
|
|
391
|
+
{ tripStatus: 'TRIP_BOOK_ASSIGNED', bookingStatus: 'TRIP_BOOK_RIDER_CONFIRMED', category: 'Assignment (special)', visibleTo: ALL },
|
|
392
|
+
];
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { StakeholderView } from './types';
|
|
2
|
+
|
|
3
|
+
export interface RoleConfig {
|
|
4
|
+
slug: StakeholderView;
|
|
5
|
+
label: string;
|
|
6
|
+
shortLabel: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: string;
|
|
9
|
+
description: string;
|
|
10
|
+
sectionIds: string[];
|
|
11
|
+
relevantPathIds: number[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ROLES: RoleConfig[] = [
|
|
15
|
+
{
|
|
16
|
+
slug: 'rider-mobile-dev',
|
|
17
|
+
label: 'Rider Mobile Developer',
|
|
18
|
+
shortLabel: 'Rider Dev',
|
|
19
|
+
icon: 'phone_iphone',
|
|
20
|
+
color: '#7b59e6',
|
|
21
|
+
description: 'Integration guide for rider app — booking status endpoints, UI states, deeplink actions, and notification payloads.',
|
|
22
|
+
sectionIds: [
|
|
23
|
+
'rider-integration',
|
|
24
|
+
'rider-ui-states',
|
|
25
|
+
'deeplinks',
|
|
26
|
+
'notification-localization',
|
|
27
|
+
'cancelability',
|
|
28
|
+
'troubleshooting',
|
|
29
|
+
],
|
|
30
|
+
relevantPathIds: [1, 2, 3, 4, 5, 6, 9, 10, 11],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
slug: 'driver-mobile-dev',
|
|
34
|
+
label: 'Driver Mobile Developer',
|
|
35
|
+
shortLabel: 'Driver Dev',
|
|
36
|
+
icon: 'directions_car',
|
|
37
|
+
color: '#06b6d4',
|
|
38
|
+
description: 'Integration guide for driver app — booking status endpoints, DAC cards, confirmation flows, and push notifications.',
|
|
39
|
+
sectionIds: [
|
|
40
|
+
'driver-integration',
|
|
41
|
+
'driver-ui-states',
|
|
42
|
+
'deeplinks',
|
|
43
|
+
'notification-localization',
|
|
44
|
+
'cancelability',
|
|
45
|
+
'troubleshooting',
|
|
46
|
+
],
|
|
47
|
+
relevantPathIds: [1, 7, 8, 9, 10, 11],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
slug: 'backend-dev',
|
|
51
|
+
label: 'Backend Developer',
|
|
52
|
+
shortLabel: 'Backend',
|
|
53
|
+
icon: 'terminal',
|
|
54
|
+
color: '#10b981',
|
|
55
|
+
description: 'API reference, middleware chains, status machine, database schema, BullMQ jobs, deployment, and security.',
|
|
56
|
+
sectionIds: [
|
|
57
|
+
'api-reference',
|
|
58
|
+
'status-machine',
|
|
59
|
+
'middleware-chain',
|
|
60
|
+
'decision-tree',
|
|
61
|
+
'bullmq-jobs',
|
|
62
|
+
'db-schema',
|
|
63
|
+
'deployment',
|
|
64
|
+
'security',
|
|
65
|
+
'troubleshooting',
|
|
66
|
+
],
|
|
67
|
+
relevantPathIds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
slug: 'product-manager',
|
|
71
|
+
label: 'Product Manager',
|
|
72
|
+
shortLabel: 'PM',
|
|
73
|
+
icon: 'bar_chart',
|
|
74
|
+
color: '#f59e0b',
|
|
75
|
+
description: 'Executive summary, feature overview, flow paths, feature flags, cancelability rules, and product roadmap.',
|
|
76
|
+
sectionIds: [
|
|
77
|
+
'executive-summary',
|
|
78
|
+
'flow-overview',
|
|
79
|
+
'cancelability',
|
|
80
|
+
'feature-flags',
|
|
81
|
+
'pm-roadmap',
|
|
82
|
+
],
|
|
83
|
+
relevantPathIds: [1, 2, 3, 9, 10],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
slug: 'engineering-manager',
|
|
87
|
+
label: 'Engineering Manager',
|
|
88
|
+
shortLabel: 'EM',
|
|
89
|
+
icon: 'groups',
|
|
90
|
+
color: '#8b5cf6',
|
|
91
|
+
description: 'Executive summary, deployment guide, monitoring & alerting, performance testing, and critical runbook.',
|
|
92
|
+
sectionIds: [
|
|
93
|
+
'executive-summary',
|
|
94
|
+
'flow-overview',
|
|
95
|
+
'deployment',
|
|
96
|
+
'monitoring-alerting',
|
|
97
|
+
'performance-testing',
|
|
98
|
+
'critical-runbook',
|
|
99
|
+
],
|
|
100
|
+
relevantPathIds: [1, 2, 3, 9, 10],
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
slug: 'staff-engineer',
|
|
104
|
+
label: 'Staff Engineer',
|
|
105
|
+
shortLabel: 'Staff Eng',
|
|
106
|
+
icon: 'engineering',
|
|
107
|
+
color: '#ec4899',
|
|
108
|
+
description: 'Deep-dive into status machine, middleware architecture, decision tree, data migration, security, and performance.',
|
|
109
|
+
sectionIds: [
|
|
110
|
+
'status-machine',
|
|
111
|
+
'middleware-chain',
|
|
112
|
+
'decision-tree',
|
|
113
|
+
'api-reference',
|
|
114
|
+
'bullmq-jobs',
|
|
115
|
+
'feature-flags',
|
|
116
|
+
'data-migration',
|
|
117
|
+
'security',
|
|
118
|
+
'performance-testing',
|
|
119
|
+
'db-schema',
|
|
120
|
+
'troubleshooting',
|
|
121
|
+
],
|
|
122
|
+
relevantPathIds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
slug: 'qa-engineer',
|
|
126
|
+
label: 'QA Engineer',
|
|
127
|
+
shortLabel: 'QA',
|
|
128
|
+
icon: 'bug_report',
|
|
129
|
+
color: '#ef4444',
|
|
130
|
+
description: 'Test plan, feature flag matrix, error codes, flow path checklist, and troubleshooting guide.',
|
|
131
|
+
sectionIds: [
|
|
132
|
+
'test-plan',
|
|
133
|
+
'flow-paths-checklist',
|
|
134
|
+
'feature-flags',
|
|
135
|
+
'error-codes',
|
|
136
|
+
'cancelability',
|
|
137
|
+
'troubleshooting',
|
|
138
|
+
],
|
|
139
|
+
relevantPathIds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
export function getRoleBySlug(slug: string): RoleConfig | undefined {
|
|
144
|
+
return ROLES.find((r) => r.slug === slug);
|
|
145
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export type StakeholderView =
|
|
2
|
+
| "rider-mobile-dev"
|
|
3
|
+
| "driver-mobile-dev"
|
|
4
|
+
| "backend-dev"
|
|
5
|
+
| "product-manager"
|
|
6
|
+
| "engineering-manager"
|
|
7
|
+
| "staff-engineer"
|
|
8
|
+
| "qa-engineer";
|
|
9
|
+
|
|
10
|
+
export type MessageType = "request" | "response" | "event" | "job" | "notification" | "cleanup";
|
|
11
|
+
|
|
12
|
+
export type ActorType = "rider" | "driver" | "ops" | "system";
|
|
13
|
+
|
|
14
|
+
export type PathCategory = "success" | "rider-cancel" | "driver-cancel" | "timeout" | "ops" | "active-cancel";
|
|
15
|
+
|
|
16
|
+
export type PlaybackState = "idle" | "playing" | "paused";
|
|
17
|
+
|
|
18
|
+
export interface SystemComponent {
|
|
19
|
+
id: string;
|
|
20
|
+
label: string;
|
|
21
|
+
icon: string;
|
|
22
|
+
color: string;
|
|
23
|
+
position: { x: number; y: number };
|
|
24
|
+
description: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AnimatedMessage {
|
|
28
|
+
id: string;
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
label: string;
|
|
32
|
+
type: MessageType;
|
|
33
|
+
color: string;
|
|
34
|
+
delay: number;
|
|
35
|
+
duration: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface FlowStep {
|
|
39
|
+
id: string;
|
|
40
|
+
title: string;
|
|
41
|
+
description: string;
|
|
42
|
+
actor: ActorType;
|
|
43
|
+
status: string;
|
|
44
|
+
bookingStatus: string;
|
|
45
|
+
trigger: string;
|
|
46
|
+
handler: string;
|
|
47
|
+
messages: AnimatedMessage[];
|
|
48
|
+
activeComponents: string[];
|
|
49
|
+
sideEffects: {
|
|
50
|
+
jobs?: string;
|
|
51
|
+
notifications?: string;
|
|
52
|
+
dac?: string;
|
|
53
|
+
pubsub?: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface FlowPath {
|
|
58
|
+
id: number;
|
|
59
|
+
label: string;
|
|
60
|
+
icon: string;
|
|
61
|
+
color: string;
|
|
62
|
+
description: string;
|
|
63
|
+
category: PathCategory;
|
|
64
|
+
steps: FlowStep[];
|
|
65
|
+
subPaths?: {
|
|
66
|
+
id: string;
|
|
67
|
+
label: string;
|
|
68
|
+
steps: FlowStep[];
|
|
69
|
+
}[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const MESSAGE_COLORS: Record<MessageType, string> = {
|
|
73
|
+
request: "#7b59e6",
|
|
74
|
+
response: "#06b6d4",
|
|
75
|
+
event: "#10b981",
|
|
76
|
+
job: "#f59e0b",
|
|
77
|
+
notification: "#fb2576",
|
|
78
|
+
cleanup: "#ef4444",
|
|
79
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from "react";
|
|
2
|
+
import { useFlowStore } from "../store/useFlowStore";
|
|
3
|
+
|
|
4
|
+
export function useAnimationQueue() {
|
|
5
|
+
const activeStepIndex = useFlowStore((s) => s.activeStepIndex);
|
|
6
|
+
const speed = useFlowStore((s) => s.speed);
|
|
7
|
+
|
|
8
|
+
const [completedTargets, setCompletedTargets] = useState<Set<string>>(new Set());
|
|
9
|
+
const [animKey, setAnimKey] = useState(0);
|
|
10
|
+
const timersRef = useRef<ReturnType<typeof setTimeout>[]>([]);
|
|
11
|
+
|
|
12
|
+
// When step changes, reset and schedule completion events
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
// Clear previous timers
|
|
15
|
+
timersRef.current.forEach(clearTimeout);
|
|
16
|
+
timersRef.current = [];
|
|
17
|
+
setCompletedTargets(new Set());
|
|
18
|
+
setAnimKey((k) => k + 1);
|
|
19
|
+
|
|
20
|
+
// Get messages from the current step
|
|
21
|
+
const step = useFlowStore.getState().getCurrentStep();
|
|
22
|
+
const messages = step?.messages || [];
|
|
23
|
+
|
|
24
|
+
if (messages.length === 0) return;
|
|
25
|
+
|
|
26
|
+
// Schedule completion events for target pulse effect
|
|
27
|
+
for (const msg of messages) {
|
|
28
|
+
const timer = setTimeout(() => {
|
|
29
|
+
setCompletedTargets((prev) => new Set(prev).add(msg.to));
|
|
30
|
+
}, (msg.delay + msg.duration) / speed);
|
|
31
|
+
timersRef.current.push(timer);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return () => {
|
|
35
|
+
timersRef.current.forEach(clearTimeout);
|
|
36
|
+
timersRef.current = [];
|
|
37
|
+
};
|
|
38
|
+
}, [activeStepIndex, speed]);
|
|
39
|
+
|
|
40
|
+
return { completedTargets, animKey, speed };
|
|
41
|
+
}
|