Security
Reporting a vulnerability
Section titled “Reporting a vulnerability”Don’t open a public issue. Use GitHub private vulnerability reporting, or email info@equationalapplications.com. You’ll get an acknowledgement within 48 hours and an assessment within 5 business days. The full policy is in SECURITY.md.
What the engine guarantees
Section titled “What the engine guarantees”- Parameterized SQL everywhere.
entityId,entryId,sourceRef,sourceHash, and query text are never concatenated into SQL. - Input normalization.
sourceRefis restricted to[A-Za-z0-9._\- ], andsourceHashmust be a 64-character hex digest. - Vector hygiene. Non-finite or empty vectors are never stored. A dimension mismatch falls
back to keyword search until
runReembed()completes. Vectors are copied defensively before they reach adapters. - Credential scrubbing. Ranker errors are sanitized before they appear in
error.causeor callbacks. - Deletes are sent to external indexes, and kept owed until confirmed. The engine records each
deleted fact and keeps it owed until your deletion hook succeeds once, across retries and
restarts. A restart alone doesn’t send them:
runPendingMaintenance(),runExternalDeletions(),forget()andrunPrune()(for the ids they touch) do, and so doessetup()when you turn ondrainExternalDeletionsOnSetup. Your hook must tolerate repeats, and the app has to run again to finish. Two cases keep no record, because the engine can’t write one: a store whosesetup()never ran (each removal is one hook call; for a failed call,forget()andrunPrune()throw and other paths emithook_failed, so the retry is yours), and an embed that lands after its fact was deleted while the database refuses writes and your hook also fails (only ahook_faileddiagnostic remains). See Deleting data for what stays with you. - Content-free diagnostics.
onDiagnosticnever carries fact text or model output.
Your responsibilities as the host
Section titled “Your responsibilities as the host”- Authorization. Decide which
entityIda caller may access. The engine scopes queries, but it doesn’t authenticate anyone. - API keys. Keep provider keys on a server, not in a mobile or browser bundle.
- Secrets in prompts.
getInstructions()and theinstructions_gettool (formerlywiki_get_instructions) returnconfig.promptsverbatim to anyone withmemory:read, so never put secrets in them. - One writer per file, across processes.
Prompt-injection trust boundary
Section titled “Prompt-injection trust boundary”User-controlled text, including event summaries, document chunks, and imported fact bodies, is interpolated verbatim into librarian, heal, and ingest prompts. Templating is simple substitution. It doesn’t detect instruction-like content.
- Mitigating prompt injection is the host’s job.
- If untrusted input flows into
write(),ingestDocument(), orimportDump(), treat the librarian’s and heal’s output as untrusted too. Validate it before you act on it downstream. - Grounding checks that a fact quotes its source. It is not an injection defense.
- In emergent mode, the ontology returned by
getInstructions()may contain types the model proposed. Agents should treat it as reference data, not as instructions.
Writing a VectorRanker adapter?
Section titled “Writing a VectorRanker adapter?”Read the adapter rules and the detailed examples in SECURITY.md.