mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
docs: publish the managed-profile lifecycle routes
The contract already pointed at them: the Guardian roster names
`DELETE /api/managed-profiles/{id}/guardians/{grantId}` as the route its
`grantId` is for, and that route was not in the spec. Creation, deletion,
invitation and removal now are, with the two bodies moved to
`src/lib/validations` so the wire shape has one source.
Three things are stated rather than left to be discovered:
- the two refusals on the invitation that carry no `meta.errorCode`, and the
order a client must resolve in because of them
- the last-Guardian 409 on the removal route, which nothing can elicit through
that route today, published with the reason
- that the sentences on the ordinary invitation describe an invited grant only,
so a client cannot carry its MANAGE rules across to a Guardian grant
This commit is contained in:
1 parent
26fceca219
commit
ec9d93aa24
5 files changed
+640
-28
No files matched your search
@@ -1,5 +1,4 @@
|
||||
import { NextRequest } from "next/server";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import {
|
||||
apiHandler,
|
||||
@@ -23,6 +22,7 @@ import { ManagedProfileLifecycleError } from "@/lib/managed-profiles/lifecycle";
|
||||
import { checkRateLimit } from "@/lib/rate-limit";
|
||||
import { GRANT_PARTY_SELECT } from "@/lib/sharing/grant-view";
|
||||
import { GrantError, inviteManagedProfileGuardian } from "@/lib/sharing/grants";
|
||||
import { inviteManagedProfileGuardianSchema } from "@/lib/validations/managed-profiles";
|
||||
|
||||
type RouteParams = { params: Promise<{ id: string }> };
|
||||
|
||||
@@ -77,13 +77,6 @@ export const GET = apiHandler(
|
||||
const INVITE_LIMIT = 10;
|
||||
const INVITE_WINDOW_MS = 60 * 60 * 1000;
|
||||
|
||||
const guardianInviteSchema = z
|
||||
.object({
|
||||
identifier: z.string().trim().min(1).max(255),
|
||||
expiresAt: z.iso.datetime({ offset: true }).nullable().optional(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
/** Invite another Guardian from a cookie-backed, freshly verified session. */
|
||||
export const POST = apiHandler(
|
||||
async (request: NextRequest, { params }: RouteParams) => {
|
||||
@@ -100,7 +93,7 @@ export const POST = apiHandler(
|
||||
maxBytes: 8 * 1024,
|
||||
});
|
||||
if (jsonError) return jsonError;
|
||||
const parsed = guardianInviteSchema.safeParse(body);
|
||||
const parsed = inviteManagedProfileGuardianSchema.safeParse(body);
|
||||
if (!parsed.success) return returnAllZodIssues(parsed.error, 422);
|
||||
const { id } = await params;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { NextRequest } from "next/server";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import {
|
||||
apiHandler,
|
||||
@@ -16,7 +15,7 @@ import { auditLog } from "@/lib/auth/audit";
|
||||
import { createManagedProfile } from "@/lib/managed-profiles/create";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { checkRateLimit } from "@/lib/rate-limit";
|
||||
import { isValidTimezone } from "@/lib/tz/format";
|
||||
import { createManagedProfileSchema } from "@/lib/validations/managed-profiles";
|
||||
|
||||
/**
|
||||
* The same ceiling its guardian sibling carries, and for the same reason.
|
||||
@@ -30,19 +29,6 @@ import { isValidTimezone } from "@/lib/tz/format";
|
||||
const CREATE_LIMIT = 10;
|
||||
const CREATE_WINDOW_MS = 60 * 60 * 1000;
|
||||
|
||||
const managedProfileSchema = z
|
||||
.object({
|
||||
displayName: z.string().trim().min(1).max(80),
|
||||
dateOfBirth: z.iso.date().nullable().optional(),
|
||||
locale: z.enum(["de", "en", "es", "fr", "it", "pl"]),
|
||||
timezone: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(64)
|
||||
.refine(isValidTimezone, "Invalid IANA timezone"),
|
||||
})
|
||||
.strict();
|
||||
|
||||
/**
|
||||
* Create a record a Guardian administers. This deliberately uses the
|
||||
* cookie-only fresh-MFA gate: a Bearer token cannot mint a credential-less
|
||||
@@ -65,7 +51,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
});
|
||||
if (jsonError) return jsonError;
|
||||
|
||||
const parsed = managedProfileSchema.safeParse(body);
|
||||
const parsed = createManagedProfileSchema.safeParse(body);
|
||||
if (!parsed.success) return returnAllZodIssues(parsed.error, 422);
|
||||
|
||||
const { profile, creatorGrant } = await createManagedProfile({
|
||||
|
||||
Reference in new issue
Block a user