ingestr v1.1.44 shipped on 31 August 2026. The change that matters on a production box is SFTP host key verification. A source URI can pin an OpenSSH known_hosts file or a SHA256 fingerprint instead of trusting whatever key answers on port 22. The same tag adds four sources: Sumble, ABRA Flexi, SatisMeter, and Twenty CRM.
The full release notes and downloads are on the GitHub release page.
SFTP host key verification ¶
PR 1155, merge commit 63c7222, adds identity checks to the SFTP source.
Password auth is still sftp://<username>:<password>@<host>:<port>. Private keys go on the key_file query parameter. When the key is encrypted, the URI password is the passphrase.
Verification is opt in:
known_hosts_filepoints at an OpenSSHknown_hostsfile. Paths that start with~/expand against the current user home.host_key_fingerprinttakes one or more OpenSSH SHA256 fingerprints. Repeat the parameter or pass a comma separated list. When this is set, it wins overknown_hosts_file.insecure_skip_host_key_check=trueis the explicit skip. It still prints a warning.
An unknown or rotated key fails the connection. That is the point. A silent MITM on a file drop used to succeed.
Existing SFTP URIs that set neither option keep working and print a migration warning. Treat the warning as unfinished work, not as a reason to leave trust on first use in production. New jobs should set known_hosts_file or host_key_fingerprint. URL encode fingerprint values. The SHA256: prefix contains a colon.
ingestr ingest \
--source-uri 'sftp://myuser:[email protected]?host_key_fingerprint=SHA256%3A<fp>' \
--source-table 'user.csv' \
--dest-uri duckdb:///sftp_data.duckdb \
--dest-table 'dest.users_details'
Sumble lists and intent signals ¶
Sumble lands as a v9 API source in merge commit abe37a4, tracked as PR 1157. The URI is sumble://?api_key=<key>. The key is sent as a bearer token.
Seven tables land in pkg/source/sumble/: organization_lists, organization_list_organizations, contact_lists, contact_list_people, signals, priority_signals, and signal_configs. Filters hang off --source-table as query parameters, for example signals?organization_ids=12,34&priorities=high.
signals and priority_signals page with offset pagination. Sumble stops at offset 10000. Extracts larger than that are truncated with a warning. The signals endpoint only returns the last 60 days unless you look up ids with signal_ids. Interval loading on date is client side because the API has no date range filter. Credits are charged per record returned, including rows later dropped by the interval. signals is newest first, so paging can stop once a page falls entirely before the interval start.
--sql-limit is honored. Parallel list workers serialize when a row budget is set, so they do not spend credits on rows the destination would discard.
ABRA Flexi, SatisMeter, and Twenty CRM ¶
Three SaaS sources ship in the same tag. Each is an additive package. No existing source path changes.
ABRA Flexi, PR 1152, merge commit f09fa7f, is Czech cloud accounting. Schemes are abra and flexibee. A typical URI is abra://<account>.flexibee.eu?username=<u>&password=<p>&company=<code>. The company code is required and never defaulted. One credential often reaches every company in an account, so guessing would load the wrong books with no error.
There is no fixed table list. Flexi publishes /<evidence>/properties.json, so any evidence name is a valid --source-table, for example faktura-vydana. Numeric fields land as strings, not float, because a float64 loses cents on a ledger. Relation fields explode into extra columns. @ is not a usable destination identifier.
SatisMeter arrives in merge commit d32833c as PR 1150. It reads campaigns, responses, and projects through the v3 REST API. The URI is satismeter://?api_key=<key>&project_id=<id>. The API rewrites an omitted startDate to 30 days ago. A pull that looks unbounded therefore returns a recent slice with no error. The contributor measured 31 rows from an unbounded probe against 25905 from a bounded backfill on the same account. The source always sends an explicit floor so “no interval” means the full history.
Twenty CRM ships in merge commit b2fc9db as PR 1153. It talks to the REST API on api.twenty.com or a self hosted host via twenty://<host>?api_key=<key>. Standard tables include people, companies, opportunities, notes, tasks, and workspaceMembers. Workspace specific objects use custom:<object_name>. Schema is read from object metadata at runtime because field sets differ between workspaces. One live pair of workspaces had a lead object in one and not the other, and person carried 79 fields against 32. A shared dbt model for people will not travel.
Composite Twenty types such as EMAILS, PHONES, and CURRENCY land as JSON. Currency amounts keep integer micros. An object without id is refused. There is nothing to deduplicate on, and an append strategy would insert the whole object again on every run. Soft deleted rows carry deletedAt. Default include_deleted=true makes a second pass so warehouse rows can show a deletion. Filter deletedAt IS NULL downstream for the live set.
Upgrade notes ¶
v1.1.44 is a stable tag, not a prerelease. The four new sources are additive.
SFTP is the only existing path that changes behavior. Unconfigured URIs still connect, with a warning. Pin known_hosts_file or host_key_fingerprint before treating SFTP as production. Leave insecure_skip_host_key_check for short lived exceptions.
Where to get it ¶
- Release notes and downloads: GitHub release page
- Source repository:
bruin-data/ingestr - Tag:
v1.1.44