feat: consolidate shared UI and harden browser authority for release

This commit is contained in:
2026-09-08 01:35:05 +02:00
parent ac40774785
commit b75ca34295
143 changed files with 8664 additions and 752 deletions
+35
View File
@@ -0,0 +1,35 @@
# Shared API client cache and authority boundaries
All optional WebUI modules use the Core API client. Its bounded in-memory caches
are an optimization, never an authorization mechanism. The backend must check
the current principal, tenant, and permissions even for conditional GETs.
- Identical simultaneous safe requests can share one network request. Requests
with caller-owned cancellation are independent.
- Responses allowing reuse have at most a 750 ms recent-response window.
`no-store` and `Vary: *` responses are not retained. `no-cache` and zero-age
responses require a server check; permitted ETags retain conditional GET
support without bypassing authorization. This follows the relevant
[HTTP cache-control semantics](https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2).
- Explicit `cache: "no-store"`, `"reload"`, or `"no-cache"` reads bypass older
response data and supersede older requests for that resource. Reload is not a
mutation. Owning read helpers must pass these options through pagination.
- Writes invalidate caches before execution and again on settlement, including
failures whose server outcome may be uncertain. Reads started before or
during the write cannot seed reusable data after it finishes.
- The shell calls `clearApiReadCache()` before explicit auth updates and when
refreshing authoritative session data. API-settings changes, clearing the
token, authentication expiry, and changes to the paired session/CSRF cookie
also invalidate both stored and in-flight reuse. Cookie observation also
covers sign-in/out in another tab; it does not read the HttpOnly session token.
- Interactive sign-in and sign-out clear a previously saved automation key.
Explicit key-based connection settings still select the key's identity;
profile-only updates preserve settings identity to avoid reload loops.
- Expired responses from superseded reads or downloads do not trigger a login
prompt in a newer session.
- Every completion (including 304) must still own its cache slot and generation
before storing anything. An old caller may receive its own result, so feature
components must continue guarding displayed state against obsolete requests.
Regression coverage: `npm run test:api-client-cache` uses the real client and
isolated network fixtures. No live API or account data is involved.