mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +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
@@ -20,8 +20,6 @@
|
||||
* field-by-field write (no mass assignment). Idempotent — always returns the
|
||||
* resolved next state so the client can hard-set the optimistic update.
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
import { apiHandler, requireAuth } from "@/lib/api-handler";
|
||||
import {
|
||||
apiError,
|
||||
@@ -36,10 +34,7 @@ import { ensureWebAiConsentReceipt } from "@/lib/consent/web-grant";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { enqueueSummaryCatchUp } from "@/lib/jobs/document-summary-catchup";
|
||||
import { checkRateLimit, rateLimitHeaders } from "@/lib/rate-limit";
|
||||
|
||||
const patchBodySchema = z.object({
|
||||
documentsAutoAiRead: z.boolean(),
|
||||
});
|
||||
import { documentsAutoAiReadPatchSchema } from "@/lib/validations/user-prefs";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -87,7 +82,7 @@ export const PATCH = apiHandler(async (req: Request) => {
|
||||
});
|
||||
if (jsonError) return jsonError;
|
||||
|
||||
const parsed = patchBodySchema.safeParse(body);
|
||||
const parsed = documentsAutoAiReadPatchSchema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
annotate({
|
||||
action: { name: "auth.me.documentsAutoAiRead.patch.invalid_shape" },
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
* limit, Zod safeParse → 422 via `returnAllZodIssues`, audit-log row,
|
||||
* field-by-field write (no mass assignment).
|
||||
*/
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { apiHandler, requireAuth } from "@/lib/api-handler";
|
||||
import {
|
||||
apiError,
|
||||
@@ -33,10 +31,10 @@ import { auditLog } from "@/lib/auth/audit";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { checkRateLimit, rateLimitHeaders } from "@/lib/rate-limit";
|
||||
import {
|
||||
injectionSiteEnum,
|
||||
INJECTION_SITE_VALUES,
|
||||
type InjectionSiteValue,
|
||||
} from "@/lib/validations/medication";
|
||||
import { injectionSitePrefsPatchSchema } from "@/lib/validations/user-prefs";
|
||||
import { NextRequest } from "next/server";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -44,18 +42,6 @@ export const dynamic = "force-dynamic";
|
||||
const PATCH_RATE_LIMIT = 60;
|
||||
const PATCH_WINDOW_MS = 60_000;
|
||||
|
||||
const patchBodySchema = 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.",
|
||||
}),
|
||||
});
|
||||
|
||||
interface InjectionSitePrefsResponse {
|
||||
globalExcludedInjectionSites: InjectionSiteValue[];
|
||||
}
|
||||
@@ -96,7 +82,7 @@ export const PATCH = apiHandler(async (request: NextRequest) => {
|
||||
});
|
||||
if (jsonError) return jsonError;
|
||||
|
||||
const parsed = patchBodySchema.safeParse(body);
|
||||
const parsed = injectionSitePrefsPatchSchema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
annotate({
|
||||
action: { name: "auth.me.injection-site-prefs.patch.invalid_shape" },
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* limit, Zod safeParse → 422 via `returnAllZodIssues`, audit-log row,
|
||||
* field-by-field write (no mass assignment).
|
||||
*/
|
||||
import { z } from "zod";
|
||||
|
||||
import { apiHandler, requireAuth, HttpError } from "@/lib/api-handler";
|
||||
import {
|
||||
apiError,
|
||||
@@ -30,10 +28,7 @@ import { auditLog } from "@/lib/auth/audit";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { checkRateLimit, rateLimitHeaders } from "@/lib/rate-limit";
|
||||
import { DEFAULT_UNIT_PREFERENCE } from "@/lib/measurements/display-transform";
|
||||
|
||||
const patchBodySchema = z.object({
|
||||
unitPreference: z.enum(["metric", "imperial"]),
|
||||
});
|
||||
import { unitPreferencePatchSchema } from "@/lib/validations/user-prefs";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -85,7 +80,7 @@ export const PATCH = apiHandler(async (req: Request) => {
|
||||
throw new HttpError(422, "unit-preference.body.invalid_json");
|
||||
}
|
||||
|
||||
const parsed = patchBodySchema.safeParse(body);
|
||||
const parsed = unitPreferencePatchSchema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
annotate({
|
||||
action: { name: "auth.me.unit-preference.patch.invalid_shape" },
|
||||
|
||||
@@ -9,10 +9,7 @@ import {
|
||||
import { NextRequest } from "next/server";
|
||||
import { apiHandler, requireAuth } from "@/lib/api-handler";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { webauthnKeyNameSchema } from "@/lib/validations/mfa";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
const passkeyRenameSchema = z.object({ name: webauthnKeyNameSchema });
|
||||
import { passkeyRenameSchema } from "@/lib/validations/auth";
|
||||
|
||||
export const PATCH = apiHandler(
|
||||
async (
|
||||
|
||||
Reference in new issue
Block a user