Five items that needed no decisions.
Indexes: the schema indexed only uploads(owner), so the worker's once-a-second
outbox poll scanned a table that only grows, and every per-customer and
per-order lookup did the same. Ten indexes now follow queries the application
actually issues, and no more, since each one is paid for on every write. The
outbox and live uploads use partial indexes so they stay the size of the backlog
rather than of all history. Confirmed against the database that the planner
chooses them.
Board: /api/operator/board returned every order ever created. Finished orders
are terminal, so they were pure growth. It now returns everything still in
progress however old, plus a window of recent finished ones and the true
finished total, and the Kanban column says "50 de 213" rather than letting the
count read as an all-time figure. An operator cannot lose a card they could act
on.
Dependencies: the root requirements.txt was the prototype's, pinned by wildcard,
listing packages this system does not use, next to the hash-locked lock file.
Deleted. pip was pinned as a runtime dependency, which installed a package
manager into the read-only production image; nothing depended on it, so it is
gone from both the direct list and the lock, and the base image's pip performs
the hash-enforced install.
Retention copy: the Site told customers their artwork was kept 90 days with 12
months of history, and invited them to reorder without uploading again. Files
are kept 30 days. The copy now matches the policy and drops the promise the
system cannot keep.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One OPERATOR_EMAIL and OPERATOR_PASSWORD served the whole factory, so every card
movement recorded the same name and the movement history could not answer who
did what. Traceability was one of the things the project set out to provide.
Accounts live in dtf_local.operators, authenticated with the same scrypt hashing
as customer accounts and with comparable work whether or not the account exists,
so absence is not observable by timing. Administration is a CLI in the API
container, like the schema migration: list, add, password, disable, enable.
Passwords are read from the terminal rather than an argument so they stay out of
shell history and the process list, and disabling deletes that operator's open
sessions instead of leaving them valid for the rest of the eight-hour window.
Migration is the part that could hurt: an empty table means 503 and a factory
locked out of its Kanban. OPERATOR_EMAIL and OPERATOR_PASSWORD seed the first
account, and only when that email is absent, so a password changed through the
CLI survives a redeploy carrying a stale environment variable. The first attempt
at this silently did nothing, because db-init receives its own small environment
and had neither variable; both compose files now pass them to it.
Verified against a running stack: bootstrap seeds the existing credential, that
credential still logs in unchanged, a second operator authenticates separately,
wrong passwords and unknown accounts are rejected alike, and disabling revokes
an open session immediately.
Roles are left out on purpose. The separation of duties the meeting described
governs rework authorisation, which this system does not implement, so a role
model would have no consumer to serve.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>