feat(server): publish a stable installation identity for client connections

The iOS app lets an account reach one server through several addresses, such as a home network
IP and a public name. Before it sends credentials to an alternative address it needs to know the
address leads to the same installation, so expose a public, credential-free GET /server-identity
returning a persisted UUID, and add the same optional instanceId to app-info with the
server-connection-identity feature flag.

The UUID lives in a singleton server_identity row shared by every replica, created on first use
and cached per process. An unreadable identity omits instanceId instead of failing app-info,
which clients rely on for feature detection. Existing routes and bodies are unchanged and the
web client does not call the new route; the iOS app does.

The migration uses IF NOT EXISTS because an unreleased build created the same table as 0109.
This commit is contained in:
neon
2026-10-13 19:37:52 -06:00
parent 294bb13987
commit fbaf0b63df
17 changed files with 24098 additions and 27 deletions
+10
View File
@@ -17,11 +17,14 @@ export const SERVER_FEATURES = [
"metadata-search-cache",
"read-aloud-delivery",
"koreader-delivery-settings",
"server-connection-identity",
] as const;
export type ServerFeature = (typeof SERVER_FEATURES)[number];
export interface AppInfoResponse {
/** Stable installation identity, absent on older servers. */
instanceId?: string;
version: string;
updateAvailable: boolean | null;
latestVersion: string | null;
@@ -29,3 +32,10 @@ export interface AppInfoResponse {
/** Absent on servers older than the field itself, which a client treats as an empty list. */
features?: ServerFeature[];
}
/** Public, credential-free identity check for explicitly enrolled connection aliases. */
export interface ServerIdentityResponse {
product: "bookorbit";
protocolVersion: 1;
instanceId: string;
}