Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions content/en/docs/developers/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ grep -rhoE 'HTTPException\(\s*(status_code\s*=\s*)?(status\.HTTP_)?[0-9]{3}|stat

Then drop the success codes the decorators declare — 200, 201, 202, 204. The grep does not see a status taken from an exception: `HTTPException(status_code=exc.status, …)` passes on the status of `KeepRefused` (`app/core/kept_volumes.py`, raised from `POST /collections/`, `PATCH /collections/{id}`, `POST /collections/{id}/move-records`, `PATCH /records/{id}`, `POST /projects/{id}/add_record/{rec_id}`, `POST /imports/digitisation-list`, `POST /collections/{id}/keep-on-unit` and `POST /collections/{id}/release-from-unit`), of `FreeRefused` (`app/core/offsite_free.py`), of `CodeRefused` (`_check_codes_with_fisqua`), and of `SearchRefused` on `GET /fisqua/descriptions` (`search_descriptions`, `app/core/unit_mode.py`: `400` `query_too_short`, `409` `off_in_this_mode` or `fisqua_not_configured`, `429` `rate_limited` with `Retry-After` when Fisqua gives one, `503` `fisqua_unreachable`). One raiser sits outside `backend/app/api/`: `app/core/db_errors.py`, which turns any `IntegrityError` — not only a unique-constraint one — into a 409 carrying a message and, when one could be recovered, the constraint name. For any single route, read it: the `HTTPException` calls are explicit, and twenty callables in `backend/app/api/` raise on a route's behalf — `_require_csrf_header` (reached through `_session_token`, and from `POST /auth/logout`), `_authorize_bootstrap`, `get_current_user` and `RoleChecker.__call__` in `auth.py`; `_zone` in `activity.py`; `_check_codes_with_fisqua` in `collections.py`, which raises the lookup's `422` or `409` with the status the refusal carries; `_refuse_capture_without_volume_or_stem`, `_refuse_retake_out_of_the_operators_hands`, `_refuse_a_new_volume_out_of_turn`, `_refuse_resolution_in_filename`, `_resolve_capture_target` and `_take_filename_index` in `cameras.py`; `_read_capped` in `imports.py`; `_refuse_a_name_that_is_a_stem` and `_update_project_held` in `projects.py`; `_stored_master`, `_image_row`, `assert_movable`, `_assert_promotable` and `_apply_status_change` in `records.py` — so a route can return a code its own body never names.

Capture endpoints report a failed capture as `{success: false, error: ...}` at HTTP 200, so a client must read the body as well as the status. `POST /cameras/calibrate` does the same with its own `501` for a backend without autofocus calibration: the route raises it inside its `try` block, and the `except Exception` there returns it as `{success: false, error: "501: …"}` at 200 (`calibrate_camera`, `cameras.py`).
Capture endpoints report a failed capture as `{success: false, error: ...}` at HTTP 200, so a client must read the body as well as the status. Calibration runs report a failure the same way, except on a backend that cannot calibrate: there `POST /cameras/calibrate` and `POST /cameras/calibrate/white-balance` answer `501` (`calibrate_camera` and `calibrate_white_balance`, `cameras.py`).

**A volume's identity — on `/collections` requests and responses.** A volume (a row in `collections`) carries the identity defined by exchange contract 1.1: a file name stem and the catalogue item's reference code. Records have no catalogue identifier: `records.external_id` was removed in migration `a7c1e9d2b4f6`. The schema gives the pattern and the lengths; the rules below are the ones it cannot state.

Expand Down Expand Up @@ -1101,7 +1101,7 @@ BOOTSTRAP_TOKEN=
ACCESS_TOKEN_EXPIRE_SECONDS=28800
```

The settings the backend reads are declared in `Settings`, `backend/app/core/config.py`, which is the authoritative list. The repository root `.env.example` lists most of them; it leaves out `CAPTUA_LOG_LEVEL`, `CAPTUA_OFFSITE_HOLD_FILE`, `CAPTUA_FISQUA_BASE_URL`, `CAPTUA_FISQUA_RETRY_BASE`, `CAPTUA_FISQUA_RETRY_MAX`, `CAPTUA_FISQUA_POLL_INTERVAL` and `CAPTUA_FISQUA_TIMEOUT`, which keep their defaults unless set. The block above shows only the settings relevant to the API.
The settings the backend reads are declared in `Settings`, `backend/app/core/config.py`, which is the authoritative list. The repository root `.env.example` lists every one of them, the prefixed ones under their `DTK_` names; `scripts/tests/env-example.test.sh` checks the two against each other. The block above shows only the settings relevant to the API.

The server host and port are not configurable by environment: the pixi `start` and `dev` tasks hardcode `--host 0.0.0.0 --port 8000`, so the native backend listens on every interface.

Expand Down
Loading