Files
zarinpal-analytics-backend/AGENTS.md

4.9 KiB

Backend Agent Operating Contract

Phase gate

This repository is in specification mode. Do not create go.mod, application packages, migrations, containers, or executable code until the relevant capability spec is approved.

For every Go-related task, always invoke and follow the golang-how-to skill, then the secondary Go skills it routes to. Before creating the Go project layout, ask the user to approve the architecture style and dependency-injection approach in that order.

Product invariants

  • Use the canonical domain terms in CONTEXT.md; update that glossary when a term's meaning is approved, without adding implementation details to it.
  • The backend is the authority for authentication, authorization, tenant isolation, metric definitions, and data provenance.
  • Every merchant-scoped query derives merchant identity from the authenticated server-side session; never trust a client-supplied merchant identifier as authorization.
  • Cross-merchant results are anonymized same-category aggregates only. Exclude the active merchant and suppress the benchmark unless at least 10 other merchants and 1,000 combined peer sessions contribute in the selected period. Use one value per peer merchant to calculate the cohort median and direction-aware performance percentile; never transaction-weight by default.
  • Treat payer_card_key as an opaque, merchant-scoped source token with unverified upstream semantics. Retain it unchanged only for internal deterministic analytics; never expose it through merchant APIs, logs, exports, or AI inputs, and never describe it as a card number or verified person identifier.
  • Use integer minor currency units or an explicitly documented fixed-precision representation; never floating point for money.
  • Interpret timezone-naive challenge timestamps as Asia/Tehran, preserve their source provenance, and normalize canonical database/API timestamps to UTC timestamptz/ISO 8601. Any change to this assumption requires a new import version and ADR.
  • Raw imports are immutable inputs; corrections are new import versions, not silent mutation.
  • CSV ingestion is a one-time bootstrap/recovery command only. Never add a file watcher, polling schedule, recurring CSV ETL, or ownership of ZarinPal's production writes without a new approved spec.
  • Treat source adjusted_fee as the merchant's real fee for this product. Normalize it once per session as fee_amount_rial; do not sum the repeated attempt-row value.
  • Treat both Paid and Verified as successful bank payments. Paid still requires merchant verification; Verified is finalized. Never classify Paid as failure.

Go baseline after approval

  • Keep main packages thin under cmd/; business code lives under internal/.
  • Wire dependencies manually with explicit constructors at the composition root. Do not introduce a DI container or code generator unless a later ADR documents measured wiring/lifecycle complexity.
  • Use explicit constructors; avoid init() side effects and mutable globals.
  • Configuration comes from validated environment variables. Logs go to stdout as structured records without credentials, card keys, or sensitive payloads.
  • Propagate context.Context; bound external calls, queues, batches, and database pools.
  • Use parameterized queries and transactions with explicit boundaries. Stream/bulk-load the multi-million-row input instead of holding it in memory.
  • Use Ent for application persistence and relationship modeling. Use pgx with PostgreSQL COPY for the bulk-import staging path; do not force high-volume ingestion through row-by-row ORM operations.
  • Database migrations are explicit, versioned, reviewed artifacts applied by a dedicated migration/deployment step. Never run Ent automatic schema creation against production during application startup.
  • Passwords use Argon2id with reviewed parameters and a unique salt. Sessions are server-side and revocable; browsers receive only an opaque token in a Secure, HttpOnly, SameSite=Lax cookie. Never put authentication tokens in browser storage.
  • Required verification includes unit/integration tests, race detection where applicable, go vet, golangci-lint, govulncheck, and migration/import tests.

Git and documentation

  • Use atomic Conventional/Commitizen commits.
  • Track specs, ERD/schema definitions, migrations, importer code, validation rules, manifests/templates, and runbooks.
  • Ignore raw CSV archives, database volumes/dumps, credentials, and generated runtime data.
  • Changes to a metric, API, schema, authorization rule, or AI data boundary require the corresponding spec/ADR update.

AI boundary (post-MVP)

AvalAI is accessed only from the backend using a server-held API key. Prefer the simplest bounded LLM call/workflow that satisfies the approved use case. Send minimized, sanitized aggregates with explicit budgets/timeouts; persist trace metadata and deterministic inputs, not unnecessary sensitive prompts. AI output is advisory and must cite underlying deterministic metrics.