fastapi-alertengine 1.1.2__tar.gz → 1.1.4__tar.gz

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 (199) hide show
  1. fastapi_alertengine-1.1.4/.claude/settings.local.json +25 -0
  2. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/PKG-INFO +1 -1
  3. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/examples/main.py +79 -97
  4. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/fastapi_alertengine/__init__.py +53 -56
  5. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/fastapi_alertengine/client.py +62 -65
  6. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/fastapi_alertengine/config.py +37 -34
  7. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/fastapi_alertengine/engine.py +191 -174
  8. fastapi_alertengine-1.1.4/fastapi_alertengine/middleware.py +59 -0
  9. fastapi_alertengine-1.1.4/fastapi_alertengine/schemas.py +12 -0
  10. fastapi_alertengine-1.1.4/fastapi_alertengine/storage.py +128 -0
  11. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/pyproject.toml +1 -1
  12. fastapi_alertengine-1.1.4/tests/test_engine_basic.py +187 -0
  13. fastapi_alertengine-1.1.2/.claude/settings.local.json +0 -17
  14. fastapi_alertengine-1.1.2/fastapi_alertengine/middleware.py +0 -64
  15. fastapi_alertengine-1.1.2/fastapi_alertengine/schemas.py +0 -52
  16. fastapi_alertengine-1.1.2/fastapi_alertengine/storage.py +0 -130
  17. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/# +0 -0
  18. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/.env +0 -0
  19. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/.env.example +0 -0
  20. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/.git +0 -0
  21. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/.gitattributes +0 -0
  22. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/.gitignore +0 -0
  23. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/AnchorFlow_Explainer.mp4 +0 -0
  24. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/AnchorFlow_Explainer_Script.docx +0 -0
  25. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/AnchorFlow_Explainer_Script.pptx +0 -0
  26. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/COMPLETE SCHEMA DOCUMENTATION FOR CLAUDE REVIEW.docx +0 -0
  27. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/Dockerfile.api +0 -0
  28. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/LICENSE +0 -0
  29. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/README.md +0 -0
  30. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/REAL_TEST_EXECUTION_MANUAL.md +0 -0
  31. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/SKILL.md +0 -0
  32. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/TESTING ARCHITECTURE.docx +0 -0
  33. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/alembic.ini +0 -0
  34. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/anchorflow-fundrazr-campaign.html +0 -0
  35. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/anchorflow_logo.gif +0 -0
  36. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/anchorflow_script.js +0 -0
  37. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/anchorflow_script_word.js +0 -0
  38. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/anchorflow_video.py +0 -0
  39. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/__init__.py +0 -0
  40. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/__init__.py +0 -0
  41. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/ecocash_wallet_adapter.py +0 -0
  42. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/fiscal_adapter.py +0 -0
  43. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/innbucks_wallet_adapter.py +0 -0
  44. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/mock_fiscal_adapter.py +0 -0
  45. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/mock_wallet_adapter.py +0 -0
  46. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/omari_wallet_adapter.py +0 -0
  47. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/paynow_wallet_adapter.py +0 -0
  48. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/twilio_adapter.py +0 -0
  49. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/wallet_adapter.py +0 -0
  50. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/zimra_fiscal+adapter.py +0 -0
  51. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/adapters/zimra_fiscal_adapter.py +0 -0
  52. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/__init__.py +0 -0
  53. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/conversation_log.py +0 -0
  54. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/engine.py +0 -0
  55. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/handlers/__init__.py +0 -0
  56. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/handlers/browsing.py +0 -0
  57. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/handlers/courier_flow.py +0 -0
  58. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/handlers/ordering.py +0 -0
  59. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/handlers/payment_wait.py +0 -0
  60. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/locks.py +0 -0
  61. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/bot/state_manager.py +0 -0
  62. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/config.py +0 -0
  63. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/__init__.py +0 -0
  64. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/ai/__init__.py +0 -0
  65. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/ai/intake_ai.py +0 -0
  66. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/ai/vision_ai.py +0 -0
  67. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/alert_deduplicator.py +0 -0
  68. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/alert_engine.py +0 -0
  69. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/alert_notification_service.py +0 -0
  70. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/config.py +0 -0
  71. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/courier_fence.py +0 -0
  72. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/event_bus.py +0 -0
  73. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/events.py +0 -0
  74. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/idempotency.py +0 -0
  75. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/load_shedding.py +0 -0
  76. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/metrics.py +0 -0
  77. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/redis.py +0 -0
  78. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/redis_health.py +0 -0
  79. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/safe_redis.py +0 -0
  80. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/core/state_machine.py +0 -0
  81. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/dashboard/transaction_health.py +0 -0
  82. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/db.py +0 -0
  83. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/events/audit_event.py +0 -0
  84. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/events/index_health.py +0 -0
  85. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/jobs/__init__.py +0 -0
  86. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/jobs/alert_cleanup_job.py +0 -0
  87. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/jobs/escrow_timeout_job.py +0 -0
  88. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/jobs/low_stock_job.py +0 -0
  89. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/jobs/merchant_ack_job.py +0 -0
  90. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/maintenance/index_health.py +0 -0
  91. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/maintenance/key_cleanup.py +0 -0
  92. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/__init__.py +0 -0
  93. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/auth.py +0 -0
  94. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/health.py +0 -0
  95. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/notifications.py +0 -0
  96. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/routes.py +0 -0
  97. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/schemas.py +0 -0
  98. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/service.py +0 -0
  99. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/templates/dashboard.html +0 -0
  100. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/merchant_portal/templates/deal_detail.html +0 -0
  101. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/middleware/__init__.py +0 -0
  102. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/middleware/request_metrics.py +0 -0
  103. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/models/__init__.py +0 -0
  104. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/models/database.py +0 -0
  105. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/models/proof_of_delivery.py +0 -0
  106. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/notifications/rotation_alerts.py +0 -0
  107. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/recovery/__init__.py +0 -0
  108. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/recovery/stuck_detector.py +0 -0
  109. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/alert_router.py +0 -0
  110. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/dashboard_router.py +0 -0
  111. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/deals.py +0 -0
  112. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/escrow_health.py +0 -0
  113. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/hypercare_dashboard.py +0 -0
  114. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/inventory.py +0 -0
  115. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/merchant_portal.py +0 -0
  116. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/metrics_router.py +0 -0
  117. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/recovery.py +0 -0
  118. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/webhook_controller.py +0 -0
  119. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/routers/whatsapp_bot.py +0 -0
  120. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/security/auth.py +0 -0
  121. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/security/encryption.py +0 -0
  122. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/security/key_rotation.py +0 -0
  123. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/security/pii_handler.py +0 -0
  124. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/__init__.py +0 -0
  125. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/catalogue.py +0 -0
  126. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/courier_timeout_engine.py +0 -0
  127. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/deal_service.py +0 -0
  128. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/dispute_service.py +0 -0
  129. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/dual_write.py +0 -0
  130. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/escrow_timeout_engine.py +0 -0
  131. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/event_log_service.py +0 -0
  132. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/inventory_service.py +0 -0
  133. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/merchant_catalogue_local.py +0 -0
  134. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/merchant_experience.py +0 -0
  135. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/merchant_onboarding.py +0 -0
  136. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/order_service.py +0 -0
  137. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/proof_of_delivery_service.py +0 -0
  138. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/recovery_service.py +0 -0
  139. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/settlement_engine.py +0 -0
  140. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/services/trust_score_engine.py +0 -0
  141. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/startup/__init__.py +0 -0
  142. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/startup/health_check.py +0 -0
  143. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/templates/deal.html +0 -0
  144. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/app/templates/merchant_dashboard.html +0 -0
  145. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/config.py +0 -0
  146. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/database.py +0 -0
  147. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/decryption.py +0 -0
  148. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/API.md +0 -0
  149. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/ARCHITECTURE.md +0 -0
  150. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/CONFIG.md +0 -0
  151. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/DEPLOYMENT.md +0 -0
  152. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/HARDENING.md +0 -0
  153. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/OPERATIONS.md +0 -0
  154. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/SYSTEM_SPEC.md +0 -0
  155. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/docs/assets/tofamba_logo.png +0 -0
  156. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/git +0 -0
  157. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/main.py +0 -0
  158. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/001_add_currency_merchant_ack.sql +0 -0
  159. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/env.py +0 -0
  160. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/script.py.mako +0 -0
  161. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250311_001_baseline_schema.py +0 -0
  162. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250311_002_add_currency_merchant_ack_indexes.py +0 -0
  163. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250329_003_merchant_onboarding.py +0 -0
  164. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250401_003_merchant_onboarding_v2.py +0 -0
  165. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250402_004_buyer_flow_orders.py +0 -0
  166. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250402_005_rbz_compliance.py +0 -0
  167. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/20250407_006_alert_history.py +0 -0
  168. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/migrations/versions/__init__.py +0 -0
  169. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/pytest +0 -0
  170. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/railway.yaml +0 -0
  171. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/requirements.txt +0 -0
  172. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/security/__init__.py +0 -0
  173. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/security/pii_handler.py +0 -0
  174. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/security/pin_verification.py +0 -0
  175. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/services/__init__.py +0 -0
  176. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/services/catalogue.py +0 -0
  177. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/services/escrow_release.py +0 -0
  178. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/services/payment_ledger.py +0 -0
  179. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/services/payment_provider.py +0 -0
  180. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/README.md +0 -0
  181. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/__init__.py +0 -0
  182. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/__init__.py +0 -0
  183. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_alert_engine_enhancements.py +0 -0
  184. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_anchorflow_tasks.py +0 -0
  185. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_courier_fence.py +0 -0
  186. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_deal_service.py +0 -0
  187. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_escrow_timeout.py +0 -0
  188. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_idempotency.py +0 -0
  189. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_inventory_service.py +0 -0
  190. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_load_shedding.py +0 -0
  191. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_metrics.py +0 -0
  192. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_mock_fiscal_adapter.py +0 -0
  193. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_mock_wallet_adapter.py +0 -0
  194. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_payment_adapters.py +0 -0
  195. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_paynow_wallet_adapter.py +0 -0
  196. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_recovery_sweep.py +0 -0
  197. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/tests/unit/test_safe_redis.py +0 -0
  198. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/workflows/tests.yml +0 -0
  199. {fastapi_alertengine-1.1.2 → fastapi_alertengine-1.1.4}/~$STING ARCHITECTURE.docx +0 -0
@@ -0,0 +1,25 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python -m twine upload dist/fastapi_alertengine-1.1.1*)",
5
+ "Bash(rm -rf dist/)",
6
+ "Bash(python -m build)",
7
+ "Bash(gh pr create --title 'docs: replace README with polished production version + $49 starter pack CTA' --body ':*)",
8
+ "Bash(where gh:*)",
9
+ "Bash(mkdir -p /tmp/alertengine_test)",
10
+ "Read(//tmp/**)",
11
+ "Bash(python -m venv venv)",
12
+ "Bash(venv/Scripts/pip install:*)",
13
+ "Bash(venv/Scripts/python -c \"import fastapi_alertengine; print\\(dir\\(fastapi_alertengine\\)\\)\")",
14
+ "Bash(venv/Scripts/python test_suite.py)",
15
+ "Bash(python -m twine upload dist/fastapi_alertengine-1.1.2* -u __token__ -p \"pypi-AgEIcHlwaS5vcmcCJDY2YzU5ZDQ2LTc1MzYtNDBlMC05NmEwLWQzNjY1YWE0YzFmMwACKlszLCJkOGIzYzYyYi04ZjZhLTQ1Y2QtOGI0Yy04NjVkNTc3YzdiMzIiXQAABiCzHg3XIP-Fc19FHsOR-y7ODms4njBSo5IoiXTHJfzUaA\")",
16
+ "Bash(venv/Scripts/python -c ':*)",
17
+ "Read(//c/tmp/alertengine_test/**)",
18
+ "Bash(python -m twine upload dist/fastapi_alertengine-1.1.3* -u __token__ -p \"pypi-AgEIcHlwaS5vcmcCJDY2YzU5ZDQ2LTc1MzYtNDBlMC05NmEwLWQzNjY1YWE0YzFmMwACKlszLCJkOGIzYzYyYi04ZjZhLTQ1Y2QtOGI0Yy04NjVkNTc3YzdiMzIiXQAABiCzHg3XIP-Fc19FHsOR-y7ODms4njBSo5IoiXTHJfzUaA\")",
19
+ "Bash(python -m twine upload dist/fastapi_alertengine-1.1.3* -u __token__ -p \"pypi-AgEIcHlwaS5vcmcCJDY2YzU5ZDQ2LTc1MzYtNDBlMC05NmEwLWQzNjY1YWE0YzFmMwACKlszLCJkOGIzYzYyYi04ZjZhLTQ1Y2QtOGI0Yy04NjVkNTc3YzdiMzIiXQAABiCzHg3XIP-Fc19FHsOR-y7ODms4njBSo5IoiXTHJfzUaA\" --verbose)",
20
+ "Bash(venv/Scripts/python -m pytest \"C:/Users/HP/OneDrive/Documents/Tandem Hive/Tandem_Hive_V1_Final/.claude/worktrees/gracious-dubinsky/tests/test_engine_basic.py\" -v --tb=short --import-mode=importlib --pythonpath \"C:/Users/HP/OneDrive/Documents/Tandem Hive/Tandem_Hive_V1_Final/.claude/worktrees/gracious-dubinsky\")",
21
+ "Bash(PYTHONPATH=\"C:/Users/HP/OneDrive/Documents/Tandem Hive/Tandem_Hive_V1_Final/.claude/worktrees/gracious-dubinsky\" /tmp/alertengine_test/venv/Scripts/python -m pytest tests/test_engine_basic.py -v --tb=short)",
22
+ "Bash(python -m twine upload dist/fastapi_alertengine-1.1.4* -u __token__ -p \"pypi-AgEIcHlwaS5vcmcCJDY2YzU5ZDQ2LTc1MzYtNDBlMC05NmEwLWQzNjY1YWE0YzFmMwACKlszLCJkOGIzYzYyYi04ZjZhLTQ1Y2QtOGI0Yy04NjVkNTc3YzdiMzIiXQAABiCzHg3XIP-Fc19FHsOR-y7ODms4njBSo5IoiXTHJfzUaA\")"
23
+ ]
24
+ }
25
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-alertengine
3
- Version: 1.1.2
3
+ Version: 1.1.4
4
4
  Summary: Production-grade request metrics middleware and SLO alert engine for FastAPI + Redis Streams
5
5
  Project-URL: Homepage, https://anchorflow.com/tofamba
6
6
  Project-URL: Repository, https://github.com/Tandem-Media/Tandem_Hive_V1_Final
@@ -1,97 +1,79 @@
1
- # examples/main.py
2
- """
3
- fastapi_alertengine — minimal demo app.
4
-
5
- Three endpoints:
6
- GET /fast — responds in ~5ms (normal traffic)
7
- GET /slow — responds in ~600ms (triggers warning)
8
- GET /error — returns HTTP 500 (drives up error rate)
9
-
10
- Run:
11
- pip install fastapi uvicorn redis fastapi-alertengine
12
- redis-server &
13
- uvicorn examples.main:app --reload
14
-
15
- Then hit the endpoints a few times and check:
16
- curl http://localhost:8000/alerts
17
- """
18
-
19
- import asyncio
20
- import os
21
-
22
- import redis
23
- from fastapi import FastAPI
24
-
25
- from fastapi_alertengine import (
26
- AlertConfig,
27
- AlertEngine,
28
- RequestMetricsMiddleware,
29
- aggregate,
30
- get_alert_engine,
31
- )
32
-
33
- # ── Redis ─────────────────────────────────────────────────────────────────────
34
-
35
- REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")
36
- rdb = redis.Redis.from_url(REDIS_URL, decode_responses=True)
37
-
38
- # ── App ───────────────────────────────────────────────────────────────────────
39
-
40
- app = FastAPI(title="fastapi_alertengine demo", version="0.1.0")
41
-
42
- # Register metrics middleware — must come before any other middleware
43
- app.add_middleware(RequestMetricsMiddleware, redis=rdb)
44
-
45
- # ── Demo endpoints ────────────────────────────────────────────────────────────
46
-
47
- @app.get("/fast", tags=["demo"])
48
- async def fast_endpoint():
49
- """Normal response — ~5ms latency."""
50
- await asyncio.sleep(0.005)
51
- return {"endpoint": "fast", "latency": "~5ms"}
52
-
53
-
54
- @app.get("/slow", tags=["demo"])
55
- async def slow_endpoint():
56
- """Slow response — ~600ms latency, will push p95 into warning range."""
57
- await asyncio.sleep(0.6)
58
- return {"endpoint": "slow", "latency": "~600ms"}
59
-
60
-
61
- @app.get("/error", tags=["demo"])
62
- async def error_endpoint():
63
- """Always returns 500 — drives up the error rate metric."""
64
- from fastapi import HTTPException
65
- raise HTTPException(status_code=500, detail="Intentional error for demo")
66
-
67
-
68
- # ── Alert status endpoint ─────────────────────────────────────────────────────
69
-
70
- @app.get("/alerts", tags=["observability"])
71
- def alert_status():
72
- """
73
- Evaluate current alert status from recent request metrics.
74
-
75
- Returns the AlertEngine result plus a p95 breakdown by traffic type.
76
- """
77
- engine = get_alert_engine(redis_client=rdb)
78
- event = engine.evaluate()
79
-
80
- return {
81
- "status": event.status,
82
- "reason": event.reason,
83
- "metrics": {
84
- "overall_p95_ms": event.metrics.overall_p95_ms,
85
- "webhook_p95_ms": event.metrics.webhook_p95_ms,
86
- "api_p95_ms": event.metrics.api_p95_ms,
87
- "error_rate": event.metrics.error_rate,
88
- "anomaly_score": event.metrics.anomaly_score,
89
- "sample_size": event.metrics.sample_size,
90
- },
91
- "thresholds": {
92
- "p95_warning_ms": event.thresholds.p95_warning_ms,
93
- "p95_critical_ms": event.thresholds.p95_critical_ms,
94
- "error_rate_critical": event.thresholds.error_rate_critical,
95
- },
96
- "aggregated": aggregate(rdb, AlertConfig()),
97
- }
1
+ # examples/main.py
2
+ """
3
+ fastapi_alertengine — minimal demo app.
4
+
5
+ Three endpoints:
6
+ GET /fast — responds in ~5ms (normal traffic)
7
+ GET /slow — responds in ~600ms (triggers warning)
8
+ GET /error — returns HTTP 500 (drives up error rate)
9
+
10
+ Run:
11
+ pip install "fastapi[standard]" redis fastapi-alertengine
12
+ redis-server &
13
+ uvicorn examples.main:app --reload
14
+
15
+ Then hit the endpoints a few times and check:
16
+ curl http://localhost:8000/alerts
17
+ """
18
+
19
+ import asyncio
20
+ import os
21
+
22
+ import redis
23
+ from fastapi import FastAPI, HTTPException
24
+
25
+ from fastapi_alertengine import (
26
+ AlertConfig,
27
+ RequestMetricsMiddleware,
28
+ aggregate,
29
+ get_alert_engine,
30
+ )
31
+
32
+ # ── Redis + engine ────────────────────────────────────────────────────────────
33
+
34
+ REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
35
+ rdb = redis.Redis.from_url(REDIS_URL, decode_responses=True)
36
+ engine = get_alert_engine(redis_client=rdb)
37
+
38
+ # ── App ───────────────────────────────────────────────────────────────────────
39
+
40
+ app = FastAPI(title="fastapi_alertengine demo", version="1.1.4")
41
+
42
+ # Register metrics middleware — must come before any other middleware
43
+ app.add_middleware(RequestMetricsMiddleware, alert_engine=engine)
44
+
45
+ # ── Demo endpoints ────────────────────────────────────────────────────────────
46
+
47
+ @app.get("/fast", tags=["demo"])
48
+ async def fast_endpoint():
49
+ """Normal response — ~5ms latency."""
50
+ await asyncio.sleep(0.005)
51
+ return {"endpoint": "fast", "latency": "~5ms"}
52
+
53
+
54
+ @app.get("/slow", tags=["demo"])
55
+ async def slow_endpoint():
56
+ """Slow response — ~600ms latency, will push p95 into warning range."""
57
+ await asyncio.sleep(0.6)
58
+ return {"endpoint": "slow", "latency": "~600ms"}
59
+
60
+
61
+ @app.get("/error", tags=["demo"])
62
+ async def error_endpoint():
63
+ """Always returns 500 — drives up the error rate metric."""
64
+ raise HTTPException(status_code=500, detail="Intentional error for demo")
65
+
66
+
67
+ # ── Alert status endpoint ─────────────────────────────────────────────────────
68
+
69
+ @app.get("/alerts", tags=["observability"])
70
+ def alert_status():
71
+ """
72
+ Evaluate current alert status from recent request metrics.
73
+
74
+ Returns the AlertEngine result plus a p95 breakdown by traffic type.
75
+ """
76
+ return {
77
+ **engine.evaluate(window_size=200),
78
+ "aggregated": aggregate(rdb, engine.config),
79
+ }
@@ -1,56 +1,53 @@
1
- # fastapi_alertengine/__init__.py
2
- """
3
- fastapi_alertengine
4
- ===================
5
-
6
- Production-grade request metrics middleware and SLO alert engine for
7
- FastAPI services. Backed by Redis Streams.
8
-
9
- Quick start::
10
-
11
- from fastapi import FastAPI
12
- from fastapi_alertengine import RequestMetricsMiddleware, get_alert_engine
13
- import redis
14
-
15
- app = FastAPI()
16
- rdb = redis.Redis.from_url("redis://localhost:6379", decode_responses=True)
17
-
18
- app.add_middleware(RequestMetricsMiddleware, redis=rdb)
19
-
20
- @app.get("/health/alerts")
21
- def alert_status():
22
- engine = get_alert_engine(redis_client=rdb)
23
- event = engine.evaluate()
24
- return {"status": event.status, "metrics": event.metrics}
25
- """
26
-
27
- from .client import get_alert_engine
28
- from .config import AlertConfig
29
- from .engine import AlertDeduplicator, AlertEngine
30
- from .middleware import RequestMetricsMiddleware
31
- from .schemas import AlertEvent, AlertMetrics, AlertThresholds, RequestMetricEvent
32
- from .storage import aggregate, read_metrics, write_metric
33
-
34
- __all__ = [
35
- # Primary surface
36
- "RequestMetricsMiddleware",
37
- "AlertEngine",
38
- "AlertDeduplicator",
39
- "get_alert_engine",
40
- # Config + schemas
41
- "AlertConfig",
42
- "AlertEvent",
43
- "AlertMetrics",
44
- "AlertThresholds",
45
- "RequestMetricEvent",
46
- # Storage helpers
47
- "aggregate",
48
- "read_metrics",
49
- "write_metric",
50
- ]
51
-
52
- try:
53
- from importlib.metadata import version as _v
54
- __version__ = _v("fastapi-alertengine")
55
- except Exception:
56
- __version__ = "unknown"
1
+ # fastapi_alertengine/__init__.py
2
+ """
3
+ fastapi_alertengine
4
+ ===================
5
+
6
+ Production-grade request metrics middleware and SLO alert engine for
7
+ FastAPI services. Backed by Redis Streams.
8
+
9
+ Quick start::
10
+
11
+ from fastapi import FastAPI
12
+ from fastapi_alertengine import RequestMetricsMiddleware, get_alert_engine
13
+ import redis
14
+
15
+ app = FastAPI()
16
+ rdb = redis.Redis.from_url("redis://localhost:6379/0", decode_responses=True)
17
+
18
+ engine = get_alert_engine(redis_client=rdb)
19
+ app.add_middleware(RequestMetricsMiddleware, alert_engine=engine)
20
+
21
+ @app.get("/health/alerts")
22
+ def alert_status():
23
+ return engine.evaluate()
24
+ """
25
+
26
+ from .client import get_alert_engine
27
+ from .config import AlertConfig
28
+ from .engine import AlertDeduplicator, AlertEngine
29
+ from .middleware import RequestMetricsMiddleware
30
+ from .schemas import RequestMetricEvent
31
+ from .storage import aggregate, p95, read_metrics, write_metric
32
+
33
+ try:
34
+ from importlib.metadata import version as _v
35
+ __version__ = _v("fastapi-alertengine")
36
+ except Exception:
37
+ __version__ = "unknown"
38
+
39
+ __all__ = [
40
+ # Primary surface
41
+ "RequestMetricsMiddleware",
42
+ "AlertEngine",
43
+ "AlertDeduplicator",
44
+ "get_alert_engine",
45
+ # Config + schemas
46
+ "AlertConfig",
47
+ "RequestMetricEvent",
48
+ # Storage helpers
49
+ "aggregate",
50
+ "p95",
51
+ "read_metrics",
52
+ "write_metric",
53
+ ]
@@ -1,65 +1,62 @@
1
- # fastapi_alertengine/client.py
2
- """
3
- get_alert_engine() — process-level singleton factory.
4
-
5
- Lazily constructs one AlertEngine per (redis_url, config) pair and
6
- caches it for the lifetime of the process. Safe to call from anywhere
7
- without worrying about duplicate Redis connections.
8
-
9
- Usage::
10
-
11
- from fastapi_alertengine import get_alert_engine
12
-
13
- engine = get_alert_engine(redis_url="redis://localhost:6379")
14
- event = engine.evaluate()
15
- """
16
-
17
- import threading
18
- from typing import Optional
19
-
20
- import redis as _redis_lib
21
-
22
- from .config import AlertConfig
23
- from .engine import AlertEngine
24
-
25
- _lock = threading.Lock()
26
- _registry: dict = {}
27
-
28
-
29
- def get_alert_engine(
30
- redis_url: str = "redis://localhost:6379",
31
- redis_client = None,
32
- config: Optional[AlertConfig] = None,
33
- ) -> AlertEngine:
34
- """
35
- Return a cached :class:`~fastapi_alertengine.engine.AlertEngine`.
36
-
37
- Pass either ``redis_url`` (a connection string) or an already-constructed
38
- ``redis_client`` instance — not both. If ``redis_client`` is supplied it
39
- is used directly and ``redis_url`` is ignored.
40
-
41
- Args:
42
- redis_url: Redis connection string (used if ``redis_client`` is None).
43
- redis_client: Pre-built ``redis.Redis`` instance (optional).
44
- config: :class:`~fastapi_alertengine.config.AlertConfig`.
45
- Defaults to library defaults.
46
-
47
- Returns:
48
- A shared :class:`~fastapi_alertengine.engine.AlertEngine` instance.
49
- """
50
- cfg = config or AlertConfig()
51
- key = id(redis_client) if redis_client is not None else redis_url
52
-
53
- if key not in _registry:
54
- with _lock:
55
- if key not in _registry:
56
- rdb = redis_client or _redis_lib.Redis.from_url(
57
- redis_url,
58
- decode_responses=True,
59
- socket_timeout=5,
60
- socket_connect_timeout=5,
61
- retry_on_timeout=True,
62
- )
63
- _registry[key] = AlertEngine(redis=rdb, config=cfg)
64
-
65
- return _registry[key]
1
+ # fastapi_alertengine/client.py
2
+ """
3
+ get_alert_engine() — process-level singleton factory.
4
+
5
+ Lazily constructs one AlertEngine per (redis_url, config) pair and caches it
6
+ for the lifetime of the process. Safe to call from anywhere without worrying
7
+ about duplicate Redis connections.
8
+
9
+ Usage::
10
+
11
+ from fastapi_alertengine import get_alert_engine
12
+
13
+ engine = get_alert_engine(redis_client=rdb)
14
+ result = engine.evaluate()
15
+ """
16
+
17
+ import threading
18
+ from typing import Optional
19
+
20
+ import redis as _redis_lib
21
+
22
+ from .config import AlertConfig
23
+ from .engine import AlertEngine
24
+
25
+ _lock: threading.Lock = threading.Lock()
26
+ _registry: dict = {}
27
+
28
+
29
+ def get_alert_engine(
30
+ config: Optional[AlertConfig] = None,
31
+ redis_client = None,
32
+ ) -> AlertEngine:
33
+ """
34
+ Return a cached :class:`~fastapi_alertengine.engine.AlertEngine`.
35
+
36
+ Pass an already-constructed ``redis_client`` to reuse an existing
37
+ connection. If omitted, a new client is created from
38
+ ``config.redis_url``.
39
+
40
+ Args:
41
+ config: :class:`~fastapi_alertengine.config.AlertConfig`.
42
+ Defaults to ``AlertConfig()`` (all library defaults).
43
+ redis_client: Pre-built ``redis.Redis`` instance (optional).
44
+
45
+ Returns:
46
+ A shared :class:`~fastapi_alertengine.engine.AlertEngine` instance.
47
+ """
48
+ cfg = config or AlertConfig()
49
+ key = id(redis_client) if redis_client is not None else cfg.redis_url
50
+
51
+ if key not in _registry:
52
+ with _lock:
53
+ if key not in _registry:
54
+ rdb = redis_client or _redis_lib.Redis.from_url(
55
+ cfg.redis_url,
56
+ decode_responses=True,
57
+ socket_timeout=5,
58
+ socket_connect_timeout=5,
59
+ )
60
+ _registry[key] = AlertEngine(redis=rdb, config=cfg)
61
+
62
+ return _registry[key]
@@ -1,34 +1,37 @@
1
- # fastapi_alertengine/config.py
2
- from dataclasses import dataclass, field
3
-
4
-
5
- @dataclass
6
- class AlertConfig:
7
- """
8
- All tunable parameters for the alert engine in one place.
9
-
10
- Pass a custom instance to RequestMetricsMiddleware and AlertEngine
11
- to override any default without subclassing.
12
- """
13
-
14
- # ── Redis Stream ──────────────────────────────────────────────────────────
15
- stream_key: str = "fastapi_alertengine:request_metrics"
16
- stream_maxlen: int = 10_000 # approximate cap (Redis MAXLEN ~)
17
-
18
- # ── Latency thresholds (ms) ───────────────────────────────────────────────
19
- p95_warning_ms: float = 1_000.0
20
- p95_critical_ms: float = 3_000.0
21
-
22
- # ── Anomaly thresholds (ratio vs rolling mean) ────────────────────────────
23
- anomaly_warning: float = 1.0
24
- anomaly_critical: float = 2.0
25
-
26
- # ── Error-rate thresholds (fraction of 5xx responses) ────────────────────
27
- error_rate_warning: float = 0.10
28
- error_rate_critical: float = 0.20
29
-
30
- # ── Evaluation window ─────────────────────────────────────────────────────
31
- window_size: int = 200 # events read per evaluate() call
32
-
33
- # ── Deduplication ─────────────────────────────────────────────────────────
34
- cooldown_seconds: int = 300 # min seconds between identical alerts
1
+ # fastapi_alertengine/config.py
2
+ from dataclasses import dataclass
3
+
4
+
5
+ @dataclass
6
+ class AlertConfig:
7
+ """
8
+ All tunable parameters for the alert engine in one place.
9
+
10
+ Pass a custom instance to get_alert_engine() or AlertEngine()
11
+ to override any default without subclassing.
12
+ """
13
+
14
+ # ── Redis connection ──────────────────────────────────────────────────────
15
+ redis_url: str = "redis://localhost:6379/0"
16
+
17
+ # ── Redis Stream ──────────────────────────────────────────────────────────
18
+ stream_key: str = "anchorflow:request_metrics"
19
+ stream_maxlen: int = 10_000 # approximate cap (Redis MAXLEN ~)
20
+
21
+ # ── Latency thresholds (ms) ───────────────────────────────────────────────
22
+ p95_warning_ms: float = 1_000.0
23
+ p95_critical_ms: float = 3_000.0
24
+
25
+ # ── Anomaly thresholds (ratio vs rolling mean) ────────────────────────────
26
+ anomaly_warning: float = 1.0
27
+ anomaly_critical: float = 2.0
28
+
29
+ # ── Error-rate thresholds (fraction of 5xx responses) ────────────────────
30
+ error_rate_warning: float = 0.10
31
+ error_rate_critical: float = 0.20
32
+
33
+ # ── Evaluation window ─────────────────────────────────────────────────────
34
+ window_size: int = 200 # events read per evaluate() call
35
+
36
+ # ── Deduplication ─────────────────────────────────────────────────────────
37
+ cooldown_seconds: int = 300 # min seconds between identical alerts