@brunosps00/dev-workflow 0.0.5 → 0.0.7

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 (166) hide show
  1. package/bin/dev-workflow.js +6 -4
  2. package/lib/constants.js +11 -0
  3. package/lib/init.js +36 -12
  4. package/lib/wrappers.js +8 -2
  5. package/package.json +1 -1
  6. package/scaffold/pt-br/commands/dw-analyze-project.md +3 -3
  7. package/scaffold/pt-br/commands/dw-bugfix.md +6 -6
  8. package/scaffold/pt-br/commands/dw-code-review.md +2 -2
  9. package/scaffold/pt-br/commands/dw-create-tasks.md +4 -4
  10. package/scaffold/pt-br/commands/dw-generate-pr.md +3 -3
  11. package/scaffold/pt-br/commands/dw-help.md +50 -50
  12. package/scaffold/pt-br/commands/dw-review-implementation.md +3 -3
  13. package/scaffold/pt-br/commands/dw-run-plan.md +8 -8
  14. package/scaffold/pt-br/commands/dw-run-task.md +3 -3
  15. package/scaffold/pt-br/templates/tasks-template.md +2 -2
  16. package/scaffold/skills/agent-browser/SKILL.md +750 -0
  17. package/scaffold/skills/agent-browser/references/authentication.md +303 -0
  18. package/scaffold/skills/agent-browser/references/commands.md +295 -0
  19. package/scaffold/skills/agent-browser/references/profiling.md +120 -0
  20. package/scaffold/skills/agent-browser/references/proxy-support.md +194 -0
  21. package/scaffold/skills/agent-browser/references/session-management.md +193 -0
  22. package/scaffold/skills/agent-browser/references/snapshot-refs.md +219 -0
  23. package/scaffold/skills/agent-browser/references/video-recording.md +173 -0
  24. package/scaffold/skills/agent-browser/templates/authenticated-session.sh +105 -0
  25. package/scaffold/skills/agent-browser/templates/capture-workflow.sh +69 -0
  26. package/scaffold/skills/agent-browser/templates/form-automation.sh +62 -0
  27. package/scaffold/skills/humanizer/README.md +143 -0
  28. package/scaffold/skills/humanizer/SKILL.md +488 -0
  29. package/scaffold/skills/humanizer/WARP.md +53 -0
  30. package/scaffold/skills/remotion-best-practices/SKILL.md +61 -0
  31. package/scaffold/skills/remotion-best-practices/rules/3d.md +86 -0
  32. package/scaffold/skills/remotion-best-practices/rules/animations.md +27 -0
  33. package/scaffold/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  34. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  35. package/scaffold/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  36. package/scaffold/skills/remotion-best-practices/rules/assets.md +78 -0
  37. package/scaffold/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  38. package/scaffold/skills/remotion-best-practices/rules/audio.md +169 -0
  39. package/scaffold/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
  40. package/scaffold/skills/remotion-best-practices/rules/can-decode.md +75 -0
  41. package/scaffold/skills/remotion-best-practices/rules/charts.md +120 -0
  42. package/scaffold/skills/remotion-best-practices/rules/compositions.md +154 -0
  43. package/scaffold/skills/remotion-best-practices/rules/display-captions.md +184 -0
  44. package/scaffold/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  45. package/scaffold/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  46. package/scaffold/skills/remotion-best-practices/rules/fonts.md +152 -0
  47. package/scaffold/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  48. package/scaffold/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  49. package/scaffold/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  50. package/scaffold/skills/remotion-best-practices/rules/gifs.md +141 -0
  51. package/scaffold/skills/remotion-best-practices/rules/images.md +134 -0
  52. package/scaffold/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  53. package/scaffold/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  54. package/scaffold/skills/remotion-best-practices/rules/lottie.md +70 -0
  55. package/scaffold/skills/remotion-best-practices/rules/maps.md +412 -0
  56. package/scaffold/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  57. package/scaffold/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  58. package/scaffold/skills/remotion-best-practices/rules/parameters.md +109 -0
  59. package/scaffold/skills/remotion-best-practices/rules/sequencing.md +118 -0
  60. package/scaffold/skills/remotion-best-practices/rules/sfx.md +26 -0
  61. package/scaffold/skills/remotion-best-practices/rules/subtitles.md +36 -0
  62. package/scaffold/skills/remotion-best-practices/rules/tailwind.md +11 -0
  63. package/scaffold/skills/remotion-best-practices/rules/text-animations.md +20 -0
  64. package/scaffold/skills/remotion-best-practices/rules/timing.md +179 -0
  65. package/scaffold/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  66. package/scaffold/skills/remotion-best-practices/rules/transitions.md +197 -0
  67. package/scaffold/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  68. package/scaffold/skills/remotion-best-practices/rules/trimming.md +51 -0
  69. package/scaffold/skills/remotion-best-practices/rules/videos.md +171 -0
  70. package/scaffold/skills/remotion-best-practices/rules/voiceover.md +99 -0
  71. package/scaffold/skills/security-review/LICENSE +22 -0
  72. package/scaffold/skills/security-review/SKILL.md +312 -0
  73. package/scaffold/skills/security-review/infrastructure/docker.md +432 -0
  74. package/scaffold/skills/security-review/languages/javascript.md +388 -0
  75. package/scaffold/skills/security-review/languages/python.md +363 -0
  76. package/scaffold/skills/security-review/references/api-security.md +519 -0
  77. package/scaffold/skills/security-review/references/authentication.md +353 -0
  78. package/scaffold/skills/security-review/references/authorization.md +372 -0
  79. package/scaffold/skills/security-review/references/business-logic.md +443 -0
  80. package/scaffold/skills/security-review/references/cryptography.md +329 -0
  81. package/scaffold/skills/security-review/references/csrf.md +398 -0
  82. package/scaffold/skills/security-review/references/data-protection.md +378 -0
  83. package/scaffold/skills/security-review/references/deserialization.md +410 -0
  84. package/scaffold/skills/security-review/references/error-handling.md +436 -0
  85. package/scaffold/skills/security-review/references/file-security.md +457 -0
  86. package/scaffold/skills/security-review/references/injection.md +259 -0
  87. package/scaffold/skills/security-review/references/logging.md +433 -0
  88. package/scaffold/skills/security-review/references/misconfiguration.md +435 -0
  89. package/scaffold/skills/security-review/references/modern-threats.md +475 -0
  90. package/scaffold/skills/security-review/references/ssrf.md +415 -0
  91. package/scaffold/skills/security-review/references/supply-chain.md +405 -0
  92. package/scaffold/skills/security-review/references/xss.md +336 -0
  93. package/scaffold/skills/vercel-react-best-practices/AGENTS.md +3648 -0
  94. package/scaffold/skills/vercel-react-best-practices/README.md +123 -0
  95. package/scaffold/skills/vercel-react-best-practices/SKILL.md +146 -0
  96. package/scaffold/skills/vercel-react-best-practices/rules/_sections.md +46 -0
  97. package/scaffold/skills/vercel-react-best-practices/rules/_template.md +28 -0
  98. package/scaffold/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  99. package/scaffold/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  100. package/scaffold/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  101. package/scaffold/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  102. package/scaffold/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  103. package/scaffold/skills/vercel-react-best-practices/rules/async-defer-await.md +82 -0
  104. package/scaffold/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  105. package/scaffold/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  106. package/scaffold/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  107. package/scaffold/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
  108. package/scaffold/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  109. package/scaffold/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  110. package/scaffold/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  111. package/scaffold/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  112. package/scaffold/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  113. package/scaffold/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  114. package/scaffold/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  115. package/scaffold/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  116. package/scaffold/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  117. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  118. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  119. package/scaffold/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  120. package/scaffold/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  121. package/scaffold/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  122. package/scaffold/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
  123. package/scaffold/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  124. package/scaffold/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  125. package/scaffold/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  126. package/scaffold/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  127. package/scaffold/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
  128. package/scaffold/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  129. package/scaffold/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  130. package/scaffold/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  131. package/scaffold/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  132. package/scaffold/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  133. package/scaffold/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  134. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  135. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  136. package/scaffold/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  137. package/scaffold/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
  138. package/scaffold/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
  139. package/scaffold/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  140. package/scaffold/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  141. package/scaffold/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  142. package/scaffold/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  143. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  144. package/scaffold/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  145. package/scaffold/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  146. package/scaffold/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  147. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  148. package/scaffold/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  149. package/scaffold/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  150. package/scaffold/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
  151. package/scaffold/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  152. package/scaffold/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  153. package/scaffold/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  154. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  155. package/scaffold/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  156. package/scaffold/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  157. package/scaffold/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  158. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  159. package/scaffold/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  160. package/scaffold/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  161. package/scaffold/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
  162. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  163. package/scaffold/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
  164. package/scaffold/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  165. package/scaffold/skills/webapp-testing/SKILL.md +133 -0
  166. package/scaffold/skills/webapp-testing/assets/test-helper.js +56 -0
@@ -0,0 +1,443 @@
1
+ # Business Logic Security Reference
2
+
3
+ ## Overview
4
+
5
+ Business logic vulnerabilities occur when the application's logic can be manipulated to achieve unintended outcomes. Unlike technical vulnerabilities, these flaws exploit legitimate functionality in unexpected ways.
6
+
7
+ ## Common Vulnerability Types
8
+
9
+ ### 1. Race Conditions
10
+
11
+ #### Time-of-Check to Time-of-Use (TOCTOU)
12
+
13
+ ```python
14
+ # VULNERABLE: Race condition in balance check
15
+ def transfer(from_account, to_account, amount):
16
+ if from_account.balance >= amount: # Check
17
+ time.sleep(0.1) # Simulating processing delay
18
+ from_account.balance -= amount # Use
19
+ to_account.balance += amount
20
+
21
+ # Attack: Two concurrent transfers can overdraft
22
+
23
+ # SAFE: Atomic operation with locking
24
+ from threading import Lock
25
+
26
+ account_locks = {}
27
+
28
+ def transfer(from_account, to_account, amount):
29
+ # Acquire locks in consistent order to prevent deadlock
30
+ locks = sorted([from_account.id, to_account.id])
31
+ with account_locks[locks[0]], account_locks[locks[1]]:
32
+ if from_account.balance >= amount:
33
+ from_account.balance -= amount
34
+ to_account.balance += amount
35
+ return True
36
+ return False
37
+ ```
38
+
39
+ #### Database-Level Locking
40
+
41
+ ```python
42
+ # SAFE: Database transaction with SELECT FOR UPDATE
43
+ from django.db import transaction
44
+
45
+ @transaction.atomic
46
+ def transfer(from_account_id, to_account_id, amount):
47
+ from_account = Account.objects.select_for_update().get(id=from_account_id)
48
+ to_account = Account.objects.select_for_update().get(id=to_account_id)
49
+
50
+ if from_account.balance >= amount:
51
+ from_account.balance -= amount
52
+ to_account.balance += amount
53
+ from_account.save()
54
+ to_account.save()
55
+ return True
56
+ return False
57
+ ```
58
+
59
+ ### 2. Workflow Bypass
60
+
61
+ ```python
62
+ # VULNERABLE: Multi-step process without server-side tracking
63
+ # Step 1: /verify-email
64
+ # Step 2: /set-password
65
+ # Step 3: /complete-registration
66
+
67
+ # Attacker skips to Step 3
68
+
69
+ # SAFE: Server-side state machine
70
+ class RegistrationFlow:
71
+ STATES = ['email_pending', 'email_verified', 'password_set', 'complete']
72
+
73
+ def __init__(self, user_id):
74
+ self.state = self.get_state(user_id)
75
+
76
+ def verify_email(self, token):
77
+ if self.state != 'email_pending':
78
+ raise InvalidStateError("Email verification not pending")
79
+ # Verify token...
80
+ self.set_state('email_verified')
81
+
82
+ def set_password(self, password):
83
+ if self.state != 'email_verified':
84
+ raise InvalidStateError("Email not verified")
85
+ # Set password...
86
+ self.set_state('password_set')
87
+
88
+ def complete(self):
89
+ if self.state != 'password_set':
90
+ raise InvalidStateError("Password not set")
91
+ # Complete registration...
92
+ self.set_state('complete')
93
+ ```
94
+
95
+ ### 3. Numeric Manipulation
96
+
97
+ #### Integer Overflow
98
+
99
+ ```python
100
+ # VULNERABLE: Integer overflow in quantity
101
+ def calculate_total(quantity, price):
102
+ return quantity * price
103
+
104
+ # Attack: quantity = -1 results in negative price (refund)
105
+
106
+ # SAFE: Validate numeric ranges
107
+ def calculate_total(quantity, price):
108
+ if quantity <= 0 or quantity > MAX_QUANTITY:
109
+ raise ValueError("Invalid quantity")
110
+ if price <= 0:
111
+ raise ValueError("Invalid price")
112
+ return quantity * price
113
+ ```
114
+
115
+ #### Floating Point Issues
116
+
117
+ ```python
118
+ # VULNERABLE: Floating point precision loss
119
+ total = 0.0
120
+ for item in items:
121
+ total += item.price * item.quantity
122
+
123
+ # 0.1 + 0.2 = 0.30000000000000004
124
+
125
+ # SAFE: Use Decimal for financial calculations
126
+ from decimal import Decimal, ROUND_HALF_UP
127
+
128
+ total = Decimal('0')
129
+ for item in items:
130
+ total += Decimal(str(item.price)) * item.quantity
131
+
132
+ # Round properly
133
+ total = total.quantize(Decimal('.01'), rounding=ROUND_HALF_UP)
134
+ ```
135
+
136
+ ### 4. Price/Discount Manipulation
137
+
138
+ ```python
139
+ # VULNERABLE: Trust client-submitted price
140
+ @app.route('/checkout', methods=['POST'])
141
+ def checkout():
142
+ price = request.json['price'] # Client can set any price!
143
+ process_payment(price)
144
+
145
+ # SAFE: Calculate price server-side
146
+ @app.route('/checkout', methods=['POST'])
147
+ def checkout():
148
+ cart = get_cart(current_user.id)
149
+ price = calculate_total(cart) # Always server-calculated
150
+ process_payment(price)
151
+ ```
152
+
153
+ ```python
154
+ # VULNERABLE: Stackable discounts without limits
155
+ def apply_discounts(cart, discount_codes):
156
+ for code in discount_codes:
157
+ discount = get_discount(code)
158
+ cart.total -= discount.amount
159
+
160
+ # Attack: Apply same code multiple times, negative total
161
+
162
+ # SAFE: Limit discount application
163
+ def apply_discounts(cart, discount_codes):
164
+ # Remove duplicates
165
+ unique_codes = set(discount_codes)
166
+
167
+ total_discount = Decimal('0')
168
+ for code in unique_codes:
169
+ if is_code_used(cart.user_id, code):
170
+ continue # Code already used
171
+ discount = get_discount(code)
172
+ total_discount += discount.amount
173
+ mark_code_used(cart.user_id, code)
174
+
175
+ # Cap discount at total
176
+ max_discount = cart.subtotal * Decimal('0.5') # Max 50% off
177
+ final_discount = min(total_discount, max_discount)
178
+ cart.total -= final_discount
179
+ ```
180
+
181
+ ### 5. Inventory/Resource Exhaustion
182
+
183
+ ```python
184
+ # VULNERABLE: No reservation during checkout
185
+ def checkout(cart):
186
+ for item in cart.items:
187
+ if get_stock(item.product_id) >= item.quantity:
188
+ # Stock available
189
+ pass
190
+ # Processing takes time...
191
+ process_payment()
192
+ for item in cart.items:
193
+ reduce_stock(item.product_id, item.quantity) # May oversell
194
+
195
+ # SAFE: Reserve inventory atomically
196
+ @transaction.atomic
197
+ def checkout(cart):
198
+ for item in cart.items:
199
+ product = Product.objects.select_for_update().get(id=item.product_id)
200
+ if product.stock < item.quantity:
201
+ raise InsufficientStock(product.name)
202
+ product.stock -= item.quantity # Reserve immediately
203
+ product.save()
204
+
205
+ # If payment fails, transaction rolls back
206
+ process_payment()
207
+ ```
208
+
209
+ ### 6. Time-Based Attacks
210
+
211
+ ```python
212
+ # VULNERABLE: Expired coupon still usable with timing attack
213
+ def apply_coupon(code):
214
+ coupon = Coupon.objects.get(code=code)
215
+ if coupon.expiry > datetime.now():
216
+ return coupon.discount
217
+ raise CouponExpired()
218
+
219
+ # SAFE: Use database time, not application time
220
+ from django.db.models.functions import Now
221
+
222
+ def apply_coupon(code):
223
+ coupon = Coupon.objects.annotate(
224
+ is_valid=Q(expiry__gt=Now())
225
+ ).get(code=code)
226
+
227
+ if not coupon.is_valid:
228
+ raise CouponExpired()
229
+ return coupon.discount
230
+ ```
231
+
232
+ ### 7. Parameter Tampering
233
+
234
+ ```python
235
+ # VULNERABLE: Trust hidden form fields
236
+ # HTML: <input type="hidden" name="user_id" value="123">
237
+
238
+ @app.route('/update-profile', methods=['POST'])
239
+ def update_profile():
240
+ user_id = request.form['user_id'] # Attacker can change this!
241
+ User.query.get(user_id).update(...)
242
+
243
+ # SAFE: Use session-based user identification
244
+ @app.route('/update-profile', methods=['POST'])
245
+ def update_profile():
246
+ user_id = current_user.id # From authenticated session
247
+ User.query.get(user_id).update(...)
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Detection Patterns
253
+
254
+ ### State Machine Validation
255
+
256
+ ```python
257
+ class OrderStateMachine:
258
+ VALID_TRANSITIONS = {
259
+ 'draft': ['submitted'],
260
+ 'submitted': ['approved', 'rejected'],
261
+ 'approved': ['shipped'],
262
+ 'shipped': ['delivered', 'returned'],
263
+ 'delivered': ['returned'],
264
+ 'rejected': [],
265
+ 'returned': ['refunded'],
266
+ 'refunded': []
267
+ }
268
+
269
+ def transition(self, order, new_state):
270
+ current = order.state
271
+ if new_state not in self.VALID_TRANSITIONS.get(current, []):
272
+ raise InvalidTransition(f"Cannot go from {current} to {new_state}")
273
+ order.state = new_state
274
+ log_state_change(order, current, new_state)
275
+ ```
276
+
277
+ ### Idempotency
278
+
279
+ ```python
280
+ # SAFE: Idempotent operations with idempotency keys
281
+ import hashlib
282
+
283
+ def process_request(request_data, idempotency_key):
284
+ # Check if request was already processed
285
+ existing = ProcessedRequest.query.filter_by(key=idempotency_key).first()
286
+ if existing:
287
+ return existing.response # Return cached response
288
+
289
+ # Process request
290
+ result = do_processing(request_data)
291
+
292
+ # Store for future duplicate requests
293
+ ProcessedRequest.create(key=idempotency_key, response=result)
294
+ return result
295
+ ```
296
+
297
+ ### Rate Limiting Business Actions
298
+
299
+ ```python
300
+ # Limit business-critical actions
301
+ from functools import wraps
302
+ import time
303
+
304
+ def rate_limit_action(action_name, limit, window):
305
+ def decorator(f):
306
+ @wraps(f)
307
+ def wrapper(*args, **kwargs):
308
+ user_id = current_user.id
309
+ key = f"action:{action_name}:{user_id}"
310
+
311
+ count = redis.incr(key)
312
+ if count == 1:
313
+ redis.expire(key, window)
314
+
315
+ if count > limit:
316
+ raise RateLimitExceeded(f"Too many {action_name} attempts")
317
+
318
+ return f(*args, **kwargs)
319
+ return wrapper
320
+ return decorator
321
+
322
+ @rate_limit_action('password_reset', limit=3, window=3600)
323
+ def request_password_reset(email):
324
+ pass
325
+
326
+ @rate_limit_action('transfer', limit=10, window=86400)
327
+ def transfer_funds(from_account, to_account, amount):
328
+ pass
329
+ ```
330
+
331
+ ---
332
+
333
+ ## Validation Patterns
334
+
335
+ ### Server-Side Calculation
336
+
337
+ ```python
338
+ # Always recalculate on server
339
+ def calculate_order_total(order):
340
+ subtotal = Decimal('0')
341
+ for item in order.items:
342
+ # Get current price from database, not from request
343
+ product = Product.query.get(item.product_id)
344
+ subtotal += product.price * item.quantity
345
+
346
+ # Apply tax
347
+ tax = subtotal * get_tax_rate(order.shipping_address)
348
+
349
+ # Apply discounts (validated server-side)
350
+ discount = calculate_discounts(order, order.discount_codes)
351
+
352
+ # Calculate total
353
+ total = subtotal + tax - discount
354
+
355
+ # Sanity checks
356
+ if total < Decimal('0'):
357
+ raise InvalidOrderError("Negative total")
358
+ if discount > subtotal:
359
+ raise InvalidOrderError("Discount exceeds subtotal")
360
+
361
+ return {
362
+ 'subtotal': subtotal,
363
+ 'tax': tax,
364
+ 'discount': discount,
365
+ 'total': total
366
+ }
367
+ ```
368
+
369
+ ### Business Rule Enforcement
370
+
371
+ ```python
372
+ class TransferValidator:
373
+ def validate(self, transfer):
374
+ errors = []
375
+
376
+ # Check transfer limits
377
+ if transfer.amount > MAX_SINGLE_TRANSFER:
378
+ errors.append("Exceeds single transfer limit")
379
+
380
+ # Check daily limits
381
+ daily_total = get_daily_transfer_total(transfer.from_account)
382
+ if daily_total + transfer.amount > DAILY_LIMIT:
383
+ errors.append("Exceeds daily transfer limit")
384
+
385
+ # Check velocity (unusual number of transfers)
386
+ recent_count = get_recent_transfer_count(transfer.from_account, hours=1)
387
+ if recent_count > MAX_TRANSFERS_PER_HOUR:
388
+ errors.append("Too many transfers in short period")
389
+
390
+ # Check for unusual patterns
391
+ if is_unusual_recipient(transfer.from_account, transfer.to_account):
392
+ errors.append("Unusual recipient - requires verification")
393
+
394
+ if errors:
395
+ raise ValidationError(errors)
396
+ ```
397
+
398
+ ---
399
+
400
+ ## Grep Patterns for Detection
401
+
402
+ ```bash
403
+ # Race condition indicators
404
+ grep -rn "sleep\|time\.sleep\|Thread\|async" --include="*.py"
405
+ grep -rn "balance\|inventory\|stock" --include="*.py" | grep -v "select_for_update\|lock"
406
+
407
+ # Price/amount from request
408
+ grep -rn "request\.\w*\[.*price\|request\.\w*\[.*amount\|request\.\w*\[.*total" --include="*.py"
409
+
410
+ # Missing validation
411
+ grep -rn "def checkout\|def purchase\|def transfer" --include="*.py"
412
+
413
+ # Floating point for money
414
+ grep -rn "float.*price\|float.*amount\|float.*balance" --include="*.py"
415
+ ```
416
+
417
+ ---
418
+
419
+ ## Testing Checklist
420
+
421
+ - [ ] Race conditions tested (concurrent requests)
422
+ - [ ] Workflow steps enforced server-side
423
+ - [ ] State transitions validated
424
+ - [ ] Prices/totals calculated server-side
425
+ - [ ] Discount limits enforced
426
+ - [ ] Inventory checked and reserved atomically
427
+ - [ ] Integer overflow/underflow prevented
428
+ - [ ] Decimal used for financial calculations
429
+ - [ ] Time-based logic uses server/database time
430
+ - [ ] Hidden field values not trusted
431
+ - [ ] Idempotency keys for critical operations
432
+ - [ ] Rate limits on business-critical actions
433
+ - [ ] Unusual patterns detected and flagged
434
+
435
+ ---
436
+
437
+ ## References
438
+
439
+ - [OWASP Business Logic Testing](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/10-Business_Logic_Testing/)
440
+ - [CWE-362: Race Condition](https://cwe.mitre.org/data/definitions/362.html)
441
+ - [CWE-367: TOCTOU Race Condition](https://cwe.mitre.org/data/definitions/367.html)
442
+ - [CWE-190: Integer Overflow](https://cwe.mitre.org/data/definitions/190.html)
443
+ - [CWE-840: Business Logic Errors](https://cwe.mitre.org/data/definitions/840.html)