01
Controlled content lifecycle
Uploads pass through source validation, scanning, parsing, review, activation, retirement, revocation, and retention states. New content does not activate automatically.
Truenote security architecture
An evidence-backed view of Truenote's safeguards across identity, ingestion, retrieval, AI data handling, answer integrity, browser protection, audit, resilience, and secure delivery.
01
Uploads pass through source validation, scanning, parsing, review, activation, retirement, revocation, and retention states. New content does not activate automatically.
02
Senior managers or super users approve. The uploader cannot approve the same version. Approval checks the source, scan verdict, findings, and document state.
03
Vector, full-text, and typo-tolerant retrieval run inside program, lifecycle, and classification filters before reranking. The model never decides which content a user may receive.
04
Every answer route requests ZDR, denies provider data collection, pins one approved provider, and disables provider fallback. No direct-provider answer escape hatch exists.
05
Every non-refusal answer must contain valid inline citations to retrieved chunks. Missing, unknown, sensitive, or ungrounded output produces a refusal.
06
File signatures, EICAR, secrets, SSNs, payment-card patterns, and prompt-injection language are checked without retaining matched sensitive values.
07
Passwords use Argon2id. Random session and reset tokens are stored only as SHA-256 hashes. Password changes and resets revoke existing sessions atomically.
08
Security-sensitive lifecycle, authentication, denial, and rate-limit actions produce correlated, append-only receipts. SIEM delivery uses HMAC signatures, retry leases, exponential backoff, and dead-letter state.
09
Credentialed mutations enforce trusted origins. CSP, frame denial, MIME protection, referrer restrictions, permission restrictions, CORS policy, and production HSTS reduce browser attack paths.
10
Embedding, parsing, reranking, generation, rewrite, naming, and evaluation calls use explicit timeouts and retry caps. The complete ask path has a fail-closed deadline.
11
Durable evaluation runs measure retrieval, reranking, citations, refusals, answer accuracy, latency, route fallback, and optional claim-level faithfulness against open and held-out questions.
12
GitHub CI runs TypeScript, the production frontend build, unit tests, CodeQL, Gitleaks, high-severity dependency audit, and CycloneDX SBOM generation.
Truenote's control model identifies AI-specific risks, assigns responsibility, and ties security assertions to testable evidence.
The security control record captures decisions, evidence grades, owners, binary acceptance tests, source files, DDL hashes, and retained CI receipts.
Implemented safeguards address prompt injection, cross-program leakage, knowledge-base poisoning, unsafe output, uncontrolled source onboarding, secret exposure, and query abuse.
Control ownership is separated across content governance, IAM, Security operations, platform/database operations, data governance, and repository ownership.
Control status distinguishes database acceptance, CI-verified behavior, implemented code, deployed configuration, and third-party responsibilities.
Clients cannot choose their program scope, clearance, model provider, lifecycle state, approval identity, or retention override. Authorized server and database paths resolve those decisions.
Unknown classifications, malformed principals, missing control schema, invalid citations, exhausted model routes, and unsafe content resolve to denial, quarantine, service unavailability, or refusal.
Credential storage, session handling, password recovery, role checks, and account administration reduce identity theft and privilege misuse.
Local passwords use Argon2id with explicit memory, time, and parallelism parameters. Verification failures return the same invalid-credentials response.
Unknown or inactive users still trigger a dummy Argon2 verification, reducing the timing difference that could reveal whether an account exists.
Sessions use 256-bit random browser tokens. Only each token's SHA-256 hash is persisted. Cookies are HTTP-only, SameSite=Lax, and secure in production.
Password changes and resets update the credential, revoke every existing session, and issue one replacement session in the same database transaction.
Password reset and invite links use random, hashed, expiring tokens. Consumption is row-locked, single-use, and paired with account-state checks.
Forgot-password requests return a uniform response, rate-limit requests, and do not issue tokens for unknown, inactive, or demo accounts.
Super user, senior manager, manager, and CSR permissions are checked on protected routes. Database constraints bind non-global users to a program.
CSV imports create CSR accounts only, normalize and deduplicate emails, assign random throwaway passwords, force password setup, and require configured email delivery.
Source governance, content validation, independent approval, and immutable provenance protect the knowledge base before content becomes searchable.
Each source records program, origin type, URI, owner, creator, approver, approval date, approval basis, and active or retired state.
The pipeline validates file signatures and EICAR, scans source text for sensitive and hostile patterns, and quarantines any upload without an acceptable scan result.
Ingestion ends at pending_review. Chunks remain outside retrieval until a different authorized reviewer approves the clean version.
Document versions retain hashes, original filenames, source ownership, parse results, scan receipts, findings, uploader, approver, classification, and lifecycle timestamps.
Program and sensitivity policies are enforced before retrieved content can enter model context or reach a user.
Vector, keyword, and neighbor queries bind program_id in SQL. A second fail-closed scope filter rejects any mismatched candidate.
Public, Internal, Confidential, and Restricted levels are compared against the authenticated user's server-owned clearance.
The same program, lifecycle, and classification rules protect ask retrieval, knowledge-base reads, citation lookup, highlights, and durable citation history.
Revoked versions stop participating in retrieval and are removed from citation access rather than remaining available through historical source links.
Vector similarity and PostgreSQL full-text search run in parallel. A trigram fallback handles keyword zero-hits, then a reranker selects final context.
Neighboring chunks can restore procedure context only within the same approved document version, program, lifecycle, and classification boundary.
Low reranker confidence refuses before generation. Candidate and final-context counts stay bounded and are recorded in evaluation configuration.
Citation-target reads re-check query ownership, program, source index, document version, lifecycle, and source offsets before returning evidence.
Truenote constrains where answer-generation traffic goes and sends an explicit privacy policy with every OpenRouter model request.
Every OpenRouter answer request sets zdr: true and data_collection: "deny". The application does not rely on an unstated provider default.
Each approved route pins exactly one reviewed provider with provider.only and sets allow_fallbacks: false, preventing OpenRouter from silently choosing another host.
Administrators can order reviewed route presets but cannot supply arbitrary model IDs, providers, request bodies, or routing policies.
If a route errors, returns empty text, or fails citation validation, Truenote advances only to another approved route carrying the same ZDR and data-collection controls.
Exhausting every approved OpenRouter route returns a safe refusal. No direct-provider answer path can bypass the per-request ZDR policy.
Follow-up rewriting and session naming use one pinned OpenRouter utility route with ZDR requested, data collection denied, and provider fallback disabled.
If an auxiliary model call fails, Truenote falls back to the original question or a locally derived title rather than sending data through an unapproved provider.
This request policy covers OpenRouter-hosted answer, rewrite, and naming calls. Direct embedding and parsing providers are separate data-processing paths.
Input, retrieved context, generation, and output checks keep answers grounded while limiting unsafe disclosure and automation.
Ask requests containing payment-card data, SSNs, or credential-shaped secrets are blocked before retrieval and generation and are not written to query history.
The generation prompt labels retrieved text as untrusted evidence, rejects embedded instructions, and prohibits prompt disclosure, credential disclosure, role changes, and tool calls.
The model receives short source aliases. Returned citations must map back to chunks supplied in the current request; unknown or out-of-range citations fail validation.
Generated text is screened again for credential, payment-card, and SSN patterns. Sensitive output becomes the standard refusal even when citations are otherwise valid.
An empty response, missing citation, malformed citation, unknown source, low-confidence retrieval result, or exhausted route chain cannot render as a normal answer.
Generation receives excerpts and a question, not application tools. Returned text cannot directly execute workflows, database changes, or external actions.
Request-origin checks, browser policy, rate limits, queues, deadlines, and integrity checks protect the application around the model.
Credentialed writes require an exact trusted origin and consistent Fetch Metadata. Foreign, opaque, malformed, cross-site, and same-site sibling origins are rejected.
Production policy restricts scripts, styles, images, fonts, connections, forms, frames, objects, base URLs, and frame ancestors and upgrades insecure requests.
Responses set MIME sniffing protection, frame denial, same-origin referrer policy, camera, location, microphone, payment and USB restrictions, cross-origin opener isolation, and production HSTS.
Cross-origin browser access is disabled by default. When configured, exact normalized origins are allowlisted and credentials are allowed only for those origins.
Source files are SHA-256 addressed, document history is versioned, activation is constrained, and privileged lifecycle changes produce immutable audit receipts.
Retrieval confidence gates generation. Every non-refusal answer must resolve its citations against the actual retrieved chunks.
Postgres-backed limits apply independently per authenticated user and per program and return a bounded retry interval when capacity is exhausted.
Login and password-recovery paths use separate sliding-window limits to bound password verification and email-trigger abuse.
Document ingestion and evaluation work run outside request handlers through pg-boss. Durable rows and reconciliation recover jobs after insert or queue-send crashes.
Every provider class has a configured timeout and retry cap. Abort signals stop work, and the overall ask deadline returns the standard refusal.
When demo mode is enabled, published demo users can read but every mutating method is denied by server middleware.
The unauthenticated health endpoint returns only service availability and does not expose database, provider, secret, user, or control-state details.
Correlated query receipts, an append-only security ledger, durable SIEM delivery, and negative tests make security activity traceable.
Query records bind the authenticated user, program, session, question, answer, refusal state, cited chunks, immutable citation snapshots, latency, and pipeline timing.
Successful answer receipts freeze ordered document, version, excerpt, and source-position evidence. Re-ingestion cannot silently rewrite an earlier answer's cited text.
Superseded sources remain labeled as historical evidence, while revoked, rejected, quarantined, failed, or deleted versions are removed from citation access.
Security events include actor, role, program, action, outcome, resource, request ID, source IP, details, previous hash, and event hash. Mutation is blocked by a database trigger.
A database trigger creates outbox rows in the same transaction as security events. The worker signs exact bodies, uses lease-fenced claims, retries, dead-lettering, and exposes super-user health.
Operational errors retain route, user, program, request, provider, and correlation data while recursively removing credential-shaped content.
CI covers cross-program access, malformed principals, privileged user administration, classification, self-approval, unsafe scan states, stale sources, purge gates, revocation, browser origins, CSP, and SIEM failures.
Authorized operators can inspect storage readiness, delivery configuration, backlog counts, oldest pending event, delivered count, dead-letter count, and last delivery time.
Formal lifecycle transitions, repeatable evaluation, retained build evidence, and recovery-aware jobs support secure operation over time.
Approval, rejection, rescan, activation, retirement, revocation, and permanent purge have explicit role, state, reason, retention, and audit requirements.
Normal removal is reversible retirement. Permanent purge requires exact title confirmation, retired state, elapsed retention or an explicit approved override, and a security receipt.
The repository includes CodeQL, secret scanning, dependency auditing, SBOM generation, Dependabot configuration, and a consolidated security regression suite.
Forward-only SQL defines lifecycle constraints, source governance, clearance, rate limits, append-only audit, and SIEM outbox behavior with post-commit acceptance queries.
Control records connect owners, source files, CI receipts, DDL hashes, and acceptance tests to the safeguards they support.
Program-scoped evaluation runs execute embedding, hybrid retrieval, reranking, generation, and citation scoring against expected documents, phrases, and refusal cases.
Protected questions remain separate from the tuning set. Reports show open and held-out pass rates so improvements cannot hide evaluation overfitting.
An opt-in judge decomposes answers into factual claims and reports unsupported claims against the exact excerpts supplied to generation.
Completed runs retain model routes, retrieval settings, question snapshots, question-set hash, results, and one approved baseline per program.
Only one run per program may be active. Durable queue reconciliation, lease tokens, cancellation fencing, and bounded run sizes protect results from duplicate or stale workers.
Dependabot checks npm and GitHub Actions dependencies weekly, while the security workflow audits production dependencies and generates a machine-readable SBOM.
Every capability below is Verified: direct repository, CI, or owner-provided database evidence passed within the named scope.
| Capability | Evidence grade | What the evidence shows | Primary evidence |
|---|---|---|---|
| Database-enforced control foundation | Verified | Owner-confirmed acceptance in the development database covers required lifecycle, source-governance, classification, approval-separation, rate-limit, and hash-chained audit objects. Acceptance returned zero unsafe active versions and zero broken audit-chain links. | docs/security/p0-p1-security-controls.sql |
| Program and clearance isolation | Verified | Negative tests deny cross-program and above-clearance access. Retrieval binds program and classification limits in SQL before ranking, then applies a second fail-closed scope check. | artifacts/api-server/src/lib/retrieval/query.tsartifacts/api-server/src/lib/security/classification.tsartifacts/api-server/src/lib/security/__tests__/negative-controls.test.ts |
| Hybrid retrieval boundary | Verified | Vector, full-text, trigram fallback, reranking, and neighbor expansion retain program, active-version, lifecycle, and classification predicates. Scope tests confirm leaked candidates are dropped fail-closed. | artifacts/api-server/src/lib/retrieval/query.tsartifacts/api-server/src/lib/retrieval/__tests__/program-scope.test.tsartifacts/api-server/src/lib/retrieval/__tests__/expand-neighbors.test.ts |
| Controlled ingestion and approval | Verified | CI covers file validation, EICAR, sensitive-content findings, self-approval denial, unsafe scan states, stale sources, and inactive-until-approved behavior. | artifacts/api-server/src/lib/ingestion/run.tsartifacts/api-server/src/routes/documents.tsartifacts/api-server/src/lib/security/__tests__/content-scan.test.tsartifacts/api-server/src/lib/security/__tests__/negative-controls.test.ts |
| OpenRouter ZDR routing policy | Verified | Tests confirm every approved answer route pins one provider, requests ZDR, denies data collection, disables provider fallback, rejects arbitrary routes, preserves the policy across route cascade, and has no direct-provider escape hatch. | artifacts/api-server/src/lib/generation/model-routing.tsartifacts/api-server/src/lib/generation/answer.tsartifacts/api-server/src/lib/generation/utility-model.tsartifacts/api-server/src/lib/generation/__tests__/model-routing.test.tsartifacts/api-server/src/lib/generation/__tests__/answer.test.ts |
| Citation and refusal contract | Verified | Generation tests reject missing, malformed, out-of-range, and unknown citations. A response without at least one valid source becomes the standard refusal. | artifacts/api-server/src/lib/generation/answer.tsartifacts/api-server/src/lib/generation/__tests__/answer.test.ts |
| Sensitive input and output handling | Verified | Tests cover credential, private-key, SSN, payment-card, EICAR, and prompt-injection detection. Sensitive model output is refused even when it includes a valid citation. | artifacts/api-server/src/lib/security/content-scan.tsartifacts/api-server/src/lib/security/__tests__/content-scan.test.tsartifacts/api-server/src/lib/generation/__tests__/answer.test.ts |
| Immutable citation receipts | Verified | Tests confirm ordered source snapshots, raw-markdown anchors, ownership and version requirements, stale-offset rejection, superseded labels, and removal of revoked or deleted evidence. | artifacts/api-server/src/lib/citations.tsartifacts/api-server/src/lib/__tests__/citations.test.ts |
| Browser mutation and CSP defense | Verified | CI passes ten browser-security tests covering trusted origins, foreign and malformed origins, cross-site requests, same-site sibling origins, and Content Security Policy. | artifacts/api-server/src/middleware/browser-security.tsartifacts/api-server/src/middleware/__tests__/browser-security.test.ts |
| Security audit and durable SIEM logic | Verified | CI passes signing, lease-fenced claiming, successful completion, retry scheduling, maximum-attempt dead-lettering, health reporting, and DDL-structure tests. | artifacts/api-server/src/lib/security/audit.tsartifacts/api-server/src/lib/security/siem-outbox.tsartifacts/api-server/src/lib/security/__tests__/siem-outbox.test.tsdocs/security/p1-siem-delivery-outbox.sql |
| Redacted diagnostics and bounded providers | Verified | Tests confirm recursive credential redaction, safe serialization, provider deadline defaults, bounded overrides, abort handling, and retry caps. | artifacts/api-server/src/lib/observability/error-log.tsartifacts/api-server/src/lib/observability/__tests__/error-log.test.tsartifacts/api-server/src/lib/deadlines.tsartifacts/api-server/src/lib/__tests__/deadlines.test.ts |
| Evaluation integrity | Verified | CI covers scoring, citation matching, expected-document rank, stage attribution, claim faithfulness, durable queue recovery, lease-fenced persistence, summaries, and protected evaluation splits. | artifacts/api-server/src/lib/eval/runner.tsartifacts/api-server/src/lib/eval/persistence.tsartifacts/api-server/src/lib/eval/queue.tsartifacts/api-server/src/lib/eval/__tests__ |
| CI security gates | Verified | The required workflow passes workspace TypeScript checks, the production frontend build, 281 unit tests, CodeQL security analysis, Gitleaks secret scanning, high-severity production dependency audit, and CycloneDX SBOM generation. | .github/workflows/security.yml.github/dependabot.yml |
These are the concrete pass conditions behind the verified capabilities above.
01
Required control objects, columns, constraints, and triggers were present in the development database. Acceptance found no active version outside the approved lifecycle and no broken audit-chain link.
02
Tests reject cross-program content, above-clearance content, and malformed principals before protected knowledge can reach ranking, generation, citation lookup, or document reads.
03
Tests reject self-approval, unsafe scan state, stale or retired sources, blocking sensitive-content findings, and activation without the required clean and approved state.
04
Tests confirm answer routes request ZDR, deny data collection, pin one provider, disable provider fallback, reject arbitrary routes, and return a refusal without a direct-provider escape hatch.
05
Generation tests confirm that missing or invalid citations cannot produce a normal answer. Known citations must resolve to chunks supplied to the model.
06
Tests detect credential, private-key, SSN, payment-card, EICAR, and prompt-injection patterns. Sensitive generated text is refused even with an otherwise valid citation.
07
Tests preserve ordered source receipts across re-ingestion, label superseded evidence, reject stale anchors, and remove revoked or deleted source access.
08
Ten tests confirm same-origin mutations work while foreign, opaque, malformed, cross-site, and sibling-origin requests are rejected. CSP restricts active browser content.
09
Seven SIEM outbox tests confirm signed payloads, bounded claims, retry backoff, lease fencing, dead-letter state, successful completion, and delivery-health DDL structure.
10
Tests confirm provider timeout and retry limits, abort propagation, route-chain cancellation, error redaction, and recovery after queue initialization failures.
11
Tests cover retrieval and reranking attribution, citation scoring, faithfulness, durable job recovery, lease fencing, cancellation, and open-versus-held-out reporting.
12
The merged security workflow completed TypeScript checks, the production frontend build, 281 unit tests, CodeQL, Gitleaks, production dependency audit, and CycloneDX SBOM generation.
The evidence table above identifies the implementation, tests, workflow, and database-control files behind each verified claim. The repository provides the complete code and change history.