mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
Register the sixteen auth, settings and discovery routes the spec never had
`pnpm openapi:check` compares the registry against the committed YAML and never the routes against the registry, so a route that was simply never registered stayed invisible to the gate. Sixteen of them are called by the native client and describe nothing: sign-out, the three per-user preference scalars, the two pre-session discovery reads, passkey login options, the passkey rename and delete, registration status, the consent latest-receipt reader and its revoke, account deletion, the instance service switches, the API-token list and revoke, the threshold overrides, the version read, and the assistant feature matrix. Each contract is derived from the handler rather than from its docblock, so the published statuses are the ones the code can actually produce — the 413 on a 1 KB body cap, the 400 the consent family answers where the rest of the API answers 422, the 403 an instance-wide API switch produces on a token READ, the last-admin and last-Guardian refusals on account deletion, and the fresh-factor arm that a Bearer transport cannot clear at any scope. Four request bodies moved to the validation modules the handlers now parse with, so the published wire cannot drift from the runtime one: the three `/api/auth/me` preference scalars into a new `user-prefs` module, and the passkey rename beside the login schemas. Behaviour is unchanged. The generated YAML is left out; it is regenerated once the remaining groups land.
This commit is contained in:
1 parent
a6c239d952
commit
b6efc6cb5a
11 files changed
+1109
-40
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod/v4";
|
||||
import { isValidKvnr, normaliseKvnr } from "@/lib/validations/kvnr";
|
||||
import { webauthnKeyNameSchema } from "@/lib/validations/mfa";
|
||||
|
||||
/** Minimum password length — must match checkPasswordStrength() in @/lib/auth/password.ts */
|
||||
const PASSWORD_MIN_LENGTH = 12;
|
||||
@@ -117,6 +118,14 @@ export const changePasswordSchema = z
|
||||
path: ["confirmPassword"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Rename a registered passkey — a PRIMARY sign-in credential, not the
|
||||
* second-factor security key `mfaWebauthnRenameSchema` covers. The two carry
|
||||
* the same label constraint and are served by different routes; they share the
|
||||
* constraint rather than the schema so neither surface can drift the other.
|
||||
*/
|
||||
export const passkeyRenameSchema = z.object({ name: webauthnKeyNameSchema });
|
||||
|
||||
export type RegisterInput = z.infer<typeof registerSchema>;
|
||||
export type LoginPasswordInput = z.infer<typeof loginPasswordSchema>;
|
||||
export type ProfileInput = z.infer<typeof profileSchema>;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Request schemas for the per-user scalar preference endpoints under
|
||||
* `/api/auth/me/*`. Single-sourced here so the runtime `safeParse` and the
|
||||
* OpenAPI registry (`src/lib/openapi/routes/profile.ts`) describe the identical
|
||||
* wire contract — the same reason `mfa.ts` exists next door.
|
||||
*
|
||||
* All three follow the same shape: a one-field PATCH that hard-sets the value
|
||||
* and answers with the resolved next state, so a client can replace its
|
||||
* optimistic update rather than re-read.
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import {
|
||||
injectionSiteEnum,
|
||||
INJECTION_SITE_VALUES,
|
||||
} from "@/lib/validations/medication";
|
||||
|
||||
/** `PATCH /api/auth/me/unit-preference` — metric/imperial display branch. */
|
||||
export const unitPreferencePatchSchema = z.object({
|
||||
unitPreference: z.enum(["metric", "imperial"]),
|
||||
});
|
||||
|
||||
/** `PATCH /api/auth/me/documents-auto-ai-read` — the auto-read opt-in. */
|
||||
export const documentsAutoAiReadPatchSchema = z.object({
|
||||
documentsAutoAiRead: z.boolean(),
|
||||
});
|
||||
|
||||
/** `PATCH /api/auth/me/injection-site-prefs` — the user-level deny-list. */
|
||||
export const injectionSitePrefsPatchSchema = z.object({
|
||||
// Dedup at write time; cap at the full enum size. An empty array
|
||||
// clears the exclusion.
|
||||
globalExcludedInjectionSites: z
|
||||
.array(injectionSiteEnum)
|
||||
.max(INJECTION_SITE_VALUES.length)
|
||||
.meta({
|
||||
description:
|
||||
"User-level injection-site deny-list. Sites here are never offered for any medication and rejected at intake (deny wins). Empty array clears the exclusion.",
|
||||
}),
|
||||
});
|
||||
Reference in new issue
Block a user