skilldrop-cli 0.16.45 → 1.0.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.
Files changed (230) hide show
  1. package/README.md +1 -1
  2. package/catalogue.json +1 -0
  3. package/model-routing.json +1 -0
  4. package/package.json +1 -1
  5. package/packs/solution-architect/skills/context-graph/SKILL.md +119 -0
  6. package/packs/solution-architect/skills/context-graph/evals/eval_queries.json +11 -0
  7. package/packs/solution-architect/skills/context-graph/evals/evals.json +225 -0
  8. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0001-record-architecture-decisions.md +19 -0
  9. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0002-postgres-as-primary-database.md +16 -0
  10. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0003-use-redis-for-session-storage.md +24 -0
  11. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0004-structured-json-logging.md +15 -0
  12. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0005-session-lifetime-eight-hours.md +22 -0
  13. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0006-move-sessions-to-postgres.md +16 -0
  14. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0007-stateless-signed-session-cookies.md +35 -0
  15. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/__init__.py +0 -0
  16. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/db.py +0 -0
  17. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/logging_setup.py +0 -0
  18. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/__init__.py +0 -0
  19. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/cookie_sessions.py +7 -0
  20. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/redis_sessions.py +7 -0
  21. package/packs/solution-architect/skills/context-graph/evals/files/10/README.md +8 -0
  22. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0001-record-architecture-decisions.md +10 -0
  23. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0004-service-auth-hmac-shared-keys.md +21 -0
  24. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0007-secrets-from-vault-agent.md +19 -0
  25. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0011-service-auth-mtls.md +23 -0
  26. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/app.py +16 -0
  27. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/__init__.py +4 -0
  28. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/hmac_verify.py +31 -0
  29. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/config/settings.py +14 -0
  30. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/__init__.py +4 -0
  31. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/mtls.py +18 -0
  32. package/packs/solution-architect/skills/context-graph/evals/files/11/README.md +4 -0
  33. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/base.py +3 -0
  34. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/line_item.py +14 -0
  35. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/order.py +24 -0
  36. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-003-money-as-minor-units.md +10 -0
  37. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-005-orders-typed-columns-only.md +10 -0
  38. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-009-line-items-immutable.md +11 -0
  39. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-014-optional-order-attributes-json.md +16 -0
  40. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-016-order-attributes-table.md +11 -0
  41. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0007_create_orders.sql +11 -0
  42. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0012_add_order_attributes.sql +2 -0
  43. package/packs/solution-architect/skills/context-graph/evals/files/12/README.md +8 -0
  44. package/packs/solution-architect/skills/context-graph/evals/files/12/config/delivery.yaml +4 -0
  45. package/packs/solution-architect/skills/context-graph/evals/files/12/config/export.yaml +2 -0
  46. package/packs/solution-architect/skills/context-graph/evals/files/12/config/partners.yaml +10 -0
  47. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0001-record-architecture-decisions.md +10 -0
  48. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0002-postgres-delivery-log.md +15 -0
  49. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0003-redis-idempotency-keys.md +15 -0
  50. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0004-retry-policy.md +16 -0
  51. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0005-hmac-signed-payloads.md +10 -0
  52. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0006-postgres-idempotency.md +15 -0
  53. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0007-sftp-batch-export.md +12 -0
  54. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0008-partner-config-in-yaml.md +12 -0
  55. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0009-partner-config-admin-api.md +13 -0
  56. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/003_idempotency_keys.sql +6 -0
  57. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/004_partners.sql +7 -0
  58. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/dispatcher.py +29 -0
  59. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/retry.py +15 -0
  60. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/signing.py +13 -0
  61. package/packs/solution-architect/skills/context-graph/evals/files/12/src/export/s3_export.py +24 -0
  62. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/pg_store.py +11 -0
  63. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/redis_store.py +8 -0
  64. package/packs/solution-architect/skills/context-graph/evals/files/12/src/partners/loader.py +15 -0
  65. package/packs/solution-architect/skills/context-graph/evals/files/12/src/store/delivery_log.py +18 -0
  66. package/packs/solution-architect/skills/context-graph/evals/files/13/README.md +3 -0
  67. package/packs/solution-architect/skills/context-graph/evals/files/13/config/cache.yaml +2 -0
  68. package/packs/solution-architect/skills/context-graph/evals/files/13/config/settings.yaml +2 -0
  69. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-008-pricing-from-erp.md +10 -0
  70. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-012-pricing-cache.md +23 -0
  71. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-015-checkout-price-lock.md +15 -0
  72. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-019-pricing-service.md +17 -0
  73. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/catalog/views.py +8 -0
  74. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/checkout/lock.py +14 -0
  75. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/cache.py +22 -0
  76. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/client.py +10 -0
  77. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0001-idempotency-keys.md +33 -0
  78. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0002-processor-retry-policy.md +26 -0
  79. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0003-money-in-minor-units.md +31 -0
  80. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0004-webhook-signing.md +27 -0
  81. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0005-retry-with-jitter.md +30 -0
  82. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0006-idempotency-at-gateway.md +28 -0
  83. package/packs/solution-architect/skills/context-graph/evals/files/14/pr-summary.md +27 -0
  84. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/amount.ts +10 -0
  85. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/charge.ts +28 -0
  86. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/idempotency.ts +4 -0
  87. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/retry.ts +21 -0
  88. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/send.ts +9 -0
  89. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/sign.ts +6 -0
  90. package/packs/solution-architect/skills/context-graph/evals/files/15/deploy/services.yaml +14 -0
  91. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0001-record-architecture-decisions.md +20 -0
  92. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0002-use-postgresql-for-shipment-data.md +23 -0
  93. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0003-store-vehicle-telemetry-in-cassandra.md +22 -0
  94. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0004-use-redis-for-session-storage.md +22 -0
  95. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0005-use-react-for-dispatcher-dashboard.md +19 -0
  96. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0006-archive-delivered-shipments-to-object-storage.md +23 -0
  97. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0007-move-shipment-records-to-mongodb.md +23 -0
  98. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0008-store-vehicle-telemetry-in-timescaledb.md +28 -0
  99. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0009-stateless-sessions-with-signed-cookies.md +24 -0
  100. package/packs/solution-architect/skills/context-graph/evals/files/15/services/api/session.py +17 -0
  101. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/db.py +30 -0
  102. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/migrations.sql +3 -0
  103. package/packs/solution-architect/skills/context-graph/evals/files/15/services/telemetry/store.py +23 -0
  104. package/packs/solution-architect/skills/context-graph/evals/files/15/web/dashboard/App.jsx +3 -0
  105. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0001-record-architecture-decisions.md +11 -0
  106. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0002-rabbitmq-for-background-jobs.md +15 -0
  107. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0003-thumbnail-service.md +20 -0
  108. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0004-money-as-integer-minor-units.md +17 -0
  109. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0005-worker-retries.md +12 -0
  110. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0006-fx-amounts-with-four-decimals.md +18 -0
  111. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0007-feature-flags.md +16 -0
  112. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0008-retire-legacy-search.md +14 -0
  113. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/__init__.py +0 -0
  114. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/amount.py +9 -0
  115. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/flags.py +1 -0
  116. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/publish.py +0 -0
  117. package/packs/solution-architect/skills/context-graph/evals/files/2/services/media/resize.py +5 -0
  118. package/packs/solution-architect/skills/context-graph/evals/files/2/services/worker/consumer.py +0 -0
  119. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0001-how-we-write-rfcs.md +9 -0
  120. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0002-payments-service-boundary.md +16 -0
  121. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0003-webhook-retries-fixed-interval.md +19 -0
  122. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0004-webhook-idempotency-keys.md +16 -0
  123. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0005-notification-retries.md +16 -0
  124. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0006-webhook-retry-backoff.md +26 -0
  125. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0007-webhooks-on-the-job-queue.md +12 -0
  126. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/__init__.py +0 -0
  127. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/retry.py +4 -0
  128. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/__init__.py +0 -0
  129. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/__init__.py +0 -0
  130. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/retry.py +15 -0
  131. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/send.py +0 -0
  132. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0001-record-architecture-decisions.md +19 -0
  133. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0002-postgres-as-system-of-record.md +18 -0
  134. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0004-redis-locks-for-scheduler.md +19 -0
  135. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0007-remove-redis.md +27 -0
  136. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0009-money-as-integer-minor-units.md +19 -0
  137. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/onboarding.md +12 -0
  138. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/__init__.py +0 -0
  139. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/db/__init__.py +22 -0
  140. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/invoicing.py +9 -0
  141. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/money.py +10 -0
  142. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/__init__.py +0 -0
  143. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/lock.py +23 -0
  144. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/runner.py +17 -0
  145. package/packs/solution-architect/skills/context-graph/evals/files/5/lib/types/index.ts +13 -0
  146. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0001-service-layout.md +20 -0
  147. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0003-ingest-retry-policy.md +26 -0
  148. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0006-shared-retry-library.md +24 -0
  149. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0008-outbound-http-client.md +22 -0
  150. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/client.ts +15 -0
  151. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/retry.ts +12 -0
  152. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/client.ts +14 -0
  153. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/retry.ts +20 -0
  154. package/packs/solution-architect/skills/context-graph/evals/files/6/README.md +4 -0
  155. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0001-monorepo-layout.md +10 -0
  156. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0002-billing-on-postgres.md +13 -0
  157. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0004-ledger-sync-nightly-batch.md +9 -0
  158. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0003-invoice-ids.md +9 -0
  159. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0007-invoice-ids-ulid.md +11 -0
  160. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0009-billing-event-store.md +15 -0
  161. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0010-revenue-service.md +13 -0
  162. package/packs/solution-architect/skills/context-graph/evals/files/6/libs/money/ulid.py +8 -0
  163. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/events.py +10 -0
  164. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/store.py +10 -0
  165. package/packs/solution-architect/skills/context-graph/evals/files/6/services/invoicing/ids/generator.py +7 -0
  166. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/README.md +4 -0
  167. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/sync.py +3 -0
  168. package/packs/solution-architect/skills/context-graph/evals/files/7/README.md +4 -0
  169. package/packs/solution-architect/skills/context-graph/evals/files/7/db/queries/orders.sql +2 -0
  170. package/packs/solution-architect/skills/context-graph/evals/files/7/db/sharding/router.py +9 -0
  171. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-001-postgres-primary.md +8 -0
  172. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-002-kafka-event-bus.md +20 -0
  173. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-003-no-orm.md +9 -0
  174. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-006-tenant-sharding.md +9 -0
  175. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-011-orm-for-admin-console.md +11 -0
  176. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/fanout/router.py +4 -0
  177. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/consumer.py +5 -0
  178. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/topics.yaml +8 -0
  179. package/packs/solution-architect/skills/context-graph/evals/files/7/rfcs/0004-region-sharding.md +15 -0
  180. package/packs/solution-architect/skills/context-graph/evals/files/7/services/admin-console/models.py +11 -0
  181. package/packs/solution-architect/skills/context-graph/evals/files/7/services/orders/repo.py +9 -0
  182. package/packs/solution-architect/skills/context-graph/evals/files/8/README.md +11 -0
  183. package/packs/solution-architect/skills/context-graph/evals/files/8/api/ledger.proto +30 -0
  184. package/packs/solution-architect/skills/context-graph/evals/files/8/config/http.yaml +10 -0
  185. package/packs/solution-architect/skills/context-graph/evals/files/8/config/messaging.yaml +8 -0
  186. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0001-record-architecture-decisions.md +20 -0
  187. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0002-postgresql-for-ledger.md +22 -0
  188. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0003-rabbitmq-domain-events.md +22 -0
  189. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0004-integer-minor-units.md +32 -0
  190. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0005-provider-http-retries.md +26 -0
  191. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0006-openapi-generated-clients.md +20 -0
  192. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0007-kafka-domain-events.md +25 -0
  193. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0008-structured-logging.md +18 -0
  194. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/rfcs/RFC-012-idempotency-keys.md +19 -0
  195. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/idempotency.py +19 -0
  196. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/server.py +35 -0
  197. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/clients/provider.py +33 -0
  198. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0001_init.sql +14 -0
  199. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0008_idempotency_keys.sql +5 -0
  200. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0009_fx_entries.sql +4 -0
  201. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/events/publisher.py +28 -0
  202. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/logging.py +25 -0
  203. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/models/entry.py +16 -0
  204. package/packs/solution-architect/skills/context-graph/evals/files/9/.env.example +3 -0
  205. package/packs/solution-architect/skills/context-graph/evals/files/9/README.md +5 -0
  206. package/packs/solution-architect/skills/context-graph/evals/files/9/docker-compose.yml +18 -0
  207. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/001-session-storage.md +21 -0
  208. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/002-api-rate-limiting.md +32 -0
  209. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/003-jwt-sessions.md +29 -0
  210. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/004-catalog-cache.md +19 -0
  211. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/cache.ts +13 -0
  212. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/repository.ts +13 -0
  213. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/email.ts +3 -0
  214. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/export.ts +3 -0
  215. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/queue.ts +10 -0
  216. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/worker.ts +8 -0
  217. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/db.ts +10 -0
  218. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/redis.ts +8 -0
  219. package/packs/solution-architect/skills/context-graph/evals/files/9/src/middleware/rateLimit.ts +26 -0
  220. package/packs/solution-architect/skills/context-graph/evals/files/9/src/server.ts +17 -0
  221. package/packs/solution-architect/skills/context-graph/evals/files/9/src/session/store.ts +10 -0
  222. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0004-kafka-for-order-events.md +19 -0
  223. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0006-email-receipts.md +7 -0
  224. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0009-sqs-for-order-events.md +19 -0
  225. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/notifications/receipts.py +0 -0
  226. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/orders/publisher.py +0 -0
  227. package/packs/solution-architect/skills/context-graph/examples/order-events.md +63 -0
  228. package/packs/solution-architect/skills/context-graph/manifest.json +33 -0
  229. package/packs/solution-architect/skills/context-graph/reference.md +104 -0
  230. package/packs/solution-architect/skills/context-graph/scripts/context_graph.py +634 -0
@@ -0,0 +1,15 @@
1
+ """Load partner configuration."""
2
+ import time
3
+
4
+ from src.db import execute
5
+
6
+ _cache = {"at": 0, "partners": []}
7
+ RELOAD_SECONDS = 60
8
+
9
+
10
+ def load_partners():
11
+ if time.time() - _cache["at"] > RELOAD_SECONDS:
12
+ rows = execute("SELECT id, url, events FROM partners WHERE enabled")
13
+ _cache["partners"] = [{"id": r[0], "url": r[1], "events": r[2]} for r in rows]
14
+ _cache["at"] = time.time()
15
+ return _cache["partners"]
@@ -0,0 +1,18 @@
1
+ """Delivery attempt log (see ADR-0002)."""
2
+ from src.db import execute
3
+
4
+
5
+ def record_attempt(event_id, partner_id, attempt_no, status_code):
6
+ execute(
7
+ "INSERT INTO delivery_attempts (event_id, partner_id, attempt_no, status_code, sent_at) "
8
+ "VALUES (%s, %s, %s, %s, now())",
9
+ (event_id, partner_id, attempt_no, status_code),
10
+ )
11
+
12
+
13
+ def mark_failed(event_id, partner_id):
14
+ execute(
15
+ "UPDATE delivery_attempts SET final_status = 'failed' "
16
+ "WHERE event_id = %s AND partner_id = %s",
17
+ (event_id, partner_id),
18
+ )
@@ -0,0 +1,3 @@
1
+ # shopfront
2
+
3
+ The Brindle & Co. web store monolith: catalog, cart, checkout. Design records live in `docs/decisions/`.
@@ -0,0 +1,2 @@
1
+ PRICING_SVC_URL: http://pricing-svc.internal:8080
2
+ REDIS_URL: redis://cache.internal:6379/0
@@ -0,0 +1,10 @@
1
+ # RFC-008: Read prices from the Halvorsen ERP
2
+
3
+ Status: Accepted
4
+ Date: 2023-02-07
5
+ Author: M. Okafor
6
+ Governs: shopfront/pricing/erp_client.py
7
+
8
+ ## Decision
9
+ Shopfront reads the current price for a SKU from the Halvorsen ERP `GetItemPrice` SOAP call
10
+ through `shopfront/pricing/erp_client.py`. The ERP is the single source of truth for prices.
@@ -0,0 +1,23 @@
1
+ # RFC-012: Cache prices in Redis
2
+
3
+ Status: Accepted
4
+ Date: 2023-06-14
5
+ Author: M. Okafor
6
+ Builds on: RFC-008
7
+ Governs: shopfront/pricing/cache.py, config/cache.yaml
8
+
9
+ ## Context
10
+ The Halvorsen ERP limits `GetItemPrice` to 40 requests/second per client and its p95 latency is
11
+ ~900 ms. During the June sale the product page timed out and the ERP throttled us for 20 minutes.
12
+
13
+ ## Decision
14
+ Put a read-through Redis cache in front of pricing. Key `price:{sku}`, TTL 60 seconds. A price
15
+ change in the ERP can therefore take up to a minute to show on the site; merchandising agreed
16
+ this is acceptable.
17
+
18
+ ## Alternatives considered
19
+ - Nightly price snapshot: rejected, price changes during sales must show within minutes.
20
+ - Asking Halvorsen to raise the limit: rejected by the vendor.
21
+
22
+ ## Revisit when
23
+ The ERP rate limit no longer applies to us.
@@ -0,0 +1,15 @@
1
+ # RFC-015: Lock the price for the duration of checkout
2
+
3
+ Status: Accepted
4
+ Date: 2024-01-09
5
+ Author: J. Lindqvist
6
+ Amends: RFC-012
7
+ Governs: shopfront/checkout/lock.py
8
+
9
+ ## Context
10
+ Customers were charged a different price from the one shown when a price changed mid-checkout.
11
+
12
+ ## Decision
13
+ When a cart enters checkout, the price a customer saw must be the price they are charged for
14
+ 15 minutes. We do this by reusing the pricing cache: checkout keeps the cached price for each
15
+ SKU in the cart alive for 15 minutes.
@@ -0,0 +1,17 @@
1
+ # RFC-019: Read prices from pricing-svc instead of the ERP
2
+
3
+ Status: Proposed
4
+ Date: 2025-03-18
5
+ Author: P. Achterberg
6
+ Supersedes: RFC-008
7
+
8
+ ## Context
9
+ The pricing team now runs `pricing-svc`, a REST service that replicates ERP prices within
10
+ 5 seconds of a change. It has no per-client rate limit and a p95 of 35 ms.
11
+
12
+ ## Proposal
13
+ Shopfront calls `GET {PRICING_SVC_URL}/v1/prices/{sku}` instead of the ERP SOAP call, and
14
+ `erp_client.py` is deleted.
15
+
16
+ ## Open questions
17
+ - Do we still need the Redis cache from RFC-012 once the ERP is out of the path?
@@ -0,0 +1,8 @@
1
+ """Product detail page."""
2
+ from shopfront.pricing import cache
3
+
4
+
5
+ def product_detail(request, sku):
6
+ product = request.catalog.get(sku)
7
+ price = cache.get_price(sku)
8
+ return request.render("product.html", {"product": product, "price": price})
@@ -0,0 +1,14 @@
1
+ """Hold prices steady while a cart is in checkout (RFC-015)."""
2
+ from shopfront.pricing import cache
3
+
4
+ LOCK_SECONDS = 15 * 60
5
+
6
+
7
+ def lock_cart_prices(cart) -> None:
8
+ for line in cart.lines:
9
+ cache.get_price(line.sku) # make sure the entry exists
10
+ cache.touch(line.sku, LOCK_SECONDS) # keep it alive for the checkout window
11
+
12
+
13
+ def price_for_charge(sku: str) -> dict:
14
+ return cache.get_price(sku)
@@ -0,0 +1,22 @@
1
+ """Read-through price cache (RFC-012)."""
2
+ import json
3
+
4
+ from shopfront.redis_client import redis
5
+ from shopfront.settings import load_yaml
6
+ from shopfront.pricing.client import fetch_price
7
+
8
+ TTL = load_yaml("config/cache.yaml")["pricing"]["ttl_seconds"]
9
+
10
+
11
+ def get_price(sku: str) -> dict:
12
+ key = f"price:{sku}"
13
+ hit = redis.get(key)
14
+ if hit is not None:
15
+ return json.loads(hit)
16
+ price = fetch_price(sku)
17
+ redis.set(key, json.dumps(price), ex=TTL)
18
+ return price
19
+
20
+
21
+ def touch(sku: str, ttl: int) -> None:
22
+ redis.expire(f"price:{sku}", ttl)
@@ -0,0 +1,10 @@
1
+ """Fetch the current price for a SKU."""
2
+ import json
3
+ import urllib.request
4
+
5
+ from shopfront.settings import PRICING_SVC_URL
6
+
7
+
8
+ def fetch_price(sku: str) -> dict:
9
+ with urllib.request.urlopen(f"{PRICING_SVC_URL}/v1/prices/{sku}", timeout=2) as resp:
10
+ return json.load(resp) # {"sku": ..., "amount_minor": ..., "currency": ...}
@@ -0,0 +1,33 @@
1
+ ---
2
+ rfc: 0001
3
+ title: Idempotency keys on every charge request
4
+ status: accepted
5
+ date: 2024-02-12
6
+ authors: [mira.okafor]
7
+ governs:
8
+ - src/payments/charge.ts
9
+ ---
10
+
11
+ # RFC-0001: Idempotency keys on every charge request
12
+
13
+ ## Problem
14
+
15
+ Mobile clients retry on flaky networks. Without a dedupe key, a retried
16
+ `POST /charges` can bill a customer twice. We had 14 double-charge tickets in
17
+ January 2024.
18
+
19
+ ## Decision
20
+
21
+ Every `POST /charges` request MUST carry an `Idempotency-Key` header. The
22
+ charge handler rejects requests without one (HTTP 400) and stores the key with
23
+ the charge for 24 hours. A repeat key returns the original response instead of
24
+ creating a new charge.
25
+
26
+ The check lives in the charge handler itself, not in the retry layer: the
27
+ retry layer only sees our own outbound retries to the card processor, not
28
+ inbound client retries.
29
+
30
+ ## Consequences
31
+
32
+ - Clients must generate a UUID per logical charge.
33
+ - The `idempotency_keys` table grows; rows expire after 24 hours.
@@ -0,0 +1,26 @@
1
+ ---
2
+ rfc: 0002
3
+ title: Fixed-interval retries to the card processor
4
+ status: superseded
5
+ superseded_by: 0005
6
+ date: 2024-02-20
7
+ authors: [dev.raman]
8
+ governs:
9
+ - src/payments/retry.ts
10
+ ---
11
+
12
+ # RFC-0002: Fixed-interval retries to the card processor
13
+
14
+ ## Problem
15
+
16
+ Calls to the card processor occasionally time out. We need a retry policy.
17
+
18
+ ## Decision
19
+
20
+ Retry failed processor calls up to 3 times with a fixed 2-second delay
21
+ between attempts.
22
+
23
+ ## Consequences
24
+
25
+ - Simple to reason about.
26
+ - Under a processor outage every instance retries in lockstep.
@@ -0,0 +1,31 @@
1
+ ---
2
+ rfc: 0003
3
+ title: Represent money as integer minor units
4
+ status: accepted
5
+ date: 2024-03-04
6
+ authors: [mira.okafor]
7
+ governs:
8
+ - src/payments/amount.ts
9
+ - src/payments/charge.ts
10
+ ---
11
+
12
+ # RFC-0003: Represent money as integer minor units
13
+
14
+ ## Problem
15
+
16
+ A refund of 19.99 was stored as 19.989999999999998 after a floating-point
17
+ round trip, and the ledger failed to reconcile.
18
+
19
+ ## Decision
20
+
21
+ All monetary amounts inside the service and on the wire are integers in the
22
+ currency's minor unit (cents for USD, pence for GBP), in a field named
23
+ `amountMinor`, paired with an ISO 4217 `currency` code. No decimal or
24
+ floating-point money fields anywhere in `src/payments/`. Conversion to a
25
+ display string happens only at the edge, via `formatAmount()` in
26
+ `src/payments/amount.ts`.
27
+
28
+ ## Consequences
29
+
30
+ - API consumers must send `amountMinor: 1999`, not `amount: 19.99`.
31
+ - Currencies with three minor digits (e.g. KWD) work without special cases.
@@ -0,0 +1,27 @@
1
+ ---
2
+ rfc: 0004
3
+ title: HMAC-SHA256 signatures on outbound webhooks
4
+ status: accepted
5
+ date: 2024-04-15
6
+ authors: [dev.raman]
7
+ governs:
8
+ - src/webhooks/sign.ts
9
+ ---
10
+
11
+ # RFC-0004: HMAC-SHA256 signatures on outbound webhooks
12
+
13
+ ## Problem
14
+
15
+ Merchants cannot tell a genuine `charge.succeeded` webhook from a forged one.
16
+
17
+ ## Decision
18
+
19
+ Every outbound webhook carries a `Ledgerline-Signature` header: an
20
+ HMAC-SHA256 of `timestamp + "." + body`, keyed with the merchant's webhook
21
+ secret. Signing is implemented in one place, `src/webhooks/sign.ts`, and every
22
+ sender must call `signPayload()` from it.
23
+
24
+ ## Consequences
25
+
26
+ - Merchants verify with a constant-time compare.
27
+ - Rotating a merchant secret invalidates in-flight retries.
@@ -0,0 +1,30 @@
1
+ ---
2
+ rfc: 0005
3
+ title: Exponential backoff with full jitter for processor retries
4
+ status: accepted
5
+ supersedes: 0002
6
+ date: 2024-06-03
7
+ authors: [dev.raman, mira.okafor]
8
+ governs:
9
+ - src/payments/retry.ts
10
+ ---
11
+
12
+ # RFC-0005: Exponential backoff with full jitter for processor retries
13
+
14
+ ## Problem
15
+
16
+ During the processor outage on 2024-05-21, RFC-0002's fixed 2-second retries
17
+ made all 40 instances hit the processor in synchronised waves, extending the
18
+ outage on our side by about 25 minutes.
19
+
20
+ ## Decision
21
+
22
+ Replace RFC-0002. Retry failed processor calls up to 4 times using
23
+ exponential backoff with full jitter: before attempt `n`, wait a random delay
24
+ between 0 and `min(8000, 250 * 2^n)` milliseconds. Never retry a 4xx response
25
+ from the processor.
26
+
27
+ ## Consequences
28
+
29
+ - Retries spread out; no lockstep under outage.
30
+ - Worst-case added latency is bounded at roughly 15 seconds.
@@ -0,0 +1,28 @@
1
+ ---
2
+ rfc: 0006
3
+ title: Move idempotency handling to the API gateway
4
+ status: proposed
5
+ date: 2024-09-30
6
+ authors: [tomas.vey]
7
+ governs:
8
+ - src/payments/charge.ts
9
+ ---
10
+
11
+ # RFC-0006: Move idempotency handling to the API gateway
12
+
13
+ ## Problem
14
+
15
+ Three services now implement their own idempotency-key tables, each slightly
16
+ differently.
17
+
18
+ ## Proposal
19
+
20
+ Enforce `Idempotency-Key` once at the API gateway and remove the per-service
21
+ checks, including the one RFC-0001 put in the charge handler.
22
+
23
+ ## Open questions
24
+
25
+ - The gateway team has not yet committed to a delivery date.
26
+ - How are responses replayed for keys the gateway has seen?
27
+
28
+ Not yet reviewed. Until this is accepted, RFC-0001 stands.
@@ -0,0 +1,27 @@
1
+ # PR #412 — "Simplify charge path" (author: tomas.vey)
2
+
3
+ Description from the author:
4
+ > Cleanup of the charge path. Retries are back to the simple policy from RFC-0002,
5
+ > which is much easier to reason about. Dedupe now happens in the retry layer so the
6
+ > header check in the handler is redundant. All in line with our RFCs.
7
+
8
+ ## Files changed
9
+
10
+ ### src/payments/charge.ts (+9 / -14)
11
+ - `ChargeRequest.amountMinor: number` renamed to `amount: number`; value is now
12
+ decimal major units (e.g. `19.99`) "to match what the mobile app sends".
13
+ - Removed the `Idempotency-Key` header check and the `idempotencyStore.get/put`
14
+ calls. Comment added: `// dedupe handled by retry layer`.
15
+ - `assertMinorUnits(req.amountMinor)` call removed.
16
+
17
+ ### src/payments/retry.ts (+6 / -12)
18
+ - `MAX_ATTEMPTS` 4 -> 3.
19
+ - Backoff replaced with a fixed `await sleep(2000)` between attempts.
20
+ - 4xx short-circuit kept.
21
+ - Header comment changed to `// Processor retry policy: RFC-0002`.
22
+
23
+ ### src/webhooks/sign.ts -> src/webhooks/signature.ts (rename, no content change)
24
+ - `send.ts` import updated to `./signature`.
25
+
26
+ ### src/webhooks/send.ts (+1 / -1)
27
+ - `console.log` replaced with `logger.info` (same fields).
@@ -0,0 +1,10 @@
1
+ // RFC-0003: money is integer minor units.
2
+ export function assertMinorUnits(amountMinor: number): void {
3
+ if (!Number.isInteger(amountMinor) || amountMinor < 0) {
4
+ throw new Error("amountMinor must be a non-negative integer");
5
+ }
6
+ }
7
+
8
+ export function formatAmount(amountMinor: number, currency: string, digits = 2): string {
9
+ return `${(amountMinor / 10 ** digits).toFixed(digits)} ${currency}`;
10
+ }
@@ -0,0 +1,28 @@
1
+ import { retryProcessorCall } from "./retry";
2
+ import { assertMinorUnits } from "./amount";
3
+ import { idempotencyStore } from "./idempotency";
4
+ import { sendWebhook } from "../webhooks/send";
5
+
6
+ export interface ChargeRequest {
7
+ amountMinor: number; // integer minor units, see RFC-0003
8
+ currency: string; // ISO 4217
9
+ cardToken: string;
10
+ }
11
+
12
+ export async function createCharge(req: ChargeRequest, headers: Record<string, string>) {
13
+ const key = headers["idempotency-key"];
14
+ if (!key) {
15
+ return { status: 400, body: { error: "Idempotency-Key header is required" } }; // RFC-0001
16
+ }
17
+ const previous = await idempotencyStore.get(key);
18
+ if (previous) return previous;
19
+
20
+ assertMinorUnits(req.amountMinor);
21
+ const result = await retryProcessorCall(() => processor.charge(req));
22
+ const response = { status: 201, body: result };
23
+ await idempotencyStore.put(key, response, 24 * 3600);
24
+ await sendWebhook("charge.succeeded", result);
25
+ return response;
26
+ }
27
+
28
+ declare const processor: { charge(req: ChargeRequest): Promise<unknown> };
@@ -0,0 +1,4 @@
1
+ export const idempotencyStore = {
2
+ async get(_key: string): Promise<any> { return undefined; },
3
+ async put(_key: string, _value: unknown, _ttlSeconds: number): Promise<void> {},
4
+ };
@@ -0,0 +1,21 @@
1
+ // Processor retry policy: RFC-0005 (supersedes RFC-0002).
2
+ const MAX_ATTEMPTS = 4;
3
+ const BASE_MS = 250;
4
+ const CAP_MS = 8000;
5
+
6
+ export async function retryProcessorCall<T>(fn: () => Promise<T>): Promise<T> {
7
+ let lastErr: unknown;
8
+ for (let n = 0; n < MAX_ATTEMPTS; n++) {
9
+ try {
10
+ return await fn();
11
+ } catch (err: any) {
12
+ if (err?.status >= 400 && err?.status < 500) throw err; // never retry 4xx
13
+ lastErr = err;
14
+ const ceiling = Math.min(CAP_MS, BASE_MS * 2 ** n);
15
+ await sleep(Math.random() * ceiling); // full jitter
16
+ }
17
+ }
18
+ throw lastErr;
19
+ }
20
+
21
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
@@ -0,0 +1,9 @@
1
+ import { signPayload } from "./sign";
2
+
3
+ export async function sendWebhook(event: string, payload: unknown): Promise<void> {
4
+ const body = JSON.stringify({ event, payload });
5
+ const ts = Math.floor(Date.now() / 1000);
6
+ const signature = signPayload(process.env.WEBHOOK_SECRET ?? "placeholder-secret", ts, body);
7
+ console.log("webhook", event, signature.slice(0, 8));
8
+ // HTTP delivery omitted in this excerpt
9
+ }
@@ -0,0 +1,6 @@
1
+ import { createHmac } from "crypto";
2
+
3
+ // RFC-0004: the single place outbound webhooks are signed.
4
+ export function signPayload(secret: string, timestamp: number, body: string): string {
5
+ return createHmac("sha256", secret).update(`${timestamp}.${body}`).digest("hex");
6
+ }
@@ -0,0 +1,14 @@
1
+ # Services deployed to the production cluster
2
+ services:
3
+ - name: shipments
4
+ path: services/shipments
5
+ datastores: [postgres:haulmark_core]
6
+ - name: telemetry
7
+ path: services/telemetry
8
+ datastores: [postgres:haulmark_telemetry]
9
+ - name: api
10
+ path: services/api
11
+ datastores: [postgres:haulmark_core]
12
+ - name: dashboard
13
+ path: web/dashboard
14
+ datastores: []
@@ -0,0 +1,20 @@
1
+ # 1. Record architecture decisions
2
+
3
+ Date: 2021-01-18
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ We need to record the architectural decisions made on Haulmark.
12
+
13
+ ## Decision
14
+
15
+ We will use Architecture Decision Records, as described by Michael Nygard,
16
+ kept in `doc/adr/`.
17
+
18
+ ## Consequences
19
+
20
+ See Michael Nygard's article "Documenting Architecture Decisions".
@@ -0,0 +1,23 @@
1
+ # 2. Use PostgreSQL for shipment data
2
+
3
+ Date: 2021-02-10
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ Shipments, stops and consignees are relational and need transactional
12
+ updates when a stop is marked delivered. The team already runs PostgreSQL 13.
13
+
14
+ ## Decision
15
+
16
+ Shipment data lives in a single PostgreSQL database, `haulmark_core`, owned by
17
+ `services/shipments/`. Other services read shipment data only through the
18
+ shipments API, never by connecting to the database directly.
19
+
20
+ ## Consequences
21
+
22
+ Strong consistency for status transitions. Schema migrations are needed for
23
+ new shipment fields.
@@ -0,0 +1,22 @@
1
+ # 3. Store vehicle telemetry in Cassandra
2
+
3
+ Date: 2021-06-02
4
+
5
+ ## Status
6
+
7
+ Superseded by [8. Store vehicle telemetry in TimescaleDB](0008-store-vehicle-telemetry-in-timescaledb.md)
8
+
9
+ ## Context
10
+
11
+ Each truck reports GPS position every 5 seconds. At 1,200 trucks this is
12
+ about 20 million rows a day, too much write volume for `haulmark_core`.
13
+
14
+ ## Decision
15
+
16
+ Vehicle telemetry is written to a 3-node Cassandra cluster by
17
+ `services/telemetry/`, partitioned by vehicle and day.
18
+
19
+ ## Consequences
20
+
21
+ High write throughput. Ad-hoc queries (e.g. "all trucks within 5 km of the
22
+ depot yesterday") are hard to express.
@@ -0,0 +1,22 @@
1
+ # 4. Use Redis for session storage
2
+
3
+ Date: 2021-07-19
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ The dispatcher web app needs server-side sessions shared across the API
12
+ instances in `services/api/`.
13
+
14
+ ## Decision
15
+
16
+ Sessions are stored in Redis with a 12-hour TTL, keyed by an opaque session
17
+ ID held in a cookie.
18
+
19
+ ## Consequences
20
+
21
+ One more piece of infrastructure to run. Logging out everywhere is a single
22
+ key delete.
@@ -0,0 +1,19 @@
1
+ # 5. Use React for the dispatcher dashboard
2
+
3
+ Date: 2021-09-06
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ The dispatcher dashboard is moving off server-rendered templates.
12
+
13
+ ## Decision
14
+
15
+ We will build the dashboard in React.
16
+
17
+ ## Consequences
18
+
19
+ The front-end team needs a separate build pipeline.
@@ -0,0 +1,23 @@
1
+ # 6. Archive delivered shipments to object storage
2
+
3
+ Date: 2022-03-14
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ `haulmark_core` has grown to 900 GB, most of it shipments delivered more
12
+ than a year ago that are only read for audits.
13
+
14
+ ## Decision
15
+
16
+ A nightly job in `services/archiver/` moves shipments delivered more than
17
+ 90 days ago out of `haulmark_core` into S3-compatible object storage as
18
+ Parquet files, one file per depot per day, and deletes them from PostgreSQL.
19
+
20
+ ## Consequences
21
+
22
+ `haulmark_core` stays small. Audit queries over archived shipments go
23
+ through the object store, not the shipments API.
@@ -0,0 +1,23 @@
1
+ # 7. Move shipment records to MongoDB
2
+
3
+ Date: 2022-08-22
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ Enterprise customers want custom fields on shipments (purchase order numbers,
12
+ temperature bands, hazmat codes) that differ per customer. Every new field
13
+ currently needs a PostgreSQL migration.
14
+
15
+ ## Decision
16
+
17
+ Shipment records will be stored as documents in MongoDB, owned by
18
+ `services/shipments/`, so per-customer fields need no schema migration.
19
+
20
+ ## Consequences
21
+
22
+ Status transitions that touch several stops lose multi-row transactions
23
+ unless we use MongoDB multi-document transactions.