Letters API: every cover letter's language comes back empty #437

Closed
opened 2026-10-01 10:46:42 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the API's output schemas with the dictionaries that fill them, and reading a letter back through the test client.

Checked again on 2026-10-01 against main at 0a5cad587: still present.

The fix for #283 added language to LetterOut, with a comment saying only the schema had forgotten it. The dictionary the router builds still has no language key, so the schema's default "" is sent for every letter: GET /api/v1/letters and GET /api/v1/letters/{id} say that no letter has a language, even when one is set. _cv_out in the same file does include it, so CVs are right.

  • Where: api/routers/documents.py:51-63, _letter_out (used by list_letters, get_letter and draft_letter); api/schemas.py:559-569, LetterOut, where language: str = "" hides the missing key rather than failing on it.
  • What happens: a letter saved with language = "de" comes back from GET /api/v1/letters/{id}, and in the list, as "language": "" (checked against the snapshot).
  • Why it matters: an agent choosing which letter to send for a German posting, through the API or the MCP server's letters tool, cannot tell a German letter from one whose language was never said, which is the distinction #283 added the field to make.
  • Fix: add "language": letter.language to _letter_out. Consider dropping the = "" default on LetterOut.language (and CVOut.language), so a router that forgets the key fails its tests instead of sending a plausible blank.

Done when

  • tests/test_api.py makes a letter with language="de" and asserts "language": "de" from GET /api/v1/letters/{id} and from GET /api/v1/letters.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, comparing the API's output schemas with the dictionaries that fill them, and reading a letter back through the test client. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The fix for #283 added `language` to `LetterOut`, with a comment saying only the schema had forgotten it. The dictionary the router builds still has no `language` key, so the schema's default `""` is sent for every letter: `GET /api/v1/letters` and `GET /api/v1/letters/{id}` say that no letter has a language, even when one is set. `_cv_out` in the same file does include it, so CVs are right. - **Where:** `api/routers/documents.py:51-63`, `_letter_out` (used by `list_letters`, `get_letter` and `draft_letter`); `api/schemas.py:559-569`, `LetterOut`, where `language: str = ""` hides the missing key rather than failing on it. - **What happens:** a letter saved with `language = "de"` comes back from `GET /api/v1/letters/{id}`, and in the list, as `"language": ""` (checked against the snapshot). - **Why it matters:** an agent choosing which letter to send for a German posting, through the API or the MCP server's letters tool, cannot tell a German letter from one whose language was never said, which is the distinction #283 added the field to make. - **Fix:** add `"language": letter.language` to `_letter_out`. Consider dropping the `= ""` default on `LetterOut.language` (and `CVOut.language`), so a router that forgets the key fails its tests instead of sending a plausible blank. ## Done when - `tests/test_api.py` makes a letter with `language="de"` and asserts `"language": "de"` from `GET /api/v1/letters/{id}` and from `GET /api/v1/letters`.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:46:42 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#437
No description provided.