Commit Graph

16 Commits

Author SHA1 Message Date
Brummel 2fc7f8ddd2 feat: Add display name to user profiles
Introduce `display_name` field to `User` struct for human-readable names
in the UI.
This falls back to the user's `slug` if not provided.

Update `AuthenticatedWebUser` and `MyCasesTemplate` to use this new
field for rendering.
Add tests for parsing `display_name` and ensure fallback logic works
correctly.
Update `users.toml.example` to document the new field.
2026-05-04 11:46:19 +02:00
Brummel bb584b6ea0 Refactor: Remove unused Whisper variants
This commit removes the `whisper_variant` and `whisper_hotwords_variant`
fields from the `run_id` generation and the `print_meta_summary`
function.

These variants are no longer used as the project is shifting focus to
LLM-based generation. The `run_full_case.rs` example has also been
updated to reflect this change.
2026-04-30 16:56:12 +02:00
Brummel a510c20e75 refactor(server): plumb Arc<Settings> through workers and routes
Config sheds its 14 Bucket-B fields (retention, whisper, ollama, llm) and
gains a sibling Arc<Settings> in AppState, loaded from settings.toml at
startup via Settings::load_or_default. Workers (transcribe, analyze,
recovery, auto_trigger) and routes (health, bulk, case_actions,
user_web) take settings as a separate parameter or State<> extractor;
Config::llm_configured moves to Settings::llm_configured.

TestConfig::build_pair() returns (Arc<Config>, Arc<Settings>); the new
create_router_with_settings / create_router_and_session_store_with_settings
helpers wire both into integration tests that exercise LLM/Whisper/Ollama.
The legacy single-Arc create_router falls back to Settings::default()
so the 17 non-LLM tests stay untouched.

Verified: cargo build clean, clippy --all-targets clean, 318 tests pass.
2026-04-27 11:48:41 +02:00
Brummel 661ea6215e Add analysis preview to case list
Introduce a `preview_lines` setting in `users.toml` to control the
number of visible lines for the analysis preview in the case list. This
feature extracts the first paragraph of the `document.md` file, strips
markdown formatting, and displays it, capped by the configured
`preview_lines`. The actual line clamping is handled client-side via CSS
`line-clamp`.
2026-04-21 17:25:14 +02:00
Brummel 3218fc62bd feat: server-authoritative case window via users.toml
The /api/oneliners time window is now read per-user from users.toml
(window_hours, default 72h). Clients no longer carry a window:
client.toml oneliner_window_hours, SyncConfig.window_hours, the
?hours=N query param, and the render_case_list cutoff filter are
gone. ETag suffix keeps the effective hours so an admin edit to
users.toml invalidates client caches on the next request.
OnelinersResponse.window_hours stays in the wire format, but now
exists solely to anchor client reconciliation.
2026-04-21 16:48:01 +02:00
Brummel e5a62d8f10 feat: add per-user retention settings to users.toml
New [user.retention] TOML sub-block with auto_close_days and
auto_delete_days. Both default to 0, which disables the respective
sweep — a conservative default that preserves current behaviour for
existing deployments and lets admins test auto-close in isolation.

Only parsing + the test User literals are touched here; the actual
lazy sweep consuming these values lands in the next commit.
2026-04-21 10:48:24 +02:00
Brummel 0d5c2f5888 Formatting 2026-04-19 15:35:10 +02:00
Brummel 997af407b6 feat: Add hunspell dictionary support to gazetteer
Integrates the `spellbook` crate to allow for a Hunspell dictionary to
be used as a veto mechanism within the gazetteer.

This prevents common German words from being incorrectly rewritten to
vocabulary entries if they fall within the edit distance threshold. For
example, "Kaktus" will no longer be rewritten to "Lantus" if a Hunspell
dictionary is provided and contains "Kaktus".

The `hunspell_dict_path` configuration option is added, defaulting to
`/usr/share/hunspell/de_DE`. This path should point to the stem of the
Hunspell dictionary files (e.g., `/usr/share/hunspell/de_DE.aff` and
`/usr/share/hunspell/de_DE.dic`).

The gazetteer now supports an optional `DictChecker` trait, allowing for
pluggable dictionary implementations. `SpellbookDict` is the initial
implementation using the `spellbook` crate.

Includes new tests to verify the dict veto functionality, including
handling of case sensitivity and exact matches. An ignored test is added
for live verification against system-installed Hunspell dictionaries.
2026-04-17 12:30:34 +02:00
Brummel 1fd252f363 Add gazetteer configuration and dependency
This commit introduces the `VOCAB_DIR` configuration option, which
specifies the directory for gazetteer files. It also adds the `strsim`
crate, which is used for calculating string similarity and is essential
for the gazetteer's functionality.

The gazetteer module has been significantly expanded to include the
`Gazetteer` struct, its loading mechanism from `.txt` files, and an
annotation function. This functionality allows for pre-LLM correction of
proper names and technical vocabulary by identifying potential
misspellings based on phonetic similarity and edit distance.
2026-04-16 17:23:52 +02:00
Brummel 3a656bd2a9 Refactor LLM API key handling for Ollama
The LLM client now conditionally adds the `Authorization` header only
when an API key is provided. The `llm_configured` check is updated to
reflect that an API key is not strictly required for Ollama-style
endpoints. A new integration test verifies the functionality against an
Ollama-compatible endpoint without an API key.
2026-04-16 14:19:43 +02:00
Brummel 70eed20909 Add LLM system prompt override
Allow overriding the LLM system prompt via the `LLM_SYSTEM_PROMPT`
environment variable. This provides flexibility for customizing LLM
behavior without code changes. A default prompt is used if the
environment variable is unset or empty.
2026-04-15 21:31:21 +02:00
Brummel 5435b60b80 Refactor config to use test_default
Introduced a `test_default` method to `Config` to provide sane defaults
for integration tests. This refactors several test files to use this new
method, reducing boilerplate and improving maintainability.

Added `LLM_TIMEOUT_SECONDS` to the environment variables and `Config`
struct.
2026-04-15 19:07:58 +02:00
Brummel d489716c9b Feat: Implement basic web authentication and UI
This commit introduces the foundation for web-based authentication and
user interface. It includes:

- **Session Management**: Securely handling user sessions using
  cryptographically generated tokens, cookies with appropriate security
  flags, and server-side storage.
- **Login/Logout Functionality**: Endpoints for users to log in with
  their credentials and log out, clearing their session.
- **User Interface**: Basic templates for the login page, a list of
  cases, and a detailed view of a single case, allowing users to
  navigate and view their data.
- **Authorization**: An `AuthenticatedWebUser` extractor to ensure only
  logged-in users can access protected web routes.
- **Configuration**: Added a `cookie_secure` option to the configuration
  to control the `Secure` flag on session cookies, useful for local
  development.
- **Dependencies**: Added necessary dependencies for password hashing,
  time handling, and TOML file manipulation.
- **Helper Binary**: Included a `hash-password` binary to simplify
  generating bcrypt hashes for user passwords.
2026-04-14 15:09:23 +02:00
Brummel 0ef9109876 Add Whisper user settings to config
Introduce a new struct `WhisperUserSettings` to hold per-user
transcription settings. This allows users to customize Whisper
transcription for their specific needs directly in the `users.toml`
configuration file.

The changes include:
- Defining `WhisperUserSettings` with optional fields for `language`,
  `hotwords`, and `initial_prompt`.
- Integrating `WhisperUserSettings` into the `User` struct, with
  `#[serde(default)]` to ensure it defaults to
  `WhisperUserSettings::default()` if not present in the TOML.
- Adding new unit tests to verify that users can be parsed correctly
  with and without a `[user.whisper]` block.
- Updating existing tests in `auth_test.rs`, `upload_test.rs`, and
  `web_test.rs` to include the new `whisper` field, ensuring backward
  compatibility.
2026-04-14 11:00:52 +02:00
Brummel 1e3cc9574c Refactor user config validation and add transcript display
Introduces a dedicated function `validate_and_index_users` to
encapsulate the logic for validating user configurations, checking for
duplicate slugs and API keys. This function returns a `Result` to handle
errors gracefully, and its usage in `load_users` is updated to panic
with a more informative error message.

Additionally, this commit modifies the web routing to fetch and display
audio transcripts. When scanning recordings, it now attempts to read a
corresponding `.transcript.txt` file. If found, the transcript content
is included in the `RecordingView` and rendered in the `cases.html`
template. If the transcript file is not found, a "Transcription pending"
message is displayed.

The `transcribe` function in `whisper.rs` is updated to explicitly set
the language to German (`language=de`), which can improve transcription
accuracy by skipping language detection. The `encode=false` query
parameter has been removed, as the service is designed to handle encoded
audio.

Finally, tests have been added for the new `validate_and_index_users`
function to ensure duplicate slugs and API keys are correctly rejected.
Integration tests in `web_test.rs` have been updated to verify the
rendering of transcripts and the pending status.
2026-04-13 17:08:21 +02:00
Brummel 44dac06961 Add configuration loading and error handling
Introduces a new `config` module for loading application settings from
environment variables and a `users.toml` file. An `error` module is
added to handle application-specific errors gracefully. An
`.env.example` file is created to show available configuration options,
and `users.toml.example` provides a template for user data. The main
function now initializes the configuration and prints the server port.
2026-04-13 12:36:01 +02:00