portal/, kanban/ and agente/ were 2,034 lines implementing the original Tiny-first model: token upload links, a second SQLite Kanban, a factory agent. Nothing imported or started any of it, and several endpoints took the acting user from the request body with no authentication at all. Their real cost was that a reader arriving at this repository found two Kanbans and two portals and had to work out which one was real. The root schema.sql and .env.exemplo went with them: both code paths load local/schema.sql, and having .env.exemplo beside .env.example differing by one letter was a trap rather than a convenience. The documents describing that model are archived rather than deleted. They record decisions and reasoning the current documents do not repeat, so they are worth keeping as background, with a header saying plainly that they are not instructions. README.md keeps its business case — the capacity figures and the cost argument are still the reason this project exists — but now states where the prototype documentation begins and that the code it describes is gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
15 KiB
Local milestone implementation report
Implemented
- A single
dtf-cloudCompose project: Site, Kanban, FastAPI Portal/API, PostgreSQL 17, private MinIO S3 storage, isolated ClamAV, and a mock integration outbox/scanning worker. Restricted database and MinIO runtime identities are provisioned by separate one-shot initialization jobs. - Existing Site product UI and commercial functions retained, with a separate local checkout bridge. Server pricing mirrors the four price ladders, all grade discounts, assembly-inclusive rates, minimum, and rounding.
- Direct multipart browser uploads, part resumption, owned upload completion, size verification, private five-minute operator downloads, persistent volumes, and 30-day object/one-day incomplete-upload lifecycle rules.
- Authenticated manual quote review supplies trusted commercial quantities and grades without adding pre-flight. Immutable server quotes include mock freight; the customer confirms the total and creates an idempotent local paid order.
- Shared PostgreSQL orders appear in Kanban. Validated transitions, correction reasons, version checks and movement history persist. Tiny/WhatsApp events use a transactional outbox, retry scheduling, unique event keys, and fake receipts.
- Loopback-only published ports; API/worker/database on an isolated network;
guards reject production mode, real adapters and nonlocal storage endpoints.
All long-running services have health checks.
.env.examplecontains disposable local defaults only. No new production credentials or provider endpoints. - Local customer registration/login, scrypt password hashes, revocable database sessions and attempt throttling. Customers see owned orders, timelines, final files and correction requests, and can upload corrections through the portal.
- Browser-local unfinished-cart recovery for 24 hours, including file blobs, with storage errors surfaced. Recovered rows can be removed/replaced and new items added. Customer navigation now points to local pages instead of the old external account/cart destinations.
- Manual final-file sets cover every order item, support multiple parts, and are required before queue entry. Corrections invalidate old final approvals. Customer and operator file views distinguish originals, corrections and finals.
- Worker retention cleanup: one-day unfinished uploads, seven-day originals after final artwork approval, and final/correction files no later than 30 days from the first upload. Combined database/clean-object backup plus isolated, hash-checked restore verification.
- Upload extension/size/count quotas, exact signed multipart
Content-Length, Host/cross-origin rejection, CSP and security headers, escaped filenames, and logout cleanup of browser cart blobs and checkout metadata. - Expiring, revocable HttpOnly operator sessions replace browser-stored Basic credentials. Customer passwords use stronger scrypt parameters, with legacy verification and upgrade on login.
- Completed artwork is quarantined until local ClamAV marks it
clean. Quote, payment, download, final-file approval, queue, and printing gates fail closed. Scanner errors/rejections remain blocked and expire within three days. This is malware scanning only, not print pre-flight. - Structured redacted security logging, a 30-day
security_eventstable, live scanner/signature alert summaries, security regressions, exact-runtime Python auditing, and JSON image-scan reports underoutput/security/. - Reproducible Python 3.12 dependency resolution: all 26 direct/transitive runtime packages are pinned with artifact hashes, and image builds enforce those hashes.
- A separate network-disabled staging-readiness gate validates non-secret inputs; it is deliberately not an application deployment or provider connection.
- A separate production delivery package defines non-root, hash-locked API/web images, one external-secret Portainer Docker Swarm stack, health-monitored rolling updates, commit-SHA rollback, and one Gitea test/scan/publish/webhook workflow matching the established Graphs/ComporHUB operating model. Its preflight deliberately blocks the current local-only source and placeholder inputs; no registry push, Swarm deployment, or real provider call occurred.
URLs
| Component | URL |
|---|---|
| Site | http://localhost:8080 |
| Customer portal | http://localhost:8080/portal.html |
| Kanban | http://localhost:8081 |
| API health | http://localhost:8000/health |
| Local object API and console | http://localhost:9000 · http://localhost:9001 |
Kanban local login: operator / local-operator-only.
Setup and the complete browser test are in LOCAL_SETUP.md.
Interactive /docs and /redoc are disabled.
Verification completed
docker compose up --build -d --wait: all seven long-running services healthy; both initialization jobs exited successfully and published ports are loopback-only.python3 -m unittest local.test_pricing -v: all tests passed, including 4,444 comparisons with the actual Site JavaScript calculator.python3 -m local.smoke_test: passed multipart resume/incomplete completion, download byte identity, private bucket and session ownership, input/tamper rejection, four-mode pricing, reviewed corrections, mock freight, concurrent payment idempotency, valid/invalid transitions, history and eight mock receipts.node local/browser_test.mjs: passed actual browser upload, manual review, local payment, cart recovery, final-file approval, customer registration, customer tracking, Kanban state changes and persisted board reload, with no JavaScript exceptions. Screenshots inspected inoutput/local/.- Local test orders are retained in Finalizado for inspection, including the browser fixture at R$21.89 and the four-mode smoke order at R$537.25.
- Restarts of all long-running containers preserved order snapshots, states, mock receipts and original file bytes; all services returned to healthy.
- Explicit guard checks rejected production mode, every real integration adapter, R2 selection and a nonlocal S3 endpoint without contacting external services.
python3 -m local.workflow_test: passed account/session isolation, guest migration, revoked-cookie rejection, customer corrections, final revision invalidation, secure file downloads and final-file gating.python3 -m local.backup create-and-verify: the refreshed 2026-09-15 bundle archived 61 clean MinIO objects (58,723,323 bytes) alongside the local database, verified SHA-256 manifests, restored and rehashed every object under an isolated MinIO prefix, restored the database with 16 orders and 107 upload records, then removed all temporary restore targets. The prior database-only backup also passed the legacy verifier.docker compose exec -T api python -m local.retention_test: verified expired object deletion, preservation of unexpired bytes, and retention of upload metadata. Only synthetic retention-test object bytes were cleaned up.python3 -m local.security_test: passed CSP/frame/Host/origin defenses, rejection of Basic credentials, HttpOnly operator-session revocation, extension and multipart-size signing, upload quotas, and login throttling.python3 -m local.scanning_test: a real harmless EICAR fixture was rejected by ClamAV and could not be downloaded or quoted; a clean control was released.docker compose exec -T api python -m local.runtime_security_test: passed database/MinIO least privilege, legacy/current password hashes, quarantine states, live scanner commands, scan-size rejection, and fail-closed offline behavior.- The hash-enforced rebuild completed successfully;
pip check, four staging-gate regressions, security, smoke, and runtime-security tests passed. A fresh exact-runtimepip-auditfound no known Python advisories on 2026-09-15. node local/browser_test.mjs: additionally passed filename XSS probes with CSP bypassed, absence of stored operator credentials, and logout removal of File blobs.- The final rebuilt stack has seven healthy long-running services; Site/API routing and a fresh guest portal session were checked after the rebuild.
- Production-package validation passed Python/unit and shell syntax checks, Gitea
workflow YAML parsing, and
docker stack configrendering. The API production image built from an immutable Python base. The web production image built from immutable Python/Nginx bases and ran as UID 101 with a read-only filesystem, returning 200 for its configured Host and 400 for an unexpected Host. - The pinned ClamAV validation image started as UID 100:101 with a read-only
filesystem, all capabilities dropped, and
no-new-privileges, then returnedPONGthrough the production health command; those restrictions are encoded in the Swarm stack. python3 deploy/production_preflight.py --source-onlyreturned the expected blocked result for local-only adapters/hosts/fake providers and missing Docker secret-file loading. This is verified fail-closed behavior, not production acceptance.
The final closeout smoke test retained local order #14 in Finalizado with eight durable fake receipts. The final workflow test again passed identity, correction, download, invalidation, and final-file gates after the PostgreSQL 17 image refresh. Existing database and MinIO named volumes were preserved.
Reuse and replacement decisions
| Existing asset | Decision |
|---|---|
dtf-site.html |
Reused directly. Preserved layout, modes, pricing, client previews, minimums and rounding; added file references and hooks for local checkout/freight. |
portal/main.py |
Inspected and preserved. Reused FastAPI and direct signed S3 upload design; replaced runtime with local/app.py because the prototype starts from Tiny and invokes pre-flight/agent delivery. |
portal/preflight.py |
Inspected, untouched, never imported by local runtime. |
kanban/main.py |
Inspected and preserved. Reused workflow state names, movement-history concept and outbox approach; replaced SQLite/folder/machine runtime with PostgreSQL endpoints. |
kanban/static/kanban.html |
Inspected and preserved. Reused dark palette, cards, columns and drag/drop pattern in local/static/kanban.html. Legacy machine controls and conflicting local/server handlers are not loaded. |
| Duplicated Tiny/WhatsApp modules | Preserved but excluded from build/runtime. New explicit fake adapters cannot invoke them. |
agente/ |
Inspected, untouched, excluded from build and Compose. Factory automation remains out of scope. |
Root schema.sql, requirements.txt, .env.exemplo |
Historical only; local runtime uses a separate dtf_local PostgreSQL schema, dependencies, and .env.example. No migration of prototype data. |
| README/API docs | Legacy content preserved under explicit notices pointing to active local instructions. |
Deferred and practical limits
This is a working local development milestone, not the completed three-week production MVP. Real payments/webhooks, freight providers, Tiny/Olist, WhatsApp, production R2, production account verification/recovery/security, automatic final print-file generation, scheduled/offsite backups and a production restore runbook, and production activation remain undone. Deployment definitions and automation now exist, but their gate correctly prevents use with the local-only application. No factory agent, hot folders, FlexiPRINT, VPN, machine dashboards, label automation, or new automatic pre-flight were added.
Browser artwork analysis already in the Site is retained as advisory prototype
behavior. The backend never adopts its prices, lengths or grades as approved.
The temporary manual quote step resolves that trust boundary locally; its role
in production needs an explicit product decision. Final files are manually
prepared and approved by operators; the test .cdr fixture is text, not printable
artwork. Cart recovery is browser-local, subject to quota, and does not reconstruct
the active artwork editor in place. Fake delivery receipts
mean only that the local adapter recorded an event, never that a person received
a message or an ERP order was created.
The multipart transport supports up to 5 GiB, but this local scanner can release only files up to 128 MiB. Larger uploads remain blocked. The scanner has no external network route and uses signatures bundled in its pinned image; rebuild or replace that image before signatures exceed the seven-day alert threshold.
The 2026-09-15 exact-runtime Python audit reported no known dependency findings.
All 26 installed packages are transitively pinned with artifact hashes; scheduled
lock refresh and audit automation are still pending.
Trivy HIGH/CRITICAL image reports are retained in output/security/: API 46
(44 Debian records without fixes plus two third-party-SBOM package records absent
from the runtime), Site 5, refreshed PostgreSQL 31, pinned MinIO 108, and pinned
ClamAV 0. Counts are scanner observations, not exploitability determinations.
MinIO was not upgraded over the preserved object volume; its old pinned release
is a material localhost-only limitation. See SECURITY_REPORT.md.
The Site retains its pre-existing external fonts/logo/PDF.js 3.11.174 references.
The known eval advisory is mitigated by the existing isEvalSupported:false call;
the old CDN dependency still needs a planned upgrade or vendored/pinned
replacement. No new production service references were added. The .git directory is unavailable
as a working Git repository in this workspace, so changes are delivered as local
files without a commit or Git diff.
Exact next step
The localhost security closeout is complete; continue local product work without
treating these controls as production approval. Before any staging or production
connection, complete PRODUCTION_INPUTS.md and pass the network-disabled readiness
gate, including the acceptance flow,
production authority for length/grade, and freight platform, origin, packaging and
policy. The verified local database/clean-object bundle addresses the local
recovery gap but is neither scheduled nor offsite and should be created while local
writes are idle. Remaining foundations include production backup/restore design,
container-image remediation/upgrade decisions, and account verification/recovery
design. The current compose.staging.yaml validates inputs only and cannot deploy
the application or contact providers.
Use the checked-in deploy/ package as the target deployment contract rather
than creating another production stack. First add the actual separate staging application runtime, beginning with S3
adapter contract tests for direct multipart upload, private downloads, CORS and
retention using injected staging credentials. Add real provider adapters only
after their contracts are confirmed; payment activation requires signed,
idempotent webhooks. Implement Docker-secret file loading, resolve or formally
accept image findings, rehearse production restore, and make the release preflight
pass without weakening it. The local runtime intentionally refuses production values.