3.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
- 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 minimum-cohort, anonymized aggregates only.
- Treat
payer_card_keyas 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 UTCtimestamptz/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.
adjusted_feeis obfuscated and may be used only for relative analysis.
Go baseline after approval
- Keep
mainpackages thin undercmd/; business code lives underinternal/. - 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
COPYfor 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 an approved adaptive hash (Argon2id or bcrypt per the approved auth spec); sessions use secure, HttpOnly cookies and server-side revocation.
- 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.