# Security model and data boundaries

Olenji is a single-user local application with a service owned by a workspace. It handles potentially private recordings and transcript text, calls optional native decoders and inference runtimes, and can send text to an explicitly configured translation provider. This document records the intended boundaries and their limitations so contributors can review a change against the actual product.

Use [SECURITY.md](/docs/1.3.0/security.md) to report a suspected vulnerability. The [API contract](/docs/1.3.0/api-contract.md) describes supported operations, and [VALIDATION.md](/docs/1.3.0/source/#source-81cf95d5c07b3b7671cd) identifies which checks actually ran. These documents do not claim a security certification or a complete independent audit.

## Assets and assumptions

The protected assets are recordings, transcript/revision history, provider credentials, the workspace API token, browser pairing credentials and the integrity of installed code/model artifacts. Correct source ownership and reliable cancellation also matter: a confused process must not overwrite another session, silently lose accepted audio or delete an active job's input.

The host account, configured executables and runtime installation are trusted. An authorized CLI agent can request local file transcription, install models and edit or delete workspace data; it is not a restricted transcript reader. The caller must grant that agent the appropriate permissions. The application is not a sandbox for a malicious agent, dependency, native library, local program or browser extension.

The service is intended for loopback use. It has no supported public hosting or multi-tenant mode. Browser same-origin protections are useful against unrelated web pages, but cookies are not scoped by TCP port. Distinct workspace cookie names prevent accidental collisions; they do not isolate the application from hostile HTTP services on the same local host. Do not treat a shared or compromised host as a trusted private workstation.

## Boundary review map

| Input or boundary | Current protection | Review locations |
| --- | --- | --- |
| Local HTTP and browser requests | Loopback binding, Host/Origin validation, authenticated API requests, one-use pairing and workspace-specific HttpOnly cookies | `service.py`, `app.py`, `runtime.py`; [API tests](/docs/1.3.0/source/#source-8536e8503be4ef396425), [boundary regressions](/docs/1.3.0/source/#source-2384fe471dffec697f53) |
| Local file paths | Path transcription additionally requires the CLI bearer credential; browser pairing alone does not authorize that route | `app.py`; [pairing and bearer-route checks](/docs/1.3.0/source/#source-8536e8503be4ef396425), [workspace-cookie checks](/docs/1.3.0/source/#source-c8deced1a631e1fc4e15) |
| Media uploads and decoding | Streamed request limits, owned upload files, bounded child output/cancellation, and FFmpeg protocol/container allowlists that exclude reference playlists | `app.py`, `audio.py`, `processes.py`; [upload lifetime](/docs/1.3.0/source/#source-65018f9e8d26988d2ca7), [audio checks](/docs/1.3.0/source/#source-1a49d5642b6057abe065) |
| Model downloads and extraction | Explicit installation, pinned identities, artifact digests where supplied, local inventories, safe archive paths and model leases | `models.py`, `catalog.py`; [model checks](/docs/1.3.0/source/#source-0adb667cd397bd56edce), [boundary regressions](/docs/1.3.0/source/#source-2384fe471dffec697f53) |
| Translation endpoints | Local-only policy, HTTPS for remote endpoints, no automatic redirects, explicit provider selection and credentials bound to their configured endpoint | `config.py`, `translations.py`; [provider checks](/docs/1.3.0/source/#source-c8deced1a631e1fc4e15), [translation checks](/docs/1.3.0/source/#source-1a49d5642b6057abe065) |
| Transcript, speaker and model text | Structured schemas, escaped rendering/exports, stable source revisions and declarative view configuration | `schemas.py`, `store.py`, `exports.py`, `web/app.js`; [store/API checks](/docs/1.3.0/source/#source-8536e8503be4ef396425), [browser tests](/docs/1.3.0/source/#source-07e3936bf165d977dddf) |
| Export and package files | Owned temporary files, complete-transfer replacement, exact release contents and SHA-256 verification | `export_files.py`, `client.py`, `scripts/build_release.py`; [exports](/docs/1.3.0/source/#source-2c07e4203b4e6073e060), [artifacts](/docs/1.3.0/source/#source-1fc3e4fea1ffe5656a4f) |

The file names in the implementation column are relative to `olenji/`, except `scripts/build_release.py`. The tests cover the named invariants, not every possible malformed input or native parser vulnerability.

## Credentials and network activity

Normal API responses omit provider keys, and request-validation errors omit submitted input values. Config and token creation request restrictive file modes. Existing directory permissions and Windows ACLs remain properties of the host; the application does not provide an encrypted vault. A user or program able to read the protected provider file can read its stored key.

The local-only setting governs supported recognition/provider processing paths. It is not a system firewall. Explicit model/runtime installation downloads requested artifacts, and an external agent can independently choose to send transcript text to its own provider. That agent's privacy controls are outside Olenji's enforcement boundary. A local model server is also a separate process with its own logging and network behavior.

Recognition reads the current session policy before each dispatch, including later live chunks and file recognition after decoding. A policy edit cannot recall an already dispatched request; stop active work before changing policy when a strict boundary is needed. Live sessions retain a shared speech-model pin through silence, pause and actual inference teardown, so model removal cannot invalidate later speech.

Translation requests ask for identity encoding and reject compressed responses before reading their body. Successful response bodies are limited to 2 MiB without an earlier decompression allocation; provider error responses close without reading their body. A provider or proxy that forces compression must be configured to honor the uncompressed request.

Provider endpoint edits must not move an existing secret to a different service. Download redirects must not retain Authorization when the scheme, host or effective port changes. A package hash establishes expected bytes; a publisher-provided digest and a locally computed inventory have different provenance. Keep that distinction in model metadata and release reports.

## Retention, deletion and recovery

Retention controls Olenji-owned session audio. It does not delete a file that the user originally supplied outside the workspace, remove transcript text, or retract an export already downloaded elsewhere. Database backups, filesystem snapshots and device storage can retain older data after application-level deletion; this is not forensic erasure.

Disabling retention must coordinate with capture/refinement ownership. An explicit disable request also retries an earlier failed cleanup even if the saved preference already says false. An operating-system deletion failure returns a retryable `AUDIO_CLEANUP_FAILED` error; the API must not report successful deletion while owned audio remains. Stop conflicting work, resolve the file-access problem and repeat the same disable request. The application does not need a new retention-enable operation to retry removal.

Interrupted uploads, prepared exports and unpublished npm setup candidates have explicit owners through cleanup. A cleanup failure must retain enough ownership to retry rather than orphan a sensitive file. Replacing an application environment while its service runs is outside the upgrade contract; stop the owned service before changing installations.

## Native and supply-chain limits

FFmpeg and speech runtimes parse external input and run native code under the user's account. Subprocess ownership, bounded protocol records and cancellation are reliability boundaries, not operating-system isolation. Python, FFmpeg, Swift/Xcode, OS libraries, GPU drivers and downloaded model/runtime artifacts need their own maintenance and platform verification.

The shipped npm wrapper has no JavaScript runtime dependencies or installation hooks, but its explicit setup installs the same Python application dependencies as the Python distribution. Those dependencies still need review. The standalone `dist/runtime-requirements.txt` and npm's embedded requirements are the same hashed default lock; optional model environments and development/browser-test tools have separate scopes. Do not describe an npm-only audit as coverage of the Python engine or models.

The release checksum manifest detects changed bytes. It does not authenticate who published them. Registry trusted publishing, repository protections, monitored private reporting and real maintainer identities require hosted configuration; [MAINTAINING.md](/docs/1.3.0/source/#source-3f8bdfae54ccb1649211) and [RELEASING.md](/docs/1.3.0/source/#source-8936340d2e7844f9c8b7) record that setup without claiming it already exists.

## When changing a boundary

Reproduce the specific failure with synthetic data, add a focused negative regression, and preserve the relevant ownership and output contract. Check both the failure and its recovery path. Record whether the test used a real process, a controlled fixture or actual hardware. Review dependencies and untrusted pull requests without publication credentials. This workflow follows the practical development, testing and supply-chain guidance in the [OpenSSF concise guide](https://best.openssf.org/Concise-Guide-for-Developing-More-Secure-Software.html).
