Kaynağa Gözat

RHL-006-refactor(docs): update documentation language and enhance caching strategy details

Code_Uwe 5 saat önce
ebeveyn
işleme
39e5431d42
4 değiştirilmiş dosya ile 114 ekleme ve 28 silme
  1. 58 3
      Docs/api.md
  2. 4 11
      Docs/auth.md
  3. 18 11
      Docs/runbook.md
  4. 34 3
      Docs/storage.md

+ 58 - 3
Docs/api.md

@@ -1,10 +1,10 @@
 <!-- --------------------------------------------------------------------------- -->
 
-<!-- Folder: Docs -->
+<!-- Ordner: Docs -->
 
-<!-- File: api.md -->
+<!-- Datei: api.md -->
 
-<!-- Relative Path: Docs/api.md -->
+<!-- Relativer Pfad: Docs/api.md -->
 
 <!-- --------------------------------------------------------------------------- -->
 
@@ -139,6 +139,61 @@ Route handlers use shared helpers:
 - For realistic `Secure` cookie behavior, prefer HTTPS.
 - For local testing on `http://localhost`, many tools/browsers treat localhost as a special-case “secure context”. Behavior may vary between environments.
 
+### 3.6 Caching & Freshness (RHL-006)
+
+This project reads delivery-note PDFs from a NAS mount. New scans can appear at any time.
+
+The caching strategy is designed to:
+
+- show new files predictably
+- reduce filesystem load where possible
+- avoid any accidental shared caching for auth-protected responses
+
+#### 3.6.1 HTTP caching policy
+
+All JSON API responses explicitly disable HTTP caching:
+
+- `Cache-Control: no-store`
+
+This is applied centrally by `lib/api/errors.js` (the `json()` / `jsonError()` helpers). The policy applies to both success and error responses.
+
+#### 3.6.2 Next.js route handler execution
+
+All API route handlers are forced to execute dynamically at request time:
+
+- each route exports `export const dynamic = "force-dynamic";`
+
+This avoids any static/ISR-like behavior for NAS-dependent endpoints and keeps auth/RBAC behavior safe.
+
+#### 3.6.3 Storage micro-cache (server-side TTL)
+
+To reduce repeated `fs.readdir()` calls, `lib/storage.js` implements a small process-local TTL cache **after** RBAC is enforced (RBAC is checked in the route handlers).
+
+TTL defaults:
+
+- `listBranches()` / `listYears()` → **60 seconds**
+- `listMonths()` / `listDays()` / `listFiles()` → **15 seconds**
+
+Important:
+
+- TTL is a **max staleness** guarantee (new files may appear immediately; they must appear after TTL).
+- Cache is **process-local** (not shared across multiple app instances).
+
+#### 3.6.4 Frontend fetch guidelines
+
+Frontend code should call these endpoints with explicit “fresh data” settings:
+
+- Use credentials:
+
+  ```js
+  fetch(url, { credentials: "include", cache: "no-store" });
+  ```
+
+- Do not rely on `next: { revalidate: ... }` for these endpoints. Freshness is controlled via:
+
+  - `Cache-Control: no-store` (HTTP)
+  - server-side storage TTL micro-cache
+
 ---
 
 ## 4. Endpoints

+ 4 - 11
Docs/auth.md

@@ -1,13 +1,3 @@
-<!-- --------------------------------------------------------------------------- -->
-
-<!-- Folder: Docs -->
-
-<!-- File: auth.md -->
-
-<!-- Relative Path: Docs/auth.md -->
-
-<!-- --------------------------------------------------------------------------- -->
-
 # Authentication & Authorization
 
 This document describes the authentication and authorization model for the internal delivery note browser.
@@ -76,7 +66,10 @@ Local HTTP testing (e.g. `http://localhost:3000` with Docker + `next start`):
 
 Staging/Production:
 
-- Keep `SESSION_COOKIE_SECURE` unset (or `true`) and run the app behind HTTPS.
+- Prefer HTTPS.
+- Keep `SESSION_COOKIE_SECURE` unset (or `true`) and run the app behind TLS.
+
+> If the application is served over **plain HTTP** (no TLS), many clients will not send `Secure` cookies back. In that case, logins will appear to “work” (Set-Cookie is present), but subsequent requests will still be unauthenticated.
 
 ### 2.3 Fail-fast environment validation
 

+ 18 - 11
Docs/runbook.md

@@ -1,10 +1,10 @@
 <!-- --------------------------------------------------------------------------- -->
 
-<!-- Folder: Docs -->
+<!-- Ordner: Docs -->
 
-<!-- File: runbook.md -->
+<!-- Datei: runbook.md -->
 
-<!-- Relative Path: Docs/runbook.md -->
+<!-- Relativer Pfad: Docs/runbook.md -->
 
 <!-- --------------------------------------------------------------------------- -->
 
@@ -213,7 +213,15 @@ Edit `.env.server`:
 
 - Set a strong `SESSION_SECRET`.
 - Keep `NODE_ENV=production`.
-- Do **not** set `SESSION_COOKIE_SECURE=false`.
+- If the app is served behind HTTPS (recommended): keep `SESSION_COOKIE_SECURE` unset (or `true`).
+
+If the app is currently served over plain HTTP (no TLS), you may temporarily set:
+
+```env
+SESSION_COOKIE_SECURE=false
+```
+
+This is required because most clients will not send `Secure` cookies over HTTP.
 
 ### 3.4 Start the stack on the server
 
@@ -230,8 +238,7 @@ If you want a simpler startup command (and to avoid forgetting `ENV_FILE=...`),
 Create `./.env` in the project root:
 
 ```bash
-printf "ENV_FILE=.env.server
-" > .env
+printf "ENV_FILE=.env.server\n" > .env
 ```
 
 After that, you can start the stack with:
@@ -246,21 +253,21 @@ Notes:
 - `.env.server` still contains secrets and must not be committed.
 - Always run `docker compose` from the project root so Compose picks up the correct `.env` file.
 
-````
-
 ### 3.5 Verify
 
 On the server:
 
 ```bash
-curl -s http://localhost:3000/api/health
-````
+curl -s http://127.0.0.1:3000/api/health
+```
 
 Expected:
 
 - `db` is `ok`
 - `nas.entriesSample` contains real branch folders (`NLxx`)
 
+> Note: On some Linux servers, `localhost` resolves to IPv6 (`::1`). If `curl http://localhost:3000` fails, use `127.0.0.1` or `curl -4`.
+
 ### 3.6 Logs and troubleshooting
 
 ```bash
@@ -273,4 +280,4 @@ docker compose -f docker-compose.yml logs --tail=200 app
 
 For real users, the application should be served over HTTPS (reverse proxy / TLS termination).
 
-Local HTTP testing is supported via `SESSION_COOKIE_SECURE=false`.
+If HTTPS is enabled, keep the default secure-cookie behavior.

+ 34 - 3
Docs/storage.md

@@ -1,10 +1,10 @@
 <!-- --------------------------------------------------------------------------- -->
 
-<!-- Folder: Docs -->
+<!-- Ordner: Docs -->
 
-<!-- File: storage.md -->
+<!-- Datei: storage.md -->
 
-<!-- Relative Path: Docs/storage.md -->
+<!-- Relativer Pfad: Docs/storage.md -->
 
 <!-- --------------------------------------------------------------------------- -->
 
@@ -128,3 +128,34 @@ API routes map filesystem errors into standardized HTTP responses:
   - `500` with `FS_STORAGE_ERROR`
 
 This mapping is implemented in `lib/api/storageErrors.js` and used by route handlers.
+
+---
+
+## 6. Caching & Freshness (RHL-006)
+
+The NAS content can change at any time (new scans). To reduce filesystem load while keeping freshness predictable, `lib/storage` implements a small process-local TTL micro-cache.
+
+### 6.1 TTLs
+
+- `listBranches()` / `listYears()` → **60 seconds**
+- `listMonths()` / `listDays()` / `listFiles()` → **15 seconds**
+
+### 6.2 Semantics
+
+- TTL is a **maximum staleness** guarantee.
+
+  - New files may appear immediately.
+  - New files must appear after TTL expires.
+
+- Cache is **process-local**.
+
+  - If the app is scaled to multiple instances, each instance maintains its own cache.
+
+- Cache keys include `NAS_ROOT_PATH`.
+
+  - This avoids cross-environment/test pollution when the env var changes.
+
+### 6.3 Testing
+
+- Unit tests clear the storage cache between tests via a test-only helper.
+- A TTL test verifies “stable within TTL” and “refresh after TTL”.