refactor: lay the repository out by role
All checks were successful
Build and deploy / Validate source (push) Successful in 7s
Build and deploy / Integration suite on a real stack (push) Successful in 1m25s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images and notify Portainer (push) Successful in 1m31s
All checks were successful
Build and deploy / Validate source (push) Successful in 7s
Build and deploy / Integration suite on a real stack (push) Successful in 1m25s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images and notify Portainer (push) Successful in 1m31s
local/ held six unrelated things under a name that stopped being true once it
became the production runtime: the service, the frontend, the tests, the ops
commands, the container definitions and the dependency lock, 65 files with
nothing to tell them apart.
app/ the service: api/ routers, core/ for identity, database, models,
prices and secret loading, and the worker, bootstrap and schema
tests/ the twelve suites, no longer inside the shipped package
ops/ backup, readiness, dependency audit, security summary
infra/ Dockerfiles, gateway templates, ClamAV and storage configuration,
the requirements and their hash lock
web/ the Site, Kanban and portal pages with their scripts
deploy/Dockerfile.api now copies app/ alone, so the tests stop shipping to
production; the local image still carries them, because the suites run inside
the stack's network.
Five kinds of reference had to follow, and each was found by something different
rather than by reading. Imports of the form "from . import db" survived a rewrite
that only matched "from .db import". Tests kept relative imports of modules that
had left the package. A mock.patch target names its module in a string, where no
import rewriting can see it. The browser test resolves a fixture by path. And the
release gate's markers pointed at local/runtime.py and local/worker.py, which is
the decay its new marker test exists to catch — it caught it.
Verified from docker compose down -v: the stack starts, all six integration
suites, both browser suites and the twenty-nine unit tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# DTF local development
|
||||
|
||||
Read `CONTEXT.md` first. The current runtime lives in `local/`; older portal,
|
||||
Read `CONTEXT.md` first. The service lives in `app/`; older portal,
|
||||
Kanban, agent, requirements, and SQL files are historical prototypes.
|
||||
|
||||
## Start
|
||||
@@ -51,7 +51,7 @@ operator interfaces.
|
||||
## Browser test order
|
||||
|
||||
1. Open the Site. Choose **Arquivo por metro** and the manual/table-price path
|
||||
(CDR/AI/PSD/TIFF). Select `local/fixtures/local-test.cdr`. This is deliberately
|
||||
(CDR/AI/PSD/TIFF). Select `tests/fixtures/local-test.cdr`. This is deliberately
|
||||
harmless text for upload testing, not a printable CDR file.
|
||||
2. Enter **1.01 metres**. The original calculation bills **1.10 m × R$19.90 =
|
||||
R$21.89**, with grade 0 and pickup. You can also use your own non-sensitive
|
||||
@@ -142,8 +142,8 @@ pricing, plus assembly and invalid-input checks.
|
||||
With the stack healthy, run the integration test (Python standard library only):
|
||||
|
||||
```bash
|
||||
python3 -m local.smoke_test
|
||||
python3 -m local.workflow_test
|
||||
python3 -m tests.smoke_test
|
||||
python3 -m tests.workflow_test
|
||||
```
|
||||
|
||||
It checks direct two-part upload/resume, missing parts, session isolation,
|
||||
@@ -159,10 +159,10 @@ Security and malware regressions are separate so an authorized harmless EICAR
|
||||
test is unmistakable:
|
||||
|
||||
```bash
|
||||
python3 -m local.security_test
|
||||
python3 -m local.scanning_test
|
||||
docker compose exec -T api python -m local.runtime_security_test
|
||||
docker compose exec -T api python -m local.retention_test
|
||||
python3 -m tests.security_test
|
||||
python3 -m tests.scanning_test
|
||||
docker compose exec -T api python3 -m tests.runtime_security_test
|
||||
docker compose exec -T api python3 -m tests.retention_test
|
||||
```
|
||||
|
||||
`local.scanning_test` stores an EICAR fixture as `SECURITY-EICAR.cdr`; ClamAV
|
||||
@@ -172,7 +172,7 @@ is retained for at most three days, so it temporarily appears in alert summaries
|
||||
For an automated real-browser walkthrough, install Chrome and use Node 22+:
|
||||
|
||||
```bash
|
||||
node local/browser_test.mjs
|
||||
node tests/browser_test.mjs
|
||||
```
|
||||
|
||||
Set `CHROME_BIN` if Chrome is not at `/usr/bin/google-chrome-stable`. The test
|
||||
@@ -217,7 +217,7 @@ again. The operator can still inspect order records.
|
||||
## Local backup and restore check
|
||||
|
||||
```bash
|
||||
python3 -m local.backup create-and-verify
|
||||
python3 -m app.backup create-and-verify
|
||||
```
|
||||
|
||||
This writes a private four-file bundle in `backups/` (ignored by Git and Docker
|
||||
@@ -234,7 +234,7 @@ checks database counts, bundle hashes, every archived object's hash, and the byt
|
||||
downloaded after restore, then removes only the temporary database and objects. It
|
||||
never restores over active data. Keep every bundle file private: it contains
|
||||
customer data, password hashes, and customer artwork. To verify it again, run
|
||||
`python3 -m local.backup verify` followed by the printed
|
||||
`python3 -m app.backup verify` followed by the printed
|
||||
`backups/...manifest.json` path. Legacy database-only `.dump` backups remain
|
||||
verifiable. Scheduling, offsite copies, and a production restore runbook remain
|
||||
unfinished.
|
||||
@@ -242,7 +242,7 @@ unfinished.
|
||||
After building the current image, test retention with synthetic files:
|
||||
|
||||
```bash
|
||||
docker compose exec -T api python -m local.retention_test
|
||||
docker compose exec -T api python3 -m tests.retention_test
|
||||
```
|
||||
|
||||
This checks that expired bytes are removed while unexpired files survive. It
|
||||
@@ -270,7 +270,7 @@ exposes `/minio/health/ready`.
|
||||
Run the redacted local alert summary inside the API network namespace:
|
||||
|
||||
```bash
|
||||
docker compose exec -T api python -m local.security_status
|
||||
docker compose exec -T api python3 -m app.security_status
|
||||
```
|
||||
|
||||
Exit status 1 means attention is required. Review blocked artwork, rate limits,
|
||||
@@ -306,12 +306,12 @@ Offline PDF previews may fall back to the prototype's manual/table-price path.
|
||||
## Dependency lock
|
||||
|
||||
The API, worker, and database initializer install every Python dependency from
|
||||
`local/requirements.lock` with `--require-hashes`. `local/requirements.txt`
|
||||
`infra/requirements.lock` with `--require-hashes`. `infra/requirements.txt`
|
||||
remains the human-maintained direct dependency list. After deliberately changing
|
||||
a direct pin, regenerate the lock in the same Python 3.12 environment and rebuild:
|
||||
|
||||
```bash
|
||||
./local/lock_dependencies.sh
|
||||
./infra/lock_dependencies.sh
|
||||
docker compose up --build -d --wait
|
||||
```
|
||||
|
||||
@@ -339,7 +339,7 @@ contracts and owners. See `staging/README.md`.
|
||||
Keep this stack local. Before connecting real services, confirm the production
|
||||
checkout trust workflow, complete `PRODUCTION_INPUTS.md`, and pass the isolated
|
||||
staging-readiness gate. Then implement the actual staging composition using the adapter contracts in
|
||||
`local/adapters.py`: start with private S3 staging storage, CORS, signed multipart
|
||||
`app/adapters.py`: start with private S3 staging storage, CORS, signed multipart
|
||||
contract tests and scoped credentials injected outside Git. Add provider sandbox
|
||||
adapters one at a time. Mercado Pago requires authenticated, signed, idempotent
|
||||
webhook handling before real payment is allowed; Tiny/Olist and WhatsApp need
|
||||
@@ -363,7 +363,7 @@ Run the source-only gate without credentials:
|
||||
python3 deploy/production_preflight.py --source-only
|
||||
```
|
||||
|
||||
It must remain blocked while `local/` supports only local fake adapters and does
|
||||
It must remain blocked while `app/` supports only local fake adapters and does
|
||||
not load Docker secret `*_FILE` settings. Do not bypass or delete this check.
|
||||
After approved production implementations and inputs exist, follow
|
||||
`PORTAINER.md` and `deploy/PRODUCTION_CHECKLIST.md`; release and deployment
|
||||
|
||||
Reference in New Issue
Block a user