docs: define Qlockify adaptation contract
This commit is contained in:
@@ -31,19 +31,21 @@ The approved product, data, analytics, identity, API, UX, and operations specifi
|
||||
2. Backend services: bounded demo authentication, metric query kernel, Redis/Asynq orchestration, details, exports, and provider integration.
|
||||
3. Backend HTTP surface: OpenAPI conformance, middleware, auth/period/run/SSE/retry/detail/CSV endpoints, audit, and hardening.
|
||||
4. Frontend: foundation and tokens, generated transport, shell/auth, dashboard sections, partial SSE states, detail/export workflows, responsive/accessibility/theme verification.
|
||||
5. Deployment: resolve concrete server inputs, construct Compose/Nginx/CI/backup operations, integrate first-start ordering, verify locally, then perform the separately authorized server release.
|
||||
5. Deployment: adapt Qlockify's Compose/Nginx/environment/manual-release/backup operations, integrate first-start ordering, verify locally with safe placeholders, then perform the separately authorized server release with real runtime values.
|
||||
|
||||
Backend provider work and frontend visual-system work can proceed in parallel after separate implementation authorization. Deployment scaffolding can also proceed in parallel once command/build contracts are stable; production bootstrap and cutover remain sequential gates.
|
||||
|
||||
## Remaining implementation inputs
|
||||
## Deferred interface details (not planning blockers)
|
||||
|
||||
These are build-time choices, not unresolved product requirements:
|
||||
|
||||
- exact pinned OpenAPI generation/validation tools and repository command wrappers;
|
||||
- exact frontend/backend build and health commands after their scaffolds exist (frontend history fallback is already restricted to non-API routes);
|
||||
- server SSH identity, Git access method, DNS/ACME email, hardware limits, registry/cache policy, backup bucket settings, and alert destinations;
|
||||
- exact backend/frontend command and environment-variable names after their scaffolds exist;
|
||||
- the hosting path for human-readable API problem pages.
|
||||
|
||||
Server IP/DNS state, Git credentials, ACME email, ParsPack values, operator identity, and alert destinations are runtime inputs supplied when their operations are performed. They do not block implementation planning or local placeholder-based validation. Deployment uses no CI/CD pipeline, runner, or registry.
|
||||
|
||||
No secrets, raw dataset, generated database, credentials, certificates, backups, or runtime volumes may be committed.
|
||||
|
||||
## Authorization gate
|
||||
|
||||
@@ -85,7 +85,7 @@ Any change to these decisions requires a spec revision before implementation.
|
||||
│ └── .git/
|
||||
├── docs/
|
||||
├── backups/ ignored runtime output
|
||||
└── deployment assets only after spec approval
|
||||
└── deployment assets only after explicit implementation authorization
|
||||
```
|
||||
|
||||
Each checkout keeps its own Git history and remote. Deployment operations verify the expected repository, branch, remote, clean state, and resolved absolute path before pulling, checking out, or building.
|
||||
@@ -499,16 +499,13 @@ Necessary changes include deployment root, archive/prefix names, Compose service
|
||||
- MVP can be operated through health, logs, release records, disk/certificate/backup checks without Prometheus/Grafana.
|
||||
- Prometheus/Grafana/exporters/dashboards/alerts are implemented and accepted after MVP readiness and before any AI implementation begins.
|
||||
|
||||
## Remaining implementation inputs
|
||||
## Implementation readiness
|
||||
|
||||
No stakeholder-level Platform Operations decisions remain. Implementation still consumes these concrete inputs without reopening the approved design:
|
||||
No stakeholder-level Platform Operations decisions or real server values are required to plan or implement the deployment artifacts. Follow `QLOCKIFY-ADAPTATION-CONTRACT.md` for the exact source-file mapping and root/backend/frontend environment ownership.
|
||||
|
||||
- the new server's public IP and DNS access
|
||||
- actual ZarinPal ParsPack endpoint/bucket/prefix credentials and separately protected encryption passphrase
|
||||
- backend/frontend build commands, health endpoints, migration/import/admin commands, and exact SSE path from their approved implementation contracts
|
||||
- the named operators allowed to perform deployment/restore and the off-server secret/configuration escrow location
|
||||
Tracked examples use blank secret placeholders and safe public defaults. The real server IP/DNS state, ParsPack values, operator identity, and secret values are runtime inputs supplied only when the relevant first-server or production operation is performed. Backend/frontend-owned command and variable names are consumed from their implementation contracts during the corresponding deployment slice; they do not reopen the approved topology or block earlier independent slices.
|
||||
|
||||
If an input would change an approved behavior rather than fill in a value/interface, amend this spec first.
|
||||
Implementation remains gated by explicit stakeholder authorization. If a discovered interface would change an approved behavior rather than fill in a service-owned command/value, amend this spec first.
|
||||
|
||||
## References
|
||||
|
||||
@@ -520,3 +517,4 @@ If an input would change an approved behavior rather than fill in a value/interf
|
||||
- PostgreSQL 18 backup/restore: <https://www.postgresql.org/docs/current/backup.html>
|
||||
- PostgreSQL dump/restore guidance: <https://www.postgresql.org/docs/current/backup-dump.html>
|
||||
- Local read-only Qlockify reference: `D:/Programing/Scripts/Qlockify/qlockify-deployment`
|
||||
- Local adaptation map: `docs/QLOCKIFY-ADAPTATION-CONTRACT.md`
|
||||
|
||||
134
docs/QLOCKIFY-ADAPTATION-CONTRACT.md
Normal file
134
docs/QLOCKIFY-ADAPTATION-CONTRACT.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# 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: Not granted
|
||||
- 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
|
||||
|
||||
```text
|
||||
/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:
|
||||
|
||||
```dotenv
|
||||
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.
|
||||
Reference in New Issue
Block a user