Parcourir la source

RHL-016 refactor(docs): update API documentation for search endpoint and authentication details

Code_Uwe il y a 3 semaines
Parent
commit
2eb9328613
3 fichiers modifiés avec 244 ajouts et 1 suppressions
  1. 109 1
      Docs/api.md
  2. 22 0
      Docs/auth.md
  3. 113 0
      Docs/frontend-api-usage.md

+ 109 - 1
Docs/api.md

@@ -1,5 +1,15 @@
 <!-- --------------------------------------------------------------------------- -->
 
+<!-- Ordner: Docs -->
+
+<!-- Datei: api.md -->
+
+<!-- Relativer Pfad: Docs/api.md -->
+
+<!-- --------------------------------------------------------------------------- -->
+
+<!-- --------------------------------------------------------------------------- -->
+
 <!-- Folder: Docs -->
 
 <!-- File: api.md -->
@@ -39,6 +49,9 @@ The environment can be validated via:
 
 In Docker/production-like runs, execute `node scripts/validate-env.mjs` before starting the server to fail fast.
 
+> Note: You may see a Node warning like `MODULE_TYPELESS_PACKAGE_JSON` when running env validation.
+> The validation still succeeds; the warning is harmless.
+
 ---
 
 ## 2. Authentication & Authorization
@@ -509,7 +522,7 @@ Stream (or download) a single PDF file from the NAS while enforcing authenticati
     For filename handling (Unicode-safe):
 
     - `filename="..."` is an ASCII fallback (safe for header values)
-    - `filename*=UTF-8''...` contains the UTF-8 encoded original name (RFC 5987)
+    - `filename*=UTF-8''...` contains the UTF-8 encoded original name
 
     Example:
 
@@ -574,6 +587,99 @@ Common error codes:
 
 ---
 
+### 4.11 `GET /api/search`
+
+**Purpose**
+
+Search delivery note content across PDFs.
+
+The endpoint returns _search hits_ with enough metadata to:
+
+- navigate to the correct Explorer day folder
+- open or download the PDF via the binary file endpoint
+
+**Authentication**: required.
+
+**RBAC behavior**
+
+- `branch` role:
+
+  - results are limited to the user’s `branchId`
+  - attempting to query other branches may return `403 AUTH_FORBIDDEN_BRANCH`
+
+- `admin`/`dev` role:
+
+  - can search across multiple branches (depending on `scope`)
+
+**Query params**
+
+- `q` (required)
+
+  - Search query string.
+
+- `scope` (optional)
+
+  - `branch` — only the current session branch
+  - `all` — all branches accessible to the current session
+  - `multi` — only branches listed in `branches`
+
+  Recommended: be explicit in the UI instead of relying on defaults.
+
+- `branch` (optional)
+
+  - Search within a single branch (subject to RBAC).
+
+- `branches` (optional)
+
+  - Comma-separated branch list for `scope=multi` (subject to RBAC).
+
+- `from`, `to` (optional)
+
+  - Date filter in `YYYY-MM-DD` format.
+
+- `limit` (optional)
+
+  - Page size.
+
+- `cursor` (optional)
+
+  - Pagination cursor returned from the previous response.
+  - Treat as **opaque**.
+
+**Response 200 (example)**
+
+```json
+{
+	"items": [
+		{
+			"branch": "NL20",
+			"date": "2025-12-18",
+			"year": "2025",
+			"month": "12",
+			"day": "18",
+			"filename": "Stapel_Seiten-4_Zeit-141039.pdf",
+			"relativePath": "NL20/2025/12/18/Stapel_Seiten-4_Zeit-141039.pdf",
+			"snippet": "..."
+		}
+	],
+	"nextCursor": "<opaque>"
+}
+```
+
+Notes:
+
+- Result order is typically relevance-based.
+- `nextCursor` is `null` when there are no more results.
+
+**Error responses**
+
+- `400` for missing/invalid parameters (returns a `VALIDATION_*` code)
+- `401` for unauthenticated access
+- `403` for branch violations (`AUTH_FORBIDDEN_BRANCH`)
+- `500` for internal search/index failures (`INTERNAL_SERVER_ERROR`)
+
+---
+
 ## 5. API v1 freeze (RHL-008)
 
 The endpoints and response shapes documented here (and in `Docs/frontend-api-usage.md`) are considered **API v1** for the first frontend implementation.
@@ -597,3 +703,5 @@ When adding new endpoints:
 5. Use the standardized error contract (prefer `withErrorHandling` + `ApiError` helpers).
 6. Add route tests (Vitest).
 7. Update this document.
+
+<!-- --------------------------------------------------------------------------- -->

+ 22 - 0
Docs/auth.md

@@ -1,3 +1,15 @@
+<!-- --------------------------------------------------------------------------- -->
+
+<!-- --------------------------------------------------------------------------- -->
+
+<!-- Ordner: Docs -->
+
+<!-- Datei: auth.md -->
+
+<!-- Relativer Pfad: Docs/auth.md -->
+
+<!-- --------------------------------------------------------------------------- -->
+
 # Authentication & Authorization
 
 This document describes the authentication and authorization model for the internal delivery note browser.
@@ -161,6 +173,14 @@ These endpoints require a valid session:
 - `GET /api/branches/[branch]/[year]/months`
 - `GET /api/branches/[branch]/[year]/[month]/days`
 - `GET /api/files?branch=&year=&month=&day=`
+- `GET /api/files/:branch/:year/:month/:day/:filename` (binary PDF stream/download)
+- `GET /api/search` (search is always subject to RBAC)
+
+Search RBAC notes:
+
+- Branch users can only search within their own branch.
+- Admin/dev can search across multiple branches.
+- Query params like `branch=` or `scope=multi&branches=...` are validated and filtered through RBAC.
 
 ---
 
@@ -301,3 +321,5 @@ Security note:
 - Use HTTPS for real users (staging/prod).
 - Keep `SESSION_SECRET` secret and rotate when needed.
 - Local HTTP testing is supported via `SESSION_COOKIE_SECURE=false`.
+
+<!-- --------------------------------------------------------------------------- -->

+ 113 - 0
Docs/frontend-api-usage.md

@@ -1,5 +1,17 @@
 <!-- --------------------------------------------------------------------------- -->
 
+<!-- --------------------------------------------------------------------------- -->
+
+<!-- Ordner: Docs -->
+
+<!-- Datei: frontend-api-usage.md -->
+
+<!-- Relativer Pfad: Docs/frontend-api-usage.md -->
+
+<!-- --------------------------------------------------------------------------- -->
+
+<!-- --------------------------------------------------------------------------- -->
+
 <!-- Folder: Docs -->
 
 <!-- File: frontend-api-usage.md -->
@@ -60,6 +72,10 @@ The core UI flow is a simple drill-down:
 7. `getFiles(branch, year, month, day)`
 8. Open a PDF via the binary endpoint (see section 4.3)
 
+Optional (admin/dev):
+
+- use the search endpoint (`GET /api/search`) to implement a global search UI (see section 4.4)
+
 ### 1.3 Example usage (client-side)
 
 ```js
@@ -415,6 +431,97 @@ const href = buildPdfDownloadUrl({ branch, year, month, day, filename });
   - If you are logged in on `http://localhost:3000`, also open the PDF on `http://localhost:3000`.
   - Switching to `http://127.0.0.1:3000` will not send the cookie (different host) and results in `401`.
 
+### 4.4 Search
+
+#### `GET /api/search`
+
+This is a **JSON** endpoint.
+
+You can call it via `apiFetch(...)` (or add a small convenience wrapper in `apiClient` when implementing the Search UI).
+
+Query params:
+
+- `q` (required)
+
+Optional filters:
+
+- `scope`: `branch | all | multi`
+- `branch`: single branch
+- `branches`: comma-separated branch list (for `scope=multi`)
+- `from`, `to`: `YYYY-MM-DD`
+- `limit`: page size
+- `cursor`: pagination cursor returned by the previous response
+
+Response shape:
+
+```json
+{
+	"items": [
+		{
+			"branch": "NL20",
+			"date": "2025-12-18",
+			"year": "2025",
+			"month": "12",
+			"day": "18",
+			"filename": "...pdf",
+			"relativePath": "NL20/2025/12/18/...pdf",
+			"snippet": "..."
+		}
+	],
+	"nextCursor": "<opaque>"
+}
+```
+
+Recommended usage (client-side):
+
+```js
+import { apiFetch } from "@/lib/frontend/apiClient";
+
+export async function searchDeliveryNotes({
+	q,
+	scope,
+	branch,
+	branches,
+	from,
+	to,
+	limit,
+	cursor,
+}) {
+	const params = new URLSearchParams();
+	params.set("q", q);
+	if (scope) params.set("scope", scope);
+	if (branch) params.set("branch", branch);
+	if (branches?.length) params.set("branches", branches.join(","));
+	if (from) params.set("from", from);
+	if (to) params.set("to", to);
+	if (limit) params.set("limit", String(limit));
+	if (cursor) params.set("cursor", cursor);
+
+	return apiFetch(`/api/search?${params.toString()}`);
+}
+```
+
+Using a hit to navigate/open:
+
+- Navigate to the day folder:
+
+  - `dayPath(hit.branch, hit.year, hit.month, hit.day)`
+
+- Open the PDF:
+
+  - `buildPdfUrl({ branch: hit.branch, year: hit.year, month: hit.month, day: hit.day, filename: hit.filename })`
+
+Pagination:
+
+- Store `nextCursor` from the response.
+- Pass it back as `cursor=` for the next page.
+- Treat the cursor as opaque.
+
+RBAC note:
+
+- Branch users will only get results for their own branch.
+- Admin/dev users can use `scope=all` or `scope=multi` for cross-branch search.
+
 ---
 
 ## 5. Error handling
@@ -534,7 +641,13 @@ Rules:
 ## 9. Out of scope / planned additions
 
 - Search UI and filters (route exists as placeholder: `/:branch/search`).
+
+  - Backend support exists via `GET /api/search`.
+  - The UI is still considered a planned addition.
+
 - Optional Explorer UX polish:
 
   - add a dedicated “Herunterladen” UI action (download variant)
   - optional in-app PDF viewer experience (instead of a new tab)
+
+<!-- --------------------------------------------------------------------------- -->