skilldrop-cli 0.16.45 → 0.16.46

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 (229) hide show
  1. package/catalogue.json +1 -0
  2. package/model-routing.json +1 -0
  3. package/package.json +1 -1
  4. package/packs/solution-architect/skills/context-graph/SKILL.md +119 -0
  5. package/packs/solution-architect/skills/context-graph/evals/eval_queries.json +11 -0
  6. package/packs/solution-architect/skills/context-graph/evals/evals.json +225 -0
  7. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0001-record-architecture-decisions.md +19 -0
  8. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0002-postgres-as-primary-database.md +16 -0
  9. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0003-use-redis-for-session-storage.md +24 -0
  10. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0004-structured-json-logging.md +15 -0
  11. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0005-session-lifetime-eight-hours.md +22 -0
  12. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0006-move-sessions-to-postgres.md +16 -0
  13. package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0007-stateless-signed-session-cookies.md +35 -0
  14. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/__init__.py +0 -0
  15. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/db.py +0 -0
  16. package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/logging_setup.py +0 -0
  17. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/__init__.py +0 -0
  18. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/cookie_sessions.py +7 -0
  19. package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/redis_sessions.py +7 -0
  20. package/packs/solution-architect/skills/context-graph/evals/files/10/README.md +8 -0
  21. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0001-record-architecture-decisions.md +10 -0
  22. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0004-service-auth-hmac-shared-keys.md +21 -0
  23. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0007-secrets-from-vault-agent.md +19 -0
  24. package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0011-service-auth-mtls.md +23 -0
  25. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/app.py +16 -0
  26. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/__init__.py +4 -0
  27. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/hmac_verify.py +31 -0
  28. package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/config/settings.py +14 -0
  29. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/__init__.py +4 -0
  30. package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/mtls.py +18 -0
  31. package/packs/solution-architect/skills/context-graph/evals/files/11/README.md +4 -0
  32. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/base.py +3 -0
  33. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/line_item.py +14 -0
  34. package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/order.py +24 -0
  35. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-003-money-as-minor-units.md +10 -0
  36. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-005-orders-typed-columns-only.md +10 -0
  37. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-009-line-items-immutable.md +11 -0
  38. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-014-optional-order-attributes-json.md +16 -0
  39. package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-016-order-attributes-table.md +11 -0
  40. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0007_create_orders.sql +11 -0
  41. package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0012_add_order_attributes.sql +2 -0
  42. package/packs/solution-architect/skills/context-graph/evals/files/12/README.md +8 -0
  43. package/packs/solution-architect/skills/context-graph/evals/files/12/config/delivery.yaml +4 -0
  44. package/packs/solution-architect/skills/context-graph/evals/files/12/config/export.yaml +2 -0
  45. package/packs/solution-architect/skills/context-graph/evals/files/12/config/partners.yaml +10 -0
  46. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0001-record-architecture-decisions.md +10 -0
  47. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0002-postgres-delivery-log.md +15 -0
  48. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0003-redis-idempotency-keys.md +15 -0
  49. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0004-retry-policy.md +16 -0
  50. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0005-hmac-signed-payloads.md +10 -0
  51. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0006-postgres-idempotency.md +15 -0
  52. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0007-sftp-batch-export.md +12 -0
  53. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0008-partner-config-in-yaml.md +12 -0
  54. package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0009-partner-config-admin-api.md +13 -0
  55. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/003_idempotency_keys.sql +6 -0
  56. package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/004_partners.sql +7 -0
  57. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/dispatcher.py +29 -0
  58. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/retry.py +15 -0
  59. package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/signing.py +13 -0
  60. package/packs/solution-architect/skills/context-graph/evals/files/12/src/export/s3_export.py +24 -0
  61. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/pg_store.py +11 -0
  62. package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/redis_store.py +8 -0
  63. package/packs/solution-architect/skills/context-graph/evals/files/12/src/partners/loader.py +15 -0
  64. package/packs/solution-architect/skills/context-graph/evals/files/12/src/store/delivery_log.py +18 -0
  65. package/packs/solution-architect/skills/context-graph/evals/files/13/README.md +3 -0
  66. package/packs/solution-architect/skills/context-graph/evals/files/13/config/cache.yaml +2 -0
  67. package/packs/solution-architect/skills/context-graph/evals/files/13/config/settings.yaml +2 -0
  68. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-008-pricing-from-erp.md +10 -0
  69. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-012-pricing-cache.md +23 -0
  70. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-015-checkout-price-lock.md +15 -0
  71. package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-019-pricing-service.md +17 -0
  72. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/catalog/views.py +8 -0
  73. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/checkout/lock.py +14 -0
  74. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/cache.py +22 -0
  75. package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/client.py +10 -0
  76. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0001-idempotency-keys.md +33 -0
  77. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0002-processor-retry-policy.md +26 -0
  78. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0003-money-in-minor-units.md +31 -0
  79. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0004-webhook-signing.md +27 -0
  80. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0005-retry-with-jitter.md +30 -0
  81. package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0006-idempotency-at-gateway.md +28 -0
  82. package/packs/solution-architect/skills/context-graph/evals/files/14/pr-summary.md +27 -0
  83. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/amount.ts +10 -0
  84. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/charge.ts +28 -0
  85. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/idempotency.ts +4 -0
  86. package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/retry.ts +21 -0
  87. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/send.ts +9 -0
  88. package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/sign.ts +6 -0
  89. package/packs/solution-architect/skills/context-graph/evals/files/15/deploy/services.yaml +14 -0
  90. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0001-record-architecture-decisions.md +20 -0
  91. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0002-use-postgresql-for-shipment-data.md +23 -0
  92. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0003-store-vehicle-telemetry-in-cassandra.md +22 -0
  93. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0004-use-redis-for-session-storage.md +22 -0
  94. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0005-use-react-for-dispatcher-dashboard.md +19 -0
  95. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0006-archive-delivered-shipments-to-object-storage.md +23 -0
  96. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0007-move-shipment-records-to-mongodb.md +23 -0
  97. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0008-store-vehicle-telemetry-in-timescaledb.md +28 -0
  98. package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0009-stateless-sessions-with-signed-cookies.md +24 -0
  99. package/packs/solution-architect/skills/context-graph/evals/files/15/services/api/session.py +17 -0
  100. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/db.py +30 -0
  101. package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/migrations.sql +3 -0
  102. package/packs/solution-architect/skills/context-graph/evals/files/15/services/telemetry/store.py +23 -0
  103. package/packs/solution-architect/skills/context-graph/evals/files/15/web/dashboard/App.jsx +3 -0
  104. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0001-record-architecture-decisions.md +11 -0
  105. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0002-rabbitmq-for-background-jobs.md +15 -0
  106. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0003-thumbnail-service.md +20 -0
  107. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0004-money-as-integer-minor-units.md +17 -0
  108. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0005-worker-retries.md +12 -0
  109. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0006-fx-amounts-with-four-decimals.md +18 -0
  110. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0007-feature-flags.md +16 -0
  111. package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0008-retire-legacy-search.md +14 -0
  112. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/__init__.py +0 -0
  113. package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/amount.py +9 -0
  114. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/flags.py +1 -0
  115. package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/publish.py +0 -0
  116. package/packs/solution-architect/skills/context-graph/evals/files/2/services/media/resize.py +5 -0
  117. package/packs/solution-architect/skills/context-graph/evals/files/2/services/worker/consumer.py +0 -0
  118. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0001-how-we-write-rfcs.md +9 -0
  119. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0002-payments-service-boundary.md +16 -0
  120. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0003-webhook-retries-fixed-interval.md +19 -0
  121. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0004-webhook-idempotency-keys.md +16 -0
  122. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0005-notification-retries.md +16 -0
  123. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0006-webhook-retry-backoff.md +26 -0
  124. package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0007-webhooks-on-the-job-queue.md +12 -0
  125. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/__init__.py +0 -0
  126. package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/retry.py +4 -0
  127. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/__init__.py +0 -0
  128. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/__init__.py +0 -0
  129. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/retry.py +15 -0
  130. package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/send.py +0 -0
  131. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0001-record-architecture-decisions.md +19 -0
  132. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0002-postgres-as-system-of-record.md +18 -0
  133. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0004-redis-locks-for-scheduler.md +19 -0
  134. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0007-remove-redis.md +27 -0
  135. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0009-money-as-integer-minor-units.md +19 -0
  136. package/packs/solution-architect/skills/context-graph/evals/files/4/docs/onboarding.md +12 -0
  137. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/__init__.py +0 -0
  138. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/db/__init__.py +22 -0
  139. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/invoicing.py +9 -0
  140. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/money.py +10 -0
  141. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/__init__.py +0 -0
  142. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/lock.py +23 -0
  143. package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/runner.py +17 -0
  144. package/packs/solution-architect/skills/context-graph/evals/files/5/lib/types/index.ts +13 -0
  145. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0001-service-layout.md +20 -0
  146. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0003-ingest-retry-policy.md +26 -0
  147. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0006-shared-retry-library.md +24 -0
  148. package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0008-outbound-http-client.md +22 -0
  149. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/client.ts +15 -0
  150. package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/retry.ts +12 -0
  151. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/client.ts +14 -0
  152. package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/retry.ts +20 -0
  153. package/packs/solution-architect/skills/context-graph/evals/files/6/README.md +4 -0
  154. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0001-monorepo-layout.md +10 -0
  155. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0002-billing-on-postgres.md +13 -0
  156. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0004-ledger-sync-nightly-batch.md +9 -0
  157. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0003-invoice-ids.md +9 -0
  158. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0007-invoice-ids-ulid.md +11 -0
  159. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0009-billing-event-store.md +15 -0
  160. package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0010-revenue-service.md +13 -0
  161. package/packs/solution-architect/skills/context-graph/evals/files/6/libs/money/ulid.py +8 -0
  162. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/events.py +10 -0
  163. package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/store.py +10 -0
  164. package/packs/solution-architect/skills/context-graph/evals/files/6/services/invoicing/ids/generator.py +7 -0
  165. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/README.md +4 -0
  166. package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/sync.py +3 -0
  167. package/packs/solution-architect/skills/context-graph/evals/files/7/README.md +4 -0
  168. package/packs/solution-architect/skills/context-graph/evals/files/7/db/queries/orders.sql +2 -0
  169. package/packs/solution-architect/skills/context-graph/evals/files/7/db/sharding/router.py +9 -0
  170. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-001-postgres-primary.md +8 -0
  171. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-002-kafka-event-bus.md +20 -0
  172. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-003-no-orm.md +9 -0
  173. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-006-tenant-sharding.md +9 -0
  174. package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-011-orm-for-admin-console.md +11 -0
  175. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/fanout/router.py +4 -0
  176. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/consumer.py +5 -0
  177. package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/topics.yaml +8 -0
  178. package/packs/solution-architect/skills/context-graph/evals/files/7/rfcs/0004-region-sharding.md +15 -0
  179. package/packs/solution-architect/skills/context-graph/evals/files/7/services/admin-console/models.py +11 -0
  180. package/packs/solution-architect/skills/context-graph/evals/files/7/services/orders/repo.py +9 -0
  181. package/packs/solution-architect/skills/context-graph/evals/files/8/README.md +11 -0
  182. package/packs/solution-architect/skills/context-graph/evals/files/8/api/ledger.proto +30 -0
  183. package/packs/solution-architect/skills/context-graph/evals/files/8/config/http.yaml +10 -0
  184. package/packs/solution-architect/skills/context-graph/evals/files/8/config/messaging.yaml +8 -0
  185. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0001-record-architecture-decisions.md +20 -0
  186. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0002-postgresql-for-ledger.md +22 -0
  187. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0003-rabbitmq-domain-events.md +22 -0
  188. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0004-integer-minor-units.md +32 -0
  189. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0005-provider-http-retries.md +26 -0
  190. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0006-openapi-generated-clients.md +20 -0
  191. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0007-kafka-domain-events.md +25 -0
  192. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0008-structured-logging.md +18 -0
  193. package/packs/solution-architect/skills/context-graph/evals/files/8/docs/rfcs/RFC-012-idempotency-keys.md +19 -0
  194. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/idempotency.py +19 -0
  195. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/server.py +35 -0
  196. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/clients/provider.py +33 -0
  197. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0001_init.sql +14 -0
  198. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0008_idempotency_keys.sql +5 -0
  199. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0009_fx_entries.sql +4 -0
  200. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/events/publisher.py +28 -0
  201. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/logging.py +25 -0
  202. package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/models/entry.py +16 -0
  203. package/packs/solution-architect/skills/context-graph/evals/files/9/.env.example +3 -0
  204. package/packs/solution-architect/skills/context-graph/evals/files/9/README.md +5 -0
  205. package/packs/solution-architect/skills/context-graph/evals/files/9/docker-compose.yml +18 -0
  206. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/001-session-storage.md +21 -0
  207. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/002-api-rate-limiting.md +32 -0
  208. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/003-jwt-sessions.md +29 -0
  209. package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/004-catalog-cache.md +19 -0
  210. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/cache.ts +13 -0
  211. package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/repository.ts +13 -0
  212. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/email.ts +3 -0
  213. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/export.ts +3 -0
  214. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/queue.ts +10 -0
  215. package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/worker.ts +8 -0
  216. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/db.ts +10 -0
  217. package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/redis.ts +8 -0
  218. package/packs/solution-architect/skills/context-graph/evals/files/9/src/middleware/rateLimit.ts +26 -0
  219. package/packs/solution-architect/skills/context-graph/evals/files/9/src/server.ts +17 -0
  220. package/packs/solution-architect/skills/context-graph/evals/files/9/src/session/store.ts +10 -0
  221. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0004-kafka-for-order-events.md +19 -0
  222. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0006-email-receipts.md +7 -0
  223. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0009-sqs-for-order-events.md +19 -0
  224. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/notifications/receipts.py +0 -0
  225. package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/orders/publisher.py +0 -0
  226. package/packs/solution-architect/skills/context-graph/examples/order-events.md +63 -0
  227. package/packs/solution-architect/skills/context-graph/manifest.json +33 -0
  228. package/packs/solution-architect/skills/context-graph/reference.md +104 -0
  229. package/packs/solution-architect/skills/context-graph/scripts/context_graph.py +634 -0
@@ -0,0 +1,17 @@
1
+ """Nightly invoice run entry point."""
2
+
3
+ from ledgerline.db import direct_connection
4
+ from ledgerline.scheduler.lock import invoice_run_lock
5
+ from ledgerline.invoicing import run_nightly
6
+
7
+
8
+ def main():
9
+ with direct_connection() as conn, invoice_run_lock(conn) as acquired:
10
+ if not acquired:
11
+ print("another worker holds the invoice-run lock; exiting")
12
+ return
13
+ run_nightly()
14
+
15
+
16
+ if __name__ == "__main__":
17
+ main()
@@ -0,0 +1,13 @@
1
+ export interface FeedEvent {
2
+ id: string;
3
+ kind: string;
4
+ occurredAt: string;
5
+ payload: Record<string, unknown>;
6
+ }
7
+
8
+ export interface Invoice {
9
+ id: string;
10
+ customerId: string;
11
+ amountMinor: number;
12
+ currency: string;
13
+ }
@@ -0,0 +1,20 @@
1
+ ---
2
+ id: RFC-0001
3
+ title: Service layout and shared code
4
+ status: accepted
5
+ date: 2024-11-02
6
+ authors: [Dara Mensah]
7
+ governs: [services/, lib/]
8
+ ---
9
+
10
+ # RFC-0001: Service layout and shared code
11
+
12
+ ## Decision
13
+
14
+ Each service under `services/<name>/` owns its own client, retry and error-handling code.
15
+ The only shared package is `lib/types/` (pure type definitions, no runtime behaviour).
16
+
17
+ ## Why
18
+
19
+ Ingest and export talk to different partners with different idempotency guarantees. A shared
20
+ runtime library would couple their failure behaviour and force lock-step releases.
@@ -0,0 +1,26 @@
1
+ ---
2
+ id: RFC-0003
3
+ title: Retry policy for the ingest service
4
+ status: accepted
5
+ date: 2025-03-11
6
+ authors: [Oskar Byrne]
7
+ governs: [services/ingest/retry.ts]
8
+ cites: [RFC-0001]
9
+ ---
10
+
11
+ # RFC-0003: Retry policy for the ingest service
12
+
13
+ ## Context
14
+
15
+ INC-114 (2025-02-27): the partner feed API returned 503 for four minutes. Every ingest worker
16
+ retried on a fixed 1 s interval, the retries stayed synchronised, and the partner rate-limited
17
+ our whole account for two hours after recovery.
18
+
19
+ ## Decision
20
+
21
+ Ingest retries use exponential backoff with full jitter: base 200 ms, cap 30 s, at most
22
+ 6 attempts. Fixed-interval retries are not allowed in ingest.
23
+
24
+ ## Consequences
25
+
26
+ Worst-case retry window is about 60 s per request. Dashboards alert on attempt 5+.
@@ -0,0 +1,24 @@
1
+ ---
2
+ id: RFC-0006
3
+ title: Extract a shared lib/retry package
4
+ status: rejected
5
+ date: 2025-06-19
6
+ authors: [Lucía Ferraro]
7
+ cites: [RFC-0001, RFC-0003]
8
+ ---
9
+
10
+ # RFC-0006: Extract a shared lib/retry package
11
+
12
+ ## Proposal
13
+
14
+ Move `services/ingest/retry.ts` and `services/export/retry.ts` into one `lib/retry/` package
15
+ with a single default policy.
16
+
17
+ ## Outcome: rejected
18
+
19
+ - Export calls to the partner billing API are NOT idempotent; export only retries on 503
20
+ responses that carry an `Idempotency-Key` echo. A single default policy would retry
21
+ unsafe calls.
22
+ - RFC-0001 keeps runtime code per service.
23
+
24
+ Revisit only if RFC-0001 is superseded.
@@ -0,0 +1,22 @@
1
+ ---
2
+ id: RFC-0008
3
+ title: One outbound HTTP client
4
+ status: accepted
5
+ date: 2025-09-30
6
+ authors: [Dara Mensah]
7
+ governs: [lib/http/, services/ingest/client.ts, services/export/client.ts]
8
+ amends: [RFC-0001]
9
+ cites: [RFC-0007]
10
+ ---
11
+
12
+ # RFC-0008: One outbound HTTP client
13
+
14
+ ## Decision
15
+
16
+ All outbound HTTP calls go through `lib/http/client.ts`. It sets timeouts, tracing headers and
17
+ applies retries uniformly (fixed 500 ms, 3 attempts). This amends RFC-0001 to allow `lib/http/`
18
+ as a second shared package. Idempotency keys are handled as described in RFC-0007.
19
+
20
+ ## Rollout
21
+
22
+ Services migrate their `client.ts` to `lib/http/` during Q4 2025.
@@ -0,0 +1,15 @@
1
+ import { retryIfSafe } from "./retry";
2
+ import type { Invoice } from "../../lib/types";
3
+
4
+ const BILLING_URL = process.env.PARTNER_BILLING_URL ?? "https://billing.partner.example/v1/invoices";
5
+
6
+ export async function pushInvoice(inv: Invoice, idempotencyKey: string): Promise<Response> {
7
+ return retryIfSafe(() =>
8
+ fetch(BILLING_URL, {
9
+ method: "POST",
10
+ headers: { "Content-Type": "application/json", "Idempotency-Key": idempotencyKey },
11
+ body: JSON.stringify(inv),
12
+ signal: AbortSignal.timeout(15_000),
13
+ }),
14
+ );
15
+ }
@@ -0,0 +1,12 @@
1
+ // Export retries are deliberately narrow: the billing API is not idempotent (RFC-0006).
2
+ const DELAY_MS = 1_000;
3
+ const MAX_ATTEMPTS = 3;
4
+
5
+ export async function retryIfSafe(fn: () => Promise<Response>): Promise<Response> {
6
+ for (let attempt = 1; ; attempt++) {
7
+ const res = await fn();
8
+ const safe = res.status === 503 && res.headers.has("Idempotency-Key");
9
+ if (!safe || attempt >= MAX_ATTEMPTS) return res;
10
+ await new Promise((r) => setTimeout(r, DELAY_MS));
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ import { withRetry } from "./retry";
2
+ import type { FeedEvent } from "../../lib/types";
3
+
4
+ const FEED_URL = process.env.PARTNER_FEED_URL ?? "https://feed.partner.example/v2/events";
5
+
6
+ export async function fetchEvents(cursor: string): Promise<FeedEvent[]> {
7
+ return withRetry(async () => {
8
+ const res = await fetch(`${FEED_URL}?cursor=${encodeURIComponent(cursor)}`, {
9
+ signal: AbortSignal.timeout(10_000),
10
+ });
11
+ if (!res.ok) throw new Error(`feed ${res.status}`);
12
+ return (await res.json()) as FeedEvent[];
13
+ });
14
+ }
@@ -0,0 +1,20 @@
1
+ // Ingest retry policy — RFC-0003. Do not change to a fixed interval (see INC-114).
2
+ const BASE_MS = 200;
3
+ const CAP_MS = 30_000;
4
+ const MAX_ATTEMPTS = 6;
5
+
6
+ export async function withRetry<T>(fn: () => Promise<T>): Promise<T> {
7
+ let attempt = 0;
8
+ for (;;) {
9
+ try {
10
+ return await fn();
11
+ } catch (err) {
12
+ attempt += 1;
13
+ if (attempt >= MAX_ATTEMPTS) throw err;
14
+ const ceiling = Math.min(CAP_MS, BASE_MS * 2 ** attempt);
15
+ await sleep(Math.random() * ceiling); // full jitter
16
+ }
17
+ }
18
+ }
19
+
20
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
@@ -0,0 +1,4 @@
1
+ # harbourline
2
+
3
+ Freight billing and invoicing platform. Monorepo: `services/` for deployables, `libs/` for shared code.
4
+ Decision records live in `docs/adr/` (architecture decision records) and `docs/rfcs/` (larger proposals).
@@ -0,0 +1,10 @@
1
+ # ADR-0001: Monorepo layout
2
+
3
+ - Status: Accepted
4
+ - Date: 2023-02-10
5
+ - Deciders: Platform team (H. Okafor, L. Brandt)
6
+ - Governs: `services/`, `libs/`
7
+
8
+ ## Decision
9
+ One repository. Each deployable service gets its own folder under `services/<name>/`; shared code goes
10
+ under `libs/`. A service folder is never shared by two deployables.
@@ -0,0 +1,13 @@
1
+ # ADR-0002: Billing data lives in Postgres
2
+
3
+ - Status: Accepted
4
+ - Date: 2023-05-03
5
+ - Deciders: H. Okafor, M. Szabo
6
+ - Governs: `services/billing/`
7
+
8
+ ## Decision
9
+ The billing service stores charges and the invoice ledger in the shared Postgres cluster
10
+ (table `invoices_ledger`). Writes are transactional updates in place.
11
+
12
+ ## Consequences
13
+ Reporting can join billing tables directly. Corrections overwrite the row and keep no history.
@@ -0,0 +1,9 @@
1
+ # ADR-0004: Ledger sync runs as a nightly batch
2
+
3
+ - Status: Accepted
4
+ - Date: 2023-09-12
5
+ - Deciders: L. Brandt
6
+ - Governs: `services/ledger-sync/`
7
+
8
+ ## Decision
9
+ Ledger sync to the finance system runs once a night at 02:00 UTC as a batch job, not as a stream.
@@ -0,0 +1,9 @@
1
+ # RFC-0003: Invoice identifiers
2
+
3
+ - Status: Accepted
4
+ - Date: 2023-06-20
5
+ - Author: M. Szabo
6
+ - Governs: `services/invoicing/ids/`
7
+
8
+ ## Proposal
9
+ Invoice IDs are sequential integers issued by a Postgres sequence, formatted `INV-000123`.
@@ -0,0 +1,11 @@
1
+ # RFC-0007: Switch invoice identifiers to ULIDs
2
+
3
+ - Status: Accepted
4
+ - Date: 2024-03-01
5
+ - Author: R. Achebe
6
+ - Supersedes: RFC-0003
7
+ - Governs: `services/invoicing/ids/`
8
+
9
+ ## Proposal
10
+ Sequential IDs leaked customer invoice volumes and forced a single writer. Invoice IDs become ULIDs,
11
+ generated in-process, formatted `INV-<ulid>`. Existing `INV-000123` IDs stay valid.
@@ -0,0 +1,15 @@
1
+ # RFC-0009: Billing writes go to an append-only event store
2
+
3
+ - Status: Accepted
4
+ - Date: 2024-08-14
5
+ - Author: R. Achebe
6
+ - Governs: `services/billing/`
7
+ - Builds on: RFC-0012 (event schema registry)
8
+
9
+ ## Proposal
10
+ Billing records every charge and correction as an immutable event in the DynamoDB table
11
+ `billing-events`. Current balances are projections of the event stream. This gives auditors a full
12
+ history of corrections.
13
+
14
+ ## Rollout
15
+ Phase 1: write events alongside the existing store. Phase 2: read balances from projections.
@@ -0,0 +1,13 @@
1
+ # RFC-0010: Merge billing and invoicing into a revenue service
2
+
3
+ - Status: Proposed
4
+ - Date: 2026-09-30
5
+ - Author: L. Brandt
6
+ - Governs: `services/revenue/` (new)
7
+
8
+ ## Proposal
9
+ Move `services/billing/` and `services/invoicing/` into a single deployable at `services/revenue/`,
10
+ with `billing/` and `invoicing/` as internal modules. Both old folders are deleted after the move.
11
+
12
+ ## Records affected
13
+ - ADR-0002 (billing storage) — path changes to `services/revenue/billing/`.
@@ -0,0 +1,8 @@
1
+ """Minimal ULID helper (placeholder implementation for the fixture)."""
2
+
3
+ import os
4
+ import time
5
+
6
+
7
+ def new_ulid():
8
+ return f"{int(time.time() * 1000):012x}{os.urandom(10).hex()}"
@@ -0,0 +1,10 @@
1
+ """Phase 1 of the event store rollout: append every charge as an event."""
2
+
3
+ EVENTS_TABLE = "billing-events"
4
+
5
+
6
+ def append_charge_event(client, invoice_id, amount_minor, at):
7
+ client.put_item(
8
+ TableName=EVENTS_TABLE,
9
+ Item={"invoice_id": invoice_id, "type": "charge", "amount_minor": amount_minor, "at": at},
10
+ )
@@ -0,0 +1,10 @@
1
+ """Billing persistence: in-place updates to the Postgres invoice ledger."""
2
+
3
+ LEDGER_TABLE = "invoices_ledger"
4
+
5
+
6
+ def record_charge(conn, invoice_id, amount_minor):
7
+ conn.execute(
8
+ f"UPDATE {LEDGER_TABLE} SET balance_minor = balance_minor + %s WHERE invoice_id = %s",
9
+ (amount_minor, invoice_id),
10
+ )
@@ -0,0 +1,7 @@
1
+ """Invoice ID generation."""
2
+
3
+ from libs.money.ulid import new_ulid
4
+
5
+
6
+ def new_invoice_id():
7
+ return f"INV-{new_ulid()}"
@@ -0,0 +1,4 @@
1
+ # ledger
2
+
3
+ Formerly `services/ledger-sync/` (renamed in 2025 when it gained the reconciliation report).
4
+ Still runs the nightly sync to the finance system at 02:00 UTC.
@@ -0,0 +1,3 @@
1
+ """Nightly ledger sync to the finance system."""
2
+
3
+ SCHEDULE_CRON = "0 2 * * *"
@@ -0,0 +1,4 @@
1
+ # fernwood
2
+
3
+ Multi-tenant data platform: ingest pipelines, an event bus, and the services on top.
4
+ Design decisions: `design/decisions/` (DD-nnn). Bigger proposals: `rfcs/`.
@@ -0,0 +1,2 @@
1
+ -- name: get_order
2
+ SELECT id, tenant_id, total_minor FROM orders WHERE id = %(id)s AND tenant_id = %(tenant_id)s;
@@ -0,0 +1,9 @@
1
+ """Pick the shard for a tenant (DD-006)."""
2
+
3
+ import hashlib
4
+
5
+ SHARD_COUNT = 16
6
+
7
+
8
+ def shard_for(tenant_id: str) -> int:
9
+ return int(hashlib.sha256(tenant_id.encode()).hexdigest(), 16) % SHARD_COUNT
@@ -0,0 +1,8 @@
1
+ # DD-001: Postgres is the primary datastore
2
+
3
+ Status: Accepted
4
+ Date: 2022-04-11
5
+ Deciders: O. Mensah
6
+ Governs: db/, services/
7
+
8
+ All service state lives in Postgres. No second OLTP database without a new decision.
@@ -0,0 +1,20 @@
1
+ # DD-002: Kafka is the event bus
2
+
3
+ Status: Accepted
4
+ Date: 2022-06-02
5
+ Deciders: O. Mensah, T. Lindqvist
6
+ Governs: pipelines/ingest/, pipelines/fanout/
7
+
8
+ ## Context
9
+ Ingest events must reach several independent consumers (fan-out, billing export, the audit sink),
10
+ and a consumer that is down for a deploy must be able to catch up afterwards.
11
+
12
+ ## Options considered
13
+ 1. Postgres LISTEN/NOTIFY — rejected: notifications are lost if no listener is connected at the
14
+ moment they fire, there is no replay, and payloads are capped at 8000 bytes.
15
+ 2. RabbitMQ — rejected: no long replay window without extra plugins.
16
+ 3. Kafka — chosen.
17
+
18
+ ## Decision
19
+ Use Kafka. Every topic keeps 7 days of retention so any consumer can replay a week of events.
20
+ Retention policy details: see DD-007.
@@ -0,0 +1,9 @@
1
+ # DD-003: No ORM in services
2
+
3
+ Status: Accepted
4
+ Date: 2022-07-19
5
+ Deciders: T. Lindqvist
6
+ Governs: services/
7
+
8
+ Services use hand-written SQL kept in db/queries/. No ORM: we want query plans reviewable in code
9
+ review and no lazy-loading surprises on hot paths.
@@ -0,0 +1,9 @@
1
+ # DD-006: Shard by tenant
2
+
3
+ Status: Accepted
4
+ Date: 2023-01-30
5
+ Deciders: Platform guild (O. Mensah, R. Vidal)
6
+ Governs: db/sharding/
7
+
8
+ Each tenant's data lives on exactly one shard, chosen by a hash of tenant_id. Cross-tenant queries
9
+ go through the reporting replica, never the shards.
@@ -0,0 +1,11 @@
1
+ # DD-011: Allow SQLAlchemy in the admin console
2
+
3
+ Status: Accepted
4
+ Date: 2024-05-08
5
+ Deciders: R. Vidal
6
+ Amends: DD-003
7
+ Governs: services/admin-console/
8
+
9
+ The admin console is internal, low-traffic CRUD over ~40 tables. Hand-written SQL there cost more
10
+ than it saved. SQLAlchemy is allowed in services/admin-console/ only. Every other service keeps
11
+ DD-003's no-ORM rule.
@@ -0,0 +1,4 @@
1
+ """Fans ingest.normalised out to downstream consumers."""
2
+
3
+ GROUP_ID = "fanout-router"
4
+ SOURCE_TOPIC = "ingest.normalised"
@@ -0,0 +1,5 @@
1
+ """Reads ingest.raw, normalises records, publishes to ingest.normalised."""
2
+
3
+ GROUP_ID = "ingest-normaliser"
4
+ SOURCE_TOPIC = "ingest.raw"
5
+ SINK_TOPIC = "ingest.normalised"
@@ -0,0 +1,8 @@
1
+ # Kafka topic config for ingest
2
+ topics:
3
+ - name: ingest.raw
4
+ partitions: 12
5
+ retention.ms: 259200000
6
+ - name: ingest.normalised
7
+ partitions: 12
8
+ retention.ms: 259200000
@@ -0,0 +1,15 @@
1
+ # RFC 0004: Shard by region instead of tenant
2
+
3
+ Status: Withdrawn
4
+ Date: 2025-02-14
5
+ Author: P. Tamboli
6
+ Supersedes: DD-006
7
+ Governs: db/sharding/
8
+
9
+ ## Proposal
10
+ Move from tenant sharding to region sharding (eu, us, apac) so data-residency rules map to shards.
11
+
12
+ ## Withdrawal note (2025-03-20)
13
+ Withdrawn after the cost review: re-sharding every tenant was estimated at two quarters of work and
14
+ residency can be met by pinning tenants to regional shards under the existing scheme. Tenant
15
+ sharding (DD-006) stays.
@@ -0,0 +1,11 @@
1
+ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
2
+
3
+
4
+ class Base(DeclarativeBase):
5
+ pass
6
+
7
+
8
+ class Tenant(Base):
9
+ __tablename__ = "tenants"
10
+ id: Mapped[int] = mapped_column(primary_key=True)
11
+ name: Mapped[str]
@@ -0,0 +1,9 @@
1
+ """Orders persistence. SQL lives in db/queries/orders.sql."""
2
+
3
+ from pathlib import Path
4
+
5
+ QUERIES = Path(__file__).resolve().parents[2] / "db" / "queries" / "orders.sql"
6
+
7
+
8
+ def load_queries():
9
+ return QUERIES.read_text()
@@ -0,0 +1,11 @@
1
+ # harbor-ledger
2
+
3
+ Double-entry ledger service for the Harbor payments platform.
4
+
5
+ - `services/ledger/` — the ledger service (Python)
6
+ - `api/` — service interface definitions
7
+ - `config/` — runtime configuration
8
+ - `docs/adr/` — architecture decision records
9
+ - `docs/rfcs/` — proposals under discussion
10
+
11
+ `services/ledger/api/gen/` is generated from `api/ledger.proto` at build time and is not checked in.
@@ -0,0 +1,30 @@
1
+ syntax = "proto3";
2
+
3
+ package harbor.ledger.v1;
4
+
5
+ // Public interface of the ledger service. Client stubs are generated from this file.
6
+ service Ledger {
7
+ rpc PostEntry(PostEntryRequest) returns (PostEntryResponse);
8
+ rpc GetBalance(GetBalanceRequest) returns (Balance);
9
+ }
10
+
11
+ message PostEntryRequest {
12
+ string idempotency_key = 1;
13
+ string account_id = 2;
14
+ int64 amount_minor = 3;
15
+ string currency = 4;
16
+ }
17
+
18
+ message PostEntryResponse {
19
+ string entry_id = 1;
20
+ }
21
+
22
+ message GetBalanceRequest {
23
+ string account_id = 1;
24
+ }
25
+
26
+ message Balance {
27
+ string account_id = 1;
28
+ int64 balance_minor = 2;
29
+ string currency = 3;
30
+ }
@@ -0,0 +1,10 @@
1
+ # Outbound HTTP settings for the payment-provider client
2
+ provider:
3
+ base_url: https://provider.example.invalid/v2
4
+ timeout_seconds: 30
5
+ max_retries: 5
6
+ backoff:
7
+ base_ms: 200
8
+ jitter: full
9
+ retry_methods: [GET, POST]
10
+ api_key: REPLACE_ME
@@ -0,0 +1,8 @@
1
+ # Domain event publishing
2
+ broker: kafka
3
+ bootstrap_servers:
4
+ - kafka-0.harbor.internal:9092
5
+ - kafka-1.harbor.internal:9092
6
+ topic: ledger.entry-events
7
+ key: account_id
8
+ acks: all
@@ -0,0 +1,20 @@
1
+ # 1. Record architecture decisions
2
+
3
+ Date: 2024-01-10
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ We need to record the architectural decisions made on this project.
12
+
13
+ ## Decision
14
+
15
+ We will use Architecture Decision Records, as described by Michael Nygard, kept in `docs/adr/`.
16
+ Larger proposals that need discussion first go in `docs/rfcs/` and become an ADR once accepted.
17
+
18
+ ## Consequences
19
+
20
+ See Michael Nygard's article for a detailed description of the process.
@@ -0,0 +1,22 @@
1
+ # 2. Use PostgreSQL for ledger storage
2
+
3
+ Date: 2024-01-22
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ The ledger needs transactional writes across journal entries and account balances, and the
12
+ team already operates PostgreSQL for two other services.
13
+
14
+ ## Decision
15
+
16
+ Ledger state lives in PostgreSQL. Schema changes are plain SQL migrations under
17
+ `services/ledger/db/migrations/`, numbered sequentially and never edited once merged.
18
+
19
+ ## Consequences
20
+
21
+ - Balances are computed inside a transaction with the entries that change them.
22
+ - No ORM-generated migrations.
@@ -0,0 +1,22 @@
1
+ # 3. Publish domain events over RabbitMQ
2
+
3
+ Date: 2024-02-14
4
+
5
+ ## Status
6
+
7
+ Accepted
8
+
9
+ ## Context
10
+
11
+ Downstream services (notifications, reporting) need to react when entries are posted.
12
+
13
+ ## Decision
14
+
15
+ The ledger publishes `EntryPosted` and `AccountFrozen` events to a RabbitMQ topic exchange
16
+ named `ledger.events`. Publishing code lives in `services/ledger/events/`. Broker settings
17
+ are in `config/messaging.yaml`.
18
+
19
+ ## Consequences
20
+
21
+ - Consumers bind their own queues; the ledger does not know who listens.
22
+ - Events are at-least-once; consumers must be idempotent.