All checks were successful
Build and deploy / Validate source (push) Successful in 10s
Build and deploy / Integration suite on a real stack (push) Successful in 1m47s
Build and deploy / Secret scan and release gate (push) Successful in 7s
Build and deploy / Publish images and notify Portainer (push) Successful in 1m38s
The previous commit used git add -A and swept in four binaries that were deliberately untracked: the week-1 client report as .docx and .pdf, a duplicate of it under output/documents, and imagem-teste.jpg, an input dropped in to test with. None of them are the repository's to version. They are untracked here, left on disk, and covered by .gitignore so the mistake cannot repeat. Three files had no sensible home. The meeting notes sat at the repository root under a 78-character name with spaces and accents, the roadmap generator lived in tmp/ — a directory otherwise ignored as scratch — and its output in output/, which is otherwise generated evidence. They are now docs/reuniao-2026-09-09- anotacoes.pdf, tools/generate_dtf_report.py and docs/roadmap-cliente.pdf, with CONTEXT.md and ROADMAP.md updated to match and a docs/README.md saying what each document is for. .gitignore no longer needs four rules to keep one generator out of an ignored directory; tmp/ is scratch again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
404 lines
20 KiB
Markdown
404 lines
20 KiB
Markdown
# DTF System - Project Context for AI Agents
|
|
|
|
## Purpose of this document
|
|
|
|
Read this document before changing code, documentation, architecture, or scope.
|
|
It is the current English source of truth for the project. It supersedes older
|
|
decisions in `README.md`, `docs/historico/ESPECIFICACAO.md`, `schema.sql`, and the existing
|
|
prototype code whenever they conflict.
|
|
|
|
Update this file whenever the team makes a material product, process, or
|
|
architecture decision.
|
|
|
|
## Project goal
|
|
|
|
Build a DTF ordering and production-flow system for Dropstar/Altus.
|
|
|
|
The current process is slow and manual: customers send artwork through
|
|
WhatsApp, staff forward files, designers discover problems late, and production
|
|
status is not visible outside the factory. The business has substantially more
|
|
machine capacity than it currently uses. The goal is to let customers place DTF
|
|
orders online, pay, send artwork, and follow production without making
|
|
WhatsApp, shared folders, or manual handoffs the bottleneck.
|
|
|
|
The customer-facing value is speed and clarity. The operations value is a
|
|
traceable queue and fewer lost or manually handled orders.
|
|
|
|
## Current MVP scope
|
|
|
|
The MVP must be delivered in **at most three weeks**. The target is a working
|
|
online system, not factory-machine automation.
|
|
|
|
### Included
|
|
|
|
- Dedicated DTF site/subdomain.
|
|
- Existing Site DTF commercial rules and product experience.
|
|
- Direct, resumable multipart file upload to Cloudflare R2.
|
|
- Mercado Pago payment integration with signed and idempotent webhooks.
|
|
- Freight quotation and charging at checkout.
|
|
- Idempotent Tiny/Olist order integration and order traceability.
|
|
- Online Kanban for production status and secure file download.
|
|
- WhatsApp status notifications.
|
|
- Private object storage, 30-day file retention, backups, and basic security.
|
|
- Operator guidance for the factory team.
|
|
|
|
### Explicitly outside the three-week delivery
|
|
|
|
- Automatic pre-flight validation. It will be validated after delivery using
|
|
real customer files and real printed output, then refined as support work.
|
|
- Direct FlexiPRINT integration.
|
|
- Factory-side agent, hot folder, internal file server automation, VPN, and
|
|
heartbeat monitoring.
|
|
- Production-room dashboard, printer/machine telemetry, and advanced reports.
|
|
- Automated shipping-label purchase, shipping-label printing, and dispatch
|
|
automation. The MVP freight scope is quote selection and charging only.
|
|
- Personalized cart behaviour based on past orders, day, or time.
|
|
|
|
After delivery, the team provides support and evaluates requested changes. Do
|
|
not turn post-delivery support into a new committed delivery phase without an
|
|
explicit decision.
|
|
|
|
## Agreed production model
|
|
|
|
```text
|
|
Customer browser
|
|
-> Site DTF / API on VPS
|
|
-> direct multipart upload to private Cloudflare R2
|
|
-> Mercado Pago payment + freight selected at checkout
|
|
-> Tiny/Olist order record
|
|
-> online Kanban
|
|
-> factory operator downloads final file and imports it manually into FlexiPRINT
|
|
```
|
|
|
|
WhatsApp is a notification channel, not the artwork-upload channel. It is used
|
|
for payment confirmation, correction requests, production status, and order
|
|
completion.
|
|
|
|
The operator works through the browser. The factory does not need an installed
|
|
agent or an internal server for the MVP.
|
|
|
|
If the factory internet connection fails, only the factory team temporarily
|
|
loses access to the Kanban and secure downloads. The public portal, payments,
|
|
uploads, R2 objects, queue, and cloud services remain online. Factory work
|
|
resumes when local access returns.
|
|
|
|
## Infrastructure and deployment
|
|
|
|
- **VPS:** runs the website, API, worker, PostgreSQL, ClamAV, Kanban, and
|
|
third-party integrations.
|
|
- **Cloudflare R2:** private S3-compatible object storage for original uploads
|
|
and final files. It does not run the application, database, worker, or
|
|
antivirus.
|
|
- **Upload path:** the browser uploads directly to R2 using short-lived,
|
|
server-issued presigned multipart URLs. Large files must never be proxied
|
|
through the VPS.
|
|
- **Deployment:** one Portainer-owned `dtf-cloud` Docker Swarm stack. One Gitea
|
|
Actions workflow tests/scans, publishes `latest` plus commit-SHA application
|
|
images, and calls the Portainer webhook. Activation remains blocked pending
|
|
the production work listed below.
|
|
- **Kanban access:** configure `OPERATOR_EMAIL` and `OPERATOR_PASSWORD` as
|
|
stack environment variables. If the email is absent, only Kanban login is
|
|
blocked; the rest of the stack remains available.
|
|
- **Recommended VPS baseline:** 4 vCPU, 16 GB RAM, and 200 GB NVMe. Existing
|
|
VPS capacity may be used if it safely meets or exceeds this baseline.
|
|
- **Backups:** PostgreSQL backups go to R2. Application secrets are never
|
|
committed to Git.
|
|
|
|
## File retention
|
|
|
|
The business does not want an unlimited artwork library.
|
|
|
|
| Artifact | Retention |
|
|
|---|---:|
|
|
| Incomplete multipart upload | 1 day |
|
|
| Rejected or infected upload | 3 days |
|
|
| Customer original after approval | Up to 7 days |
|
|
| Final print artwork | Maximum 30 days from the first upload |
|
|
| Order history and metrics | Kept in the database without keeping the image |
|
|
|
|
The 30-day retention decision overrides older references to 90 days or
|
|
12-month artwork reordering.
|
|
|
|
## R2 planning cost reference
|
|
|
|
R2 cost is driven primarily by the average number of gigabytes stored during a
|
|
month; read/write operations are expected to be a much smaller cost at the
|
|
project's scale. There is no egress charge in the current planning model.
|
|
|
|
The client-facing roadmap uses the following planning examples, based on
|
|
standard R2 storage pricing, the included storage allowance, and an exchange
|
|
rate reference of USD 1 = BRL 5.13:
|
|
|
|
| Average storage | Approx. R2/month | Approx. BRL/month |
|
|
|---|---:|---:|
|
|
| 100 GB | USD 1.35 | BRL 7 |
|
|
| 500 GB | USD 7.35 | BRL 38 |
|
|
| 1 TB | USD 14.85 | BRL 76 |
|
|
| 3 TB | USD 44.85 | BRL 230 |
|
|
|
|
These are planning estimates only. Confirm Cloudflare pricing, exchange rates,
|
|
taxes, and payment-provider fees before presenting a commercial quote.
|
|
|
|
## Commercial rules
|
|
|
|
The existing rules in `dtf-site.html` are approved as the current source of
|
|
truth. Do **not** redesign, simplify, or change prices, discounts, minimums,
|
|
rounding, or product modes without explicit approval.
|
|
|
|
The current site contains four product modes, quality-based price tiers,
|
|
artwork-ready discounts, separate assembly charges for loose artwork, a
|
|
one-metre minimum, and ten-centimetre billing rounding.
|
|
|
|
The browser may display the calculation, but production payment creation must
|
|
recalculate and validate all price, quantity, freight, and discount values on
|
|
the server. Client-provided totals are never authoritative.
|
|
|
|
Normal JPG/PNG uploads are individual artwork by default, including when uploaded
|
|
from the by-metre panel. They use the existing loose-artwork editor, printed
|
|
width, quantity, and live packing canvas; packed height determines metres.
|
|
Customers uploading an already assembled film-width image must explicitly select
|
|
the ready-sheet option before uploading. PDF and manual-format ready sheets keep
|
|
their existing workflow. These models retain their separate approved price tiers;
|
|
image dimensions alone must never classify a normal artwork as a finished sheet.
|
|
|
|
## Freight
|
|
|
|
The original visual freight flow in `dtf-site.html` was a stub with only pickup
|
|
functional. The localhost bridge now supports pickup and backend fake freight
|
|
quotes; there is still no real carrier quotation or production checkout.
|
|
|
|
The customer already uses Correios and other shipping platforms. Before freight
|
|
can be completed, obtain:
|
|
|
|
- The platform(s) that should be used as the source of truth.
|
|
- API credentials or delegated access for the selected platform.
|
|
- Origin postal code/address.
|
|
- Available services and carriers to offer.
|
|
- Packaging weight and dimensions by DTF length/package.
|
|
- Freight business policy: exact pass-through, subsidy, free-shipping rules,
|
|
pickup, or other exceptions.
|
|
|
|
At checkout, the backend must quote freight from the selected source, store the
|
|
chosen service and quoted amount, include the amount in the Mercado Pago
|
|
payment, and persist it in the order. Do not create a payment before the freight
|
|
amount is final.
|
|
|
|
## Integrations
|
|
|
|
### Mercado Pago
|
|
|
|
Required before production payment integration, not for the local mock milestone:
|
|
|
|
- Production credentials.
|
|
- Webhook configuration/access.
|
|
|
|
Webhook processing must verify authenticity and be idempotent. A duplicate or
|
|
late delivery must not create a duplicate payment, order, message, or queue
|
|
card.
|
|
|
|
### Tiny/Olist
|
|
|
|
Tiny/Olist is already available. The implementation must create/update orders
|
|
idempotently and use the order number for traceability. Confirm the actual API
|
|
endpoints, marker/tag behaviour, and rate limits before production use.
|
|
|
|
### WhatsApp
|
|
|
|
WhatsApp is already available, but the technical provider still needs to be
|
|
confirmed (official Meta Cloud API, Z-API, or another provider).
|
|
|
|
Implement only the required customer events:
|
|
|
|
1. Payment approved.
|
|
2. Artwork correction needed, with a secure link back to the site.
|
|
3. Order entered production.
|
|
4. Order ready for collection or shipping.
|
|
|
|
Messages initiated by the business may require approved templates depending on
|
|
the provider and conversation state. Use an outbox/job mechanism with retries,
|
|
delivery status handling, and idempotency. Do not send artwork through
|
|
WhatsApp.
|
|
|
|
## Factory responsibilities after delivery
|
|
|
|
The client/factory team is responsible for:
|
|
|
|
- Opening the Kanban, downloading final files, and importing them manually into
|
|
the current FlexiPRINT setup.
|
|
- Performing real print tests and reporting mismatches in the final file or
|
|
printed result.
|
|
- Maintaining PCs, printers, FlexiPRINT licences, printing profiles, internal
|
|
folders, and the local factory network.
|
|
- Informing the development team about changes to prices, freight, operational
|
|
rules, or external platforms that need system changes.
|
|
|
|
The development team delivers the online system, provides usage guidance, and
|
|
supports subsequent corrections or scoped enhancements.
|
|
|
|
## Three-week roadmap
|
|
|
|
| Week | Delivery | Result |
|
|
|---|---|---|
|
|
| 1 | Infrastructure and upload | VPS, domain, database, R2, multipart upload, antivirus, and service foundation. |
|
|
| 2 | Payment, freight, and order | Mercado Pago, freight quotation, idempotent Tiny/Olist order creation, final file generation, and main Kanban states. |
|
|
| 3 | Kanban and handover | Online Kanban, secure download, WhatsApp status messages, 30-day retention, and operational handover. |
|
|
|
|
## Known implementation status
|
|
|
|
### Active localhost milestone (2026-09-15)
|
|
|
|
The current implementation target is localhost before any production connection.
|
|
Use `docker-compose.yml`, `.env.example`, and `LOCAL_SETUP.md`. The runtime is in
|
|
`local/`; historical `portal/`, `kanban/`, `agente/`, and `schema.sql` are preserved
|
|
as references and are not imported or started by Compose.
|
|
|
|
- One local `dtf-cloud` Compose project runs seven long-lived services: Site and
|
|
Kanban web gateways, FastAPI Portal/API, PostgreSQL, MinIO, ClamAV, and a
|
|
PostgreSQL outbox/scanning worker. Separate database and storage initialization
|
|
jobs provision restricted runtime identities, for nine Compose services total.
|
|
- MinIO implements the S3 storage boundary with direct multipart browser uploads,
|
|
resumable parts, private objects, and short-lived signed operator downloads.
|
|
- Payment, freight, Tiny/Olist, and WhatsApp use fake adapters only. No production
|
|
credentials or integrations are configured. The API and worker have no external
|
|
network route; only local web/storage gateways publish loopback ports.
|
|
- The original Site commercial calculation and appearance remain the source of
|
|
truth. Its existing browser artwork analysis is retained as prototype advice;
|
|
no new automatic pre-flight, server artwork analysis, or print-file generation
|
|
is implemented or invoked.
|
|
- Since client length and grade could be tampered with and automatic pre-flight
|
|
is deferred, a local operator manually confirms those commercial inputs before
|
|
checkout. This is a development trust-boundary decision, not a new production
|
|
promise. The backend calculates all tiers, discounts, assembly-inclusive rates,
|
|
one-metre minimum, ten-centimetre rounding, freight, and final totals. Immutable
|
|
approved quotes expire after 24 hours. A customer confirms the server total
|
|
on the Site to create one idempotent local paid order.
|
|
- Paid orders use `rec`, `tra`, `fil`, `imp`, `cor`, `fin`, with allowed transitions,
|
|
operator authentication, concurrency checks, and durable movement history.
|
|
Local mock integration receipts are visible in the Kanban.
|
|
- The customer portal at `/portal.html` supports local registration/login,
|
|
stronger scrypt password hashing with legacy-hash upgrade, revocable HttpOnly
|
|
sessions, owned order history/status, secure active
|
|
file downloads, and correction uploads. Registration/login can claim only the
|
|
current guest session's records, never orders found by email or CNPJ. Email
|
|
verification and password recovery are not implemented.
|
|
- Unfinished carts (including File blobs) recover from IndexedDB for 24 hours in
|
|
the same browser, scoped to the guest/account identity. Recovered items can be
|
|
removed/replaced or joined by new items; in-place reconstruction of the artwork
|
|
editor and cross-device cart synchronization are not implemented. Browser
|
|
storage capacity limits apply. Payment clears the saved cart. Logout revokes
|
|
the server session and clears local checkout metadata and saved File blobs
|
|
across open Site tabs.
|
|
- Operators manually upload and approve a complete final-file set, with one or
|
|
more files per order item. Queue entry requires active final files for every
|
|
item. Corrections invalidate the old set; customers submit corrections through
|
|
their portal, and operators reapprove final files. No artwork transformation,
|
|
automatic pre-flight, or machine control is performed.
|
|
- Every completed upload is quarantined pending a local ClamAV scan. Only `clean`
|
|
files can be quoted, commercially approved, paid, downloaded, attached as final
|
|
files, or admitted to the print queue. Rejected/error files remain blocked and
|
|
expire within three days. The isolated scanner uses signatures bundled in its
|
|
pinned image and has no external network route. The transport accepts files up
|
|
to 5 GiB, but the local scan/release limit is 128 MiB; larger files remain
|
|
blocked. This malware gate is not print pre-flight or artwork validation.
|
|
- A retention worker removes expired object bytes but keeps order/file metadata:
|
|
incomplete uploads after one day, originals within seven days of manual final
|
|
artwork approval, and attached final/correction files within 30 days of the
|
|
order's first upload. Storage lifecycle is also a 30-day backstop.
|
|
- Structured security events are written to logs and PostgreSQL. The local
|
|
`security_status` command summarizes authentication, rate-limit, scan, and
|
|
scanner/signature alerts without exposing secrets. Security regression tests,
|
|
exact-runtime Python dependency auditing, and Trivy image reports live under
|
|
`local/` and `output/security/`; open findings are documented in
|
|
`SECURITY_REPORT.md` and are not a production-readiness claim.
|
|
- All direct and transitive Python packages are pinned with artifact hashes in
|
|
`local/requirements.lock`; the API image build requires those hashes. The lock
|
|
is regenerated in a disposable Python 3.12 container by
|
|
`local/lock_dependencies.sh`. A fresh exact-runtime audit found no known Python
|
|
advisories on 2026-09-15; this does not cover OS/container findings.
|
|
- `compose.staging.yaml` is a separate, network-disabled readiness gate only. It
|
|
validates non-secret staging decisions and rejects placeholders, local endpoints,
|
|
fake providers, embedded secret settings, and unsafe secret sources. It does not
|
|
deploy the application, contain credentials, or contact any real provider.
|
|
- A separate production delivery package now exists under `deploy/`, with
|
|
non-root API/web image definitions, a single Portainer Docker Swarm stack,
|
|
external secret/volume contracts, health-monitored rolling updates,
|
|
commit-SHA rollback images, and one protected Gitea workflow under
|
|
`.gitea/workflows/`. The package never contains provider credentials and has
|
|
not been deployed. Its fail-closed preflight intentionally rejects the current
|
|
source until production adapters, Docker-secret file loading, approved inputs,
|
|
restore rehearsal, image scans, and human security approval are complete.
|
|
- `python3 -m local.backup create-and-verify` creates a private, Git-ignored bundle
|
|
containing a PostgreSQL dump plus every complete, unexpired object already marked
|
|
`clean`. SHA-256 manifests protect both parts. Verification restores the database
|
|
under a UUID name and the object bytes under a UUID MinIO prefix, hashes the
|
|
restored bytes, then removes only those temporary targets. Active data is never
|
|
overwritten; pending, rejected, errored, expired, and purged objects are excluded.
|
|
Run this local snapshot while uploads and retention are idle. Scheduling, offsite
|
|
copies, and production restore operations remain unfinished.
|
|
- Real providers, production authentication hardening, email verification/recovery,
|
|
automatic final-file generation, production backup operations, and production
|
|
activation remain incomplete. Deployment plumbing exists but cannot pass its
|
|
release gate yet. No factory automation or pre-flight is added.
|
|
|
|
See `docs/historico/IMPLEMENTATION_REPORT.md` for verification, `PRODUCTION_INPUTS.md` for the
|
|
decisions and evidence required before staging or production connection, and
|
|
`PORTAINER.md` for the production delivery contract.
|
|
The client roadmap promises are unchanged, so its PDF source is not regenerated
|
|
for this local implementation checkpoint.
|
|
|
|
### Existing assets
|
|
|
|
- `dtf-site.html`: the Site. Commercial rules, artwork analysis, cart and
|
|
delivery UI; its behaviour lives in `local/static/site-*.js`.
|
|
- `docs/historico/`: the original specification, endpoint sketch, task plan and
|
|
status report. Background only — they describe a model this system does not
|
|
implement.
|
|
|
|
The prototypes they describe (`portal/`, `kanban/`, `agente/`, the root
|
|
`schema.sql` and `.env.exemplo`) were removed on 2026-09-21 once nothing
|
|
referenced them; recover from Git history if ever needed.
|
|
- `tools/generate_dtf_report.py`: generator for the client-facing roadmap PDF.
|
|
- `docs/roadmap-cliente.pdf`: the generated roadmap, as last sent.
|
|
- `docs/reuniao-2026-09-09-anotacoes.pdf`:
|
|
meeting notes that established the business direction. Treat it as context;
|
|
the latest decisions in this document define the active scope.
|
|
|
|
### Important gaps and stale assumptions
|
|
|
|
- The original Site had no backend payment, freight quote, order persistence,
|
|
authentication, purchase history, or real cart persistence. Local order
|
|
persistence, reviewed quotes, mock freight and fake payment now work through
|
|
`local/static/checkout.js`. The local customer portal now provides accounts and
|
|
order history; cart recovery is browser-local. Production account verification,
|
|
recovery, and cross-device cart editing are still absent.
|
|
- Without the local bridge, the original freight fallback remains a stub.
|
|
Real freight quotation remains unimplemented in all runtimes.
|
|
- The existing `portal/whats.py` and `kanban/whats.py` are duplicated and send
|
|
direct text messages. They are not production-ready notification modules.
|
|
- Older documentation and code describe a Tiny webhook creating an upload link,
|
|
a factory agent, local Kanban, FlexiPRINT automation, 90-day retention, and
|
|
12-month artwork reuse. Those are not the current MVP model.
|
|
|
|
## Documentation synchronization
|
|
|
|
`context.md` is the compact operating context for agents. The current
|
|
client-facing narrative, diagrams, and formatting live in
|
|
`docs/roadmap-cliente.pdf`, generated from `tools/generate_dtf_report.py`.
|
|
|
|
When a decision changes, update both the relevant implementation context here
|
|
and the roadmap source when it changes what the client-facing plan promises.
|
|
|
|
## Change-control rules for agents
|
|
|
|
- Preserve the current Site DTF commercial rules unless explicitly asked to
|
|
change them.
|
|
- Do not add factory-side automation, a local agent, hot folders, FlexiPRINT
|
|
control, machine dashboards, or a new post-MVP delivery commitment by
|
|
inference.
|
|
- Do not claim that R2 hosts or executes application services.
|
|
- Keep all customer-facing and internal documentation in English only when this
|
|
file is the requested artifact; otherwise follow the user's requested
|
|
language.
|
|
- When a requirement is unclear, distinguish between the MVP, a future
|
|
enhancement, and an existing prototype assumption before changing code.
|