Operations
1. Deployment
| Property | Value |
|---|---|
| Image | registry/taxation:<tag> (built from packages/taxation/Dockerfile) |
| Container Port | 3000 (external 31130) |
| Replicas | 1 (Snowflake worker id 13 is hardcoded — see warning) |
| Probes | GET /healthz (live), GET /readyz (ready) |
| Snowflake ID | 13 (APP_ENV_SNOWFLAKE_WORKER_ID) |
| Run modes | RUN_MODE=startup (app + CDC consumer) · RUN_MODE=migrate (seeds) |
| Migration mode | run-once bun run migrate job before/at boot |
Scale warning: worker id
13is hardcoded in env. Running >1 replica risks Snowflake id collisions. Multiple replicas also each run a CDC consumer in the same group — partition rebalance applies, but the id hazard is the blocker.
Traefik labels
yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.taxation.rule=PathPrefix(`/v1/api/taxation`)"
- "traefik.http.services.taxation.loadbalancer.server.port=3000"2. Observability
| Signal | Source | Where to look |
|---|---|---|
| Logs | stdout (structured key-value) | kubectl logs <pod> / Loki |
| Health | GET /healthz, GET /readyz | Gateway portal |
| Metrics | none package-specific | — |
| Traces | none | — |
Key log lines
| Scope | Notable lines |
|---|---|
ApplicationKafkaComponent | Connected/Disconnected to broker, Received message | Topic | Partition | Offset, Error processing message |
TaxationWorkerService | Handling product CDC | OP | After, DONE product CDC reconcile (provisioned/deprovisioned) |
TaxProvisioningService | START/DONE provision, SKIP provision — already provisioned, DEACTIVATED existing TaxSet |
TaxGroupService | VALIDATED | TaxGroup ... for Merchant ... |
3. Security
| Concern | Mitigation |
|---|---|
| AuthN | JWT (ES256, JWKS from identity) + HTTP Basic; strategies: ['jwt','basic'] on every route |
| AuthZ | Resource-based permissions seeded per controller; baseline grant to OWNER/EMPLOYEE/CASHIER |
| Secrets | env-mounted (APP_ENV_POSTGRES_PASSWORD, Kafka SASL creds); never in code |
| Kafka | SASL SCRAM-SHA-512 |
| Soft-delete | deletedAt — no hard-delete; deprovision uses status DEACTIVATED |
| No audit trail | Tax-config changes are not audited (unlike invoice's InvoiceAuditTracing) |
4. Runbook
4.1 Alert classes
| Alert | Trigger | Check | Fix | Escalate |
|---|---|---|---|---|
taxationCDCLag | products updated but no TaxSet change | logs Received message, consumer group lag | restart consumer; verify broker | on-call backend |
taxationProvisionErrors | TaxGroup not found / has no items errors | logs level=error in provisioning | verify seeds ran (migrate); check taxGroupId validity | on-call backend |
taxationMissingBackfill | products created while consumer down show no tax | — | manual POST /tax-provisioning/provision per product | on-call backend |
4.2 Common operations
| Operation | Command |
|---|---|
| Tail logs | kubectl logs -n <ns> -f deploy/taxation |
| Re-run seeds | bun run migrate (in pod, RUN_MODE=migrate) |
| Manual provision | POST /v1/api/taxation/tax-provisioning/provision { productId, taxGroupId } |
| Manual deprovision | POST /v1/api/taxation/tax-provisioning/deprovision { productId } |
| Replay product CDC | re-trigger a product update in commerce (no built-in replay job) |
No CDC backfill.
fallbackMode: latestmeans products changed before the consumer's offset window are never reprocessed. Recover via manual provisioning endpoints or by re-saving the product in commerce.
5. Related Pages
- Configuration
/runbook/— central runbook for cross-service incidents- Decisions