Files
zarinpal-analytics-deployment/docs/QLOCKIFY-ADAPTATION-CONTRACT.md

8.7 KiB

Qlockify deployment adaptation contract

  • Status: Approved planning baseline
  • Source: D:/Programing/Scripts/Qlockify/qlockify-deployment (read-only)
  • Target: /home/ubuntu/zarinpal-analytics-deployment
  • Implementation authorization: Granted by user on 2026-08-20
  • Last updated: 2026-08-20

Purpose

Use Qlockify's proven single-server deployment shape and environment-file layout for ZarinPal Analytics without requiring production IPs, credentials, or operator names during planning. Real values are supplied on the server when deployment occurs; they are not planning blockers and never enter public Git.

Repository layout

/home/ubuntu/zarinpal-analytics-deployment/
├── .env                         ignored deployment/TLS/backup values
├── backend/                     ignored backend Git checkout
│   └── .env                     ignored backend/runtime values
├── frontend/                    ignored frontend Git checkout
│   └── .env                     ignored public build values only
├── data/incoming/               ignored one-time CSV input
├── data/reports/                ignored import reports
├── releases/                    ignored non-secret release records
└── backups/                     ignored encrypted local backups

This deliberately simplifies Qlockify's extra application subdirectory layer. Each service checkout is directly under the deployment root and keeps an independent .git directory.

File adaptation matrix

Qlockify source Planned ZarinPal artifact Adaptation
.env.sample .env.example Keep TLS and ParsPack variable names; use the ZarinPal domain/prefix; remove alternate-domain and duplicate database values.
backend/.env.sample backend-owned .env.example, consumed as backend/.env Replace Django, JWT, Celery, OAuth, SMS, and demo-cleanup variables with the Go API/worker/import contracts.
frontend/.env.sample frontend-owned .env.example, consumed as frontend/.env Keep only public same-origin build configuration; never place a secret here.
docker-compose.yml compose.yaml Keep single-host orchestration and nested build contexts; replace Django/Celery/media services with API, worker, migrate, importer, and admin boundaries.
backend/Dockerfile deployment backend image definition Build the backend checkout once and select API/worker/migrate/import/admin commands from the same recorded backend revision.
frontend/Dockerfile deployment frontend image definition Build the ordinary frontend checkout, including its tracked font and license.
nginx/* nginx/* Keep HTTP-01, automatic renewal, temporary bootstrap certificate, and reload flow; use only zarinpal.amiirkhl.ir and ZarinPal routes.
scripts/deploy.sh scripts/deploy.sh plus release-record helper Keep manual Compose build/start structure; Git pulls happen interactively before the script; remove fetch/reset and partial-repository release selection.
scripts/backup.sh scripts/backup.sh Keep plain-SQL pg_dump and temporary archive structure; include PostgreSQL plus non-secret manifest/checksums only.
scripts/backup-upload-s3.sh same filename Keep root .env loading, OpenSSL/rclone flow, ParsPack support, and 3/7 retention; retain encrypted local artifacts.
scripts/restore.sh same filename Keep plain-SQL restore basis; remove env/media restore and add empty-target plus production guards.
scripts/restore-from-s3.sh same filename Keep rclone/decrypt handoff; require an explicit object id for production and validate it before restore.
.gitea/workflows/* none Do not port. ZarinPal deployment is manual and has no CI/CD pipeline or runner.

Environment layout

Future tracked examples contain placeholders or safe public defaults only. Production files are Git-ignored, owned by ubuntu, mode 0600, excluded from backup, and loaded without printing resolved values.

Deployment root .env

The future .env.example uses this deployment-owned contract:

COMPOSE_PROJECT_NAME=zarinpal_analytics

SSL_CERT_MODE=letsencrypt
LETSENCRYPT_EMAIL=
PRIMARY_DOMAIN=zarinpal.amiirkhl.ir
CERTBOT_STAGING=0

S3_BACKUP_BUCKET=
S3_BACKUP_PREFIX=backup/zarinpal-analytics
S3_BACKUP_ENDPOINT_URL=
S3_BACKUP_ACCESS_KEY_ID=
S3_BACKUP_SECRET_ACCESS_KEY=
BACKUP_ENCRYPTION_PASSPHRASE=
BACKUP_LOCAL_KEEP_LATEST=3
BACKUP_REMOTE_KEEP_LATEST=7

There is no ALT_DOMAINS, runner, registry, deploy-host, SSH-key, or CI variable. The endpoint, bucket, email, access keys, and passphrase may remain blank in the tracked example; the future validation command requires them only for the operation that consumes them.

Backend backend/.env

The backend repository owns the complete Go application example. Deployment requires these semantic groups and consumes their eventual exact backend-owned names without maintaining a second competing template:

  • production mode and structured-log level
  • API listen address and public origin https://zarinpal.amiirkhl.ir
  • POSTGRES_HOST=postgres, port 5432, database/user/password
  • REDIS_HOST=redis, port 6379, password, and database selection required by the backend/Asynq contract
  • session/cookie secrets and secure same-origin cookie settings
  • analytics TTL, rate limits, worker concurrency 16, per-merchant concurrency 4, 60-second attempt timeout, and retry policy
  • import source/report paths, schema version, readiness timeout, and bounded batch/resource settings

The same protected file supplies PostgreSQL, Redis, API, worker, migrate, importer, and admin services only with the variables each service needs. Qlockify-only Django, JWT, Celery, Google OAuth, SMS, demo-environment, media, and scheduled-cleanup variables are not carried over.

Frontend frontend/.env

The frontend repository owns its exact public variable name. Its production value is the same-origin API prefix, initially /api/v1. No database, Redis, session, backup, AvalAI, or other secret is allowed in this file or the browser bundle.

Manual deployment flow

  1. The operator manually runs git pull --ff-only origin main in deployment, backend, and frontend checkouts and enters source-forge credentials interactively.
  2. The future deploy command acquires the operation lock and verifies exact paths, remotes, main, equality with origin/main, and clean trees. It performs no Git fetch, pull, checkout, or reset.
  3. It records all three commit hashes and validates the root/backend/frontend environment contracts without printing values.
  4. It validates Compose, builds from the three recorded revisions, starts data services, runs the one-off migration, and replaces application services only after the required gates pass.
  5. It validates private readiness plus public TLS/routing/font/SSE behavior, observes for 15 minutes, then marks the release active.
  6. Rollback selects the prior release's three hashes, rebuilds, and re-runs the same checks. It never automatically reverses a migration.

The ordinary deployment path never invokes CSV import or credential generation. The first server uses the separately planned first-start.sh path after migration and before the first public activation.

Always / Ask / Never

Always

  • Adapt from the named tracked Qlockify source file and record intentional differences.
  • Keep all three real .env files ignored, mode 0600, and out of backups/logs.
  • Validate only the variables needed by the requested operation.
  • Preserve exact-path guards before any mutation, cleanup, restore, or retention action.

Ask first

  • Rename a deployment-owned variable after implementation begins.
  • Add a public origin/domain, external provider, persistent data class, or secret consumer.
  • Change the manual three-repository release rule or Qlockify-derived backup encryption/retention contract.

Never

  • Port Qlockify's Gitea workflows, runner/deploy-key variables, or automated deployment.
  • Port Qlockify's destructive git reset --hard synchronization.
  • Copy Qlockify credentials, domains, database names, service names, or secret values.
  • Back up or restore .env files, Redis, TLS keys, raw CSV, credentials, logs, or frontend assets.
  • Create a second font path or private asset-injection workflow.

Planning acceptance

  • Every future deployment artifact maps to a named Qlockify source or a documented ZarinPal-only requirement.
  • Root/backend/frontend environment ownership is unambiguous and has no duplicate secret source.
  • Tracked examples can be committed with blank secret placeholders and useful safe defaults.
  • Planning and local validation do not require a server IP, real DNS access, real ParsPack values, or named operators.
  • Real values are required only at the first-server or operation-specific execution gate.