Sources with a `teller` block in their config can pull transactions
straight from the bank instead of taking a CSV upload. Only the fetch
differs — dedupe, logging, and transformation reuse the import path.
api/lib/teller.js speaks Teller's mutual-TLS protocol (client cert plus
the access token as the HTTP Basic username) and flattens transactions
into the shallow map the rule engine expects. Access tokens live in .env,
one per enrollment, not in the database that manage.py offers to reset.
Pending transactions are skipped by default: their ids change when they
post, which would import the same charge twice under two keys. Sources
should use ['id'] as constraint_fields — Teller's transaction id makes
overlapping pulls free while keeping genuinely repeated charges distinct.
Untested against the live API — Teller has no self-serve signup at the
moment, so no account to verify against.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G2HFeU5neCKagTnmA6o9Tu
Architecture, file structure, the manage.py menu, and the API reference were
each documented in two or three of README.md, SPEC.md, and CLAUDE.md — the same
drift trap the SQL just had.
SPEC.md, examples/GETTING_STARTED.md, and ui/README.md move into docs/.
PERSPECTIVE.md and docs/perspective-pivot.md merge into docs/perspective.md,
version rationale first, then the API reference. README.md becomes an entry
point that links out, and CLAUDE.md keeps only working rules and non-obvious
behaviour, pointing at docs/spec.md for the rest. examples/ keeps just the
sample CSV the tutorial loads.
Corrections found while consolidating:
- the spec's API table was missing 20 routes — every override endpoint, most of
/api/stacks, the mapping remap routes, /health. Rebuilt from the route files
- the tutorial used port 3000 (default is 3020) and never mentioned Basic auth,
so every curl in it would have 401'd
- the tutorial and the spec each hand-listed the SQL deploy order; both now
point at manage.py, which is where the order actually lives
- CLAUDE.md described deduplication as an MD5 hash (it is a plain JSONB object),
claimed 5 tables and 4 functions, and told you to run a setup.sh that has not
existed for some time
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>