Privacy Policy
Last updated: 2026-09-20
1. Who holds the data
The operator does. FundTrace runs on a host the operator controls, against a Postgres database and a blob store on that same host. KAL Technologies LLC publishes the software; it operates no service, receives no telemetry, has no account system, and has no way to reach an installation it did not install. There is no "FundTrace cloud" to send anything to.
Everything described below therefore answers the question "what does an installation store", not "what do we collect". Who may see it is decided entirely by whoever runs the host.
2. What an installation stores
Uploaded files, kept whole
Imported workbooks, filed return PDFs, evidence attached to an exception and generated export bundles are stored as their original bytes, addressed by their SHA-256 digest. The database keeps the digest, the size, the media type and a storage URI; the bytes themselves live in the blob store. There is no delete method on the blob store interface, and the table that records the originals rejects UPDATE and DELETE by a database trigger — an imported file is meant to stay exactly as it arrived.
The rows derived from those files
Importing a workbook produces ledger rows: advances with the counterparty business name as it appeared in the file, the funder, the funding date and amount, the factor, the RTR, the term, and the syndicated amounts and commissions; a payment row for every payment row in the source, with its debit, gross, servicing fee and net amounts, its process, cleared and bank dates and the status the platform reported; the annual state of each advance; funder and merchant labels; and the per-cell provenance linking a derived figure back to the sheet row it came from. Manually entered records sit alongside them: capital transfers in and out of the platform, and reported losses.
Tax figures, per filing entity
Tax data is keyed to a filing entity, not to a fund. A filing entity row holds a legal name, optionally the last four digits of an EIN, a state and a formation date — no full tax identification number is stored anywhere. Per entity and year, an installation holds the calculated obligation, the figures as actually reported on a return, payments and their verification, assessments, and any correction recorded after a year was closed. A closed year is frozen by a database trigger; corrections are new rows, never edits.
Review decisions
Each exception the engine raises carries its type, severity, the amount at stake, a summary and its evidence. Every action taken on it — explained, approved, rejected — is appended as its own row with the actor, whether that actor was a person or the system, the note they left, the states it moved between and the timestamp.
The audit trail
Every state-changing action writes one append-only audit row, in the same transaction as the change itself. A row holds the time, the actor, a dotted action name, what the action acted on, the fund it belonged to, and a payload carrying the request id, the actor's display name, the outcome, and whatever evidence the action recorded. UPDATE and DELETE on this table are refused by a trigger, so the trail cannot be edited from inside the application — including by the operator.
Account credentials
One row per account: the email address, lowercased and unique, an optional display name, an Argon2id hash of the password, the TOTP secret encrypted with AES-256-GCM under a key derived from the installation's AUTH_SECRET, hashes of the ten single-use recovery codes, the highest authentication-code time step already spent, the failed-sign-in and lockout counters, and the enrolment, password-change and last-sign-in timestamps. The password itself and the plaintext TOTP secret are never stored.
Sign-in attempts
Every sign-in attempt, successful or not, writes a row holding the lowercased email that was tried, a keyed hash of the client IP address, the outcome and the time. The IP address is not kept in the clear — the rate limiter only ever compares hashes. The email is kept in the clear, because it is what the limiter counts by and an attempt against some other address is the detail worth having. No password, authentication code or recovery code is ever written to this table. A prune function exists for this table, but nothing schedules it: rows are kept until the operator prunes them.
3. Cookies
Two cookies, both strictly necessary:
- The session cookie, set by Auth.js when you sign in. It carries a signed and encrypted token, not your credentials.
httpOnly,SameSite=Strict,Securewhenever the installation is served over https, and an eight-hour idle lifetime that slides with activity. - The recovery-code cookie,
fundtrace.recovery-codes, which carries a freshly issued set of recovery codes from the action that created them to the one page render that shows them.httpOnly,SameSite=Strict, sixty seconds, and the page deletes it as it renders. It exists so the codes never travel in a URL, where they would end up in browser history and proxy logs.
There are no analytics, no tracking pixels, no third-party embeds, no advertising and no cross-site identifiers of any kind. The application loads no script, font or stylesheet from anyone else's domain. Because nothing non-essential is set, there is no consent banner to click.
4. Third parties
The complete list, and most of it is conditional on how you deployed:
- Your host and infrastructure provider. Whoever runs the machine can, in principle, reach the database and the disk. That is the trust boundary of any self-hosted deployment.
- Your reverse proxy's access log. The deployment terminates TLS at a reverse proxy on the same host, which writes one access log line per request — including the client IP address — to the host's own log stream. That log is the operator's.
- AWS Cognito — only if the deployment sets
AUTH_DRIVER=cognito. Sign-in then happens at Amazon's hosted UI and your email and credentials are handled by Amazon under their terms. The driver the deployment documentation recommends islocal, which authenticates entirely on your own host and talks to nobody. - S3-compatible object storage — only if it is configured. The production default is a local disk volume on your own host; an S3 or MinIO endpoint is an opt-in upgrade, and only then do the uploaded bytes leave the machine.
There is nothing else. No error reporting service, no log shipper, no email provider.
5. What is never done with it
Data in an installation is not sold, rented, shared or disclosed to anyone by the software, because the software sends it nowhere. It is not used to train any model. No large language model is called anywhere in this version: the schema reserves a table for machine-written explanations of an exception, and that table is created empty and never written.
6. Retention, deletion and backups
Retention is the operator's decision, with two constraints built into the application: imported originals and the audit trail have no delete path at all, by design, so "delete a record" means acting on the database directly and knowingly.
Backups are the other place data persists after it is gone from a screen. The deployment ships a backup script that takes a compressed dump of the whole database and a tar of the blob volume, on a nightly timer and on demand, keeping daily and monthly sets. Anything removed from the live database remains in every backup set taken before the removal until those sets expire or are destroyed. Backups are stored wherever the operator puts them.
7. Security, stated honestly
What the application actually does:
- Sign-in requires a password and a time-based authentication code; there is no way to skip the second factor.
- Passwords are stored as Argon2id hashes at OWASP's baseline parameters, never in the clear.
- The TOTP secret is encrypted at rest and the recovery codes are stored as keyed hashes, under a key that lives in the environment rather than in the database.
- Sign-in is rate limited per email address and per client address, with a lockout that doubles and is capped.
- Every state change writes an append-only audit row that the application cannot edit.
- Every route except the sign-in page, the authentication endpoints, the health check and these legal pages requires a session; the rule denies by default.
- TLS is terminated at the edge with HSTS,
nosniff, frame denial and a referrer policy. - Stored file bytes are verified against their digest when they are written and when they are read.
And what none of that amounts to: no SOC 2 report, no HIPAA compliance, no PCI DSS attestation and no independent security assessment of any kind. Nobody has certified this software. FundTrace should not be used with protected health information, and it is demo software rather than a product — see the Terms and Conditions.
8. Contact
Questions about this policy, or a request about data held in an installation, go to lala@mrkaltech.com. A request about data in someone's installation has to reach the operator of that installation — KAL Technologies LLC cannot read, export or delete data it has no access to.