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.
- package/README.md +1 -1
- package/catalogue.json +1 -0
- package/model-routing.json +1 -0
- package/package.json +1 -1
- package/packs/solution-architect/skills/context-graph/SKILL.md +119 -0
- package/packs/solution-architect/skills/context-graph/evals/eval_queries.json +11 -0
- package/packs/solution-architect/skills/context-graph/evals/evals.json +225 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0001-record-architecture-decisions.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0002-postgres-as-primary-database.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0003-use-redis-for-session-storage.md +24 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0004-structured-json-logging.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0005-session-lifetime-eight-hours.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0006-move-sessions-to-postgres.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/docs/adr/0007-stateless-signed-session-cookies.md +35 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/db.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/api/logging_setup.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/cookie_sessions.py +7 -0
- package/packs/solution-architect/skills/context-graph/evals/files/1/services/auth/redis_sessions.py +7 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/README.md +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0001-record-architecture-decisions.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0004-service-auth-hmac-shared-keys.md +21 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0007-secrets-from-vault-agent.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/docs/adr/0011-service-auth-mtls.md +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/app.py +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/__init__.py +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/auth/hmac_verify.py +31 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/billing-api/config/settings.py +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/__init__.py +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/10/services/ledger-worker/auth/mtls.py +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/README.md +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/base.py +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/line_item.py +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/app/models/order.py +24 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-003-money-as-minor-units.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-005-orders-typed-columns-only.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-009-line-items-immutable.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-014-optional-order-attributes-json.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/eng/decisions/DR-016-order-attributes-table.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0007_create_orders.sql +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/11/migrations/0012_add_order_attributes.sql +2 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/README.md +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/config/delivery.yaml +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/config/export.yaml +2 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/config/partners.yaml +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0001-record-architecture-decisions.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0002-postgres-delivery-log.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0003-redis-idempotency-keys.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0004-retry-policy.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0005-hmac-signed-payloads.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0006-postgres-idempotency.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0007-sftp-batch-export.md +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0008-partner-config-in-yaml.md +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/docs/adr/0009-partner-config-admin-api.md +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/003_idempotency_keys.sql +6 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/migrations/004_partners.sql +7 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/dispatcher.py +29 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/retry.py +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/delivery/signing.py +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/export/s3_export.py +24 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/pg_store.py +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/idempotency/redis_store.py +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/partners/loader.py +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/12/src/store/delivery_log.py +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/README.md +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/config/cache.yaml +2 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/config/settings.yaml +2 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-008-pricing-from-erp.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-012-pricing-cache.md +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-015-checkout-price-lock.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/docs/decisions/RFC-019-pricing-service.md +17 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/catalog/views.py +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/checkout/lock.py +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/cache.py +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/13/shopfront/pricing/client.py +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0001-idempotency-keys.md +33 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0002-processor-retry-policy.md +26 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0003-money-in-minor-units.md +31 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0004-webhook-signing.md +27 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0005-retry-with-jitter.md +30 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/docs/rfcs/0006-idempotency-at-gateway.md +28 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/pr-summary.md +27 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/amount.ts +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/charge.ts +28 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/idempotency.ts +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/payments/retry.ts +21 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/send.ts +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/14/src/webhooks/sign.ts +6 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/deploy/services.yaml +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0001-record-architecture-decisions.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0002-use-postgresql-for-shipment-data.md +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0003-store-vehicle-telemetry-in-cassandra.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0004-use-redis-for-session-storage.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0005-use-react-for-dispatcher-dashboard.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0006-archive-delivered-shipments-to-object-storage.md +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0007-move-shipment-records-to-mongodb.md +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0008-store-vehicle-telemetry-in-timescaledb.md +28 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/doc/adr/0009-stateless-sessions-with-signed-cookies.md +24 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/services/api/session.py +17 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/db.py +30 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/services/shipments/migrations.sql +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/services/telemetry/store.py +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/15/web/dashboard/App.jsx +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0001-record-architecture-decisions.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0002-rabbitmq-for-background-jobs.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0003-thumbnail-service.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0004-money-as-integer-minor-units.md +17 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0005-worker-retries.md +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0006-fx-amounts-with-four-decimals.md +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0007-feature-flags.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/docs/adr/0008-retire-legacy-search.md +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/libs/money/amount.py +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/flags.py +1 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/services/checkout/publish.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/services/media/resize.py +5 -0
- package/packs/solution-architect/skills/context-graph/evals/files/2/services/worker/consumer.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0001-how-we-write-rfcs.md +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0002-payments-service-boundary.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0003-webhook-retries-fixed-interval.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0004-webhook-idempotency-keys.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0005-notification-retries.md +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0006-webhook-retry-backoff.md +26 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/docs/rfcs/0007-webhooks-on-the-job-queue.md +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/notifications/retry.py +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/retry.py +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/3/services/payments/webhooks/send.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0001-record-architecture-decisions.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0002-postgres-as-system-of-record.md +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0004-redis-locks-for-scheduler.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0007-remove-redis.md +27 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/adr/0009-money-as-integer-minor-units.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/docs/onboarding.md +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/db/__init__.py +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/invoicing.py +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/money.py +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/__init__.py +0 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/lock.py +23 -0
- package/packs/solution-architect/skills/context-graph/evals/files/4/src/ledgerline/scheduler/runner.py +17 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/lib/types/index.ts +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0001-service-layout.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0003-ingest-retry-policy.md +26 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0006-shared-retry-library.md +24 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0008-outbound-http-client.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/client.ts +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/services/export/retry.ts +12 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/client.ts +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/5/services/ingest/retry.ts +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/README.md +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0001-monorepo-layout.md +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0002-billing-on-postgres.md +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0004-ledger-sync-nightly-batch.md +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0003-invoice-ids.md +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0007-invoice-ids-ulid.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0009-billing-event-store.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/docs/rfcs/RFC-0010-revenue-service.md +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/libs/money/ulid.py +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/events.py +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/store.py +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/services/invoicing/ids/generator.py +7 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/README.md +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/6/services/ledger/sync.py +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/README.md +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/db/queries/orders.sql +2 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/db/sharding/router.py +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-001-postgres-primary.md +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-002-kafka-event-bus.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-003-no-orm.md +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-006-tenant-sharding.md +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/design/decisions/DD-011-orm-for-admin-console.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/fanout/router.py +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/consumer.py +5 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/pipelines/ingest/topics.yaml +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/rfcs/0004-region-sharding.md +15 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/services/admin-console/models.py +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/7/services/orders/repo.py +9 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/README.md +11 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/api/ledger.proto +30 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/config/http.yaml +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/config/messaging.yaml +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0001-record-architecture-decisions.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0002-postgresql-for-ledger.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0003-rabbitmq-domain-events.md +22 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0004-integer-minor-units.md +32 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0005-provider-http-retries.md +26 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0006-openapi-generated-clients.md +20 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0007-kafka-domain-events.md +25 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/adr/0008-structured-logging.md +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/docs/rfcs/RFC-012-idempotency-keys.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/idempotency.py +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/api/server.py +35 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/clients/provider.py +33 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0001_init.sql +14 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0008_idempotency_keys.sql +5 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/db/migrations/0009_fx_entries.sql +4 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/events/publisher.py +28 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/logging.py +25 -0
- package/packs/solution-architect/skills/context-graph/evals/files/8/services/ledger/models/entry.py +16 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/.env.example +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/README.md +5 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/docker-compose.yml +18 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/001-session-storage.md +21 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/002-api-rate-limiting.md +32 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/003-jwt-sessions.md +29 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/docs/decisions/004-catalog-cache.md +19 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/cache.ts +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/catalog/repository.ts +13 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/email.ts +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/export.ts +3 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/queue.ts +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/jobs/worker.ts +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/db.ts +10 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/lib/redis.ts +8 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/middleware/rateLimit.ts +26 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/server.ts +17 -0
- package/packs/solution-architect/skills/context-graph/evals/files/9/src/session/store.ts +10 -0
- package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0004-kafka-for-order-events.md +19 -0
- package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0006-email-receipts.md +7 -0
- package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/docs/adr/0009-sqs-for-order-events.md +19 -0
- package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/notifications/receipts.py +0 -0
- package/packs/solution-architect/skills/context-graph/examples/inputs/order-events/services/orders/publisher.py +0 -0
- package/packs/solution-architect/skills/context-graph/examples/order-events.md +63 -0
- package/packs/solution-architect/skills/context-graph/manifest.json +33 -0
- package/packs/solution-architect/skills/context-graph/reference.md +104 -0
- 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()
|
package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0001-service-layout.md
ADDED
|
@@ -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.
|
package/packs/solution-architect/skills/context-graph/evals/files/5/rfcs/0003-ingest-retry-policy.md
ADDED
|
@@ -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));
|
package/packs/solution-architect/skills/context-graph/evals/files/6/docs/adr/0001-monorepo-layout.md
ADDED
|
@@ -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,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/`.
|
package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/events.py
ADDED
|
@@ -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
|
+
)
|
package/packs/solution-architect/skills/context-graph/evals/files/6/services/billing/src/store.py
ADDED
|
@@ -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,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.
|
package/packs/solution-architect/skills/context-graph/evals/files/7/rfcs/0004-region-sharding.md
ADDED
|
@@ -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
|
+
# 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,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.
|