feat: API sync and documentation audit - 100% endpoint coverage (#94)

Code quality:
- Add Zod validation to 14 route handlers that used raw JSON.parse
  (favicon, find-duplicates, barcode-read, upscale, blur-faces,
  erase-object, colorize, enhance-faces, red-eye-removal,
  remove-background/effects, auth, api-keys, roles, teams,
  analytics, settings, user-files)
- Standardize error responses to safeParse + formatZodErrors pattern
- Replace unsafe `as` type casts with schema validation

OpenAPI spec (89 -> 115 operations):
- Add 14 missing tool endpoints (adjust-colors, sharpening,
  optimize-for-web, image-enhancement, noise-removal, red-eye-removal,
  restore-photo, passport-photo, colorize, enhance-faces, image-to-base64)
- Add 12 missing non-tool endpoints (analytics, features, audit-log,
  roles, admin-health)
- Add typed error schemas for 401/403/409 responses
- Add descriptions to all path parameters
- Bump version from 0.9.0 to 1.15.9

Documentation:
- Fix 8 incorrect env var defaults in configuration guide
- Add 15 undocumented env vars to configuration guide
- Fix tool ID mismatch (color-adjustments -> adjust-colors)
- Add 4 new API sections (Roles, Audit Log, Analytics, Features)
- Add image-enhancement to AI engine reference
- Update AI tool count from 13 to 14 across all docs
- Add 6 missing doc links to README
This commit is contained in:
Ashim
2026-04-23 20:26:58 +08:00
committed by GitHub
parent 136a4dd641
commit 97938bdc47
28 changed files with 2814 additions and 191 deletions
+24 -5
View File
@@ -6,6 +6,7 @@ import { getBundleForTool, TOOL_BUNDLE_MAP } from "@ashim/shared";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import { z } from "zod";
import { autoOrient } from "../../lib/auto-orient.js";
import { formatZodErrors } from "../../lib/errors.js";
import { isToolInstalled } from "../../lib/feature-status.js";
import { validateImageBuffer } from "../../lib/file-validation.js";
import { decodeToSharpCompat, needsCliDecode } from "../../lib/format-decoders.js";
@@ -14,6 +15,11 @@ import { createWorkspace } from "../../lib/workspace.js";
import { updateSingleFileProgress } from "../progress.js";
import { registerToolProcessFn } from "../tool-factory.js";
const settingsSchema = z.object({
blurRadius: z.number().min(1).max(100).default(30),
sensitivity: z.number().min(0).max(1).default(0.5),
});
/** Face detection and blurring route. */
export function registerBlurFaces(app: FastifyInstance) {
app.post("/api/v1/tools/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
@@ -67,7 +73,19 @@ export function registerBlurFaces(app: FastifyInstance) {
}
try {
const settings = settingsRaw ? JSON.parse(settingsRaw) : {};
let settings: z.infer<typeof settingsSchema>;
try {
const parsed = settingsRaw ? JSON.parse(settingsRaw) : {};
const result = settingsSchema.safeParse(parsed);
if (!result.success) {
return reply
.status(400)
.send({ error: "Invalid settings", details: formatZodErrors(result.error.issues) });
}
settings = result.data;
} catch {
return reply.status(400).send({ error: "Settings must be valid JSON" });
}
if (validation.format === "heif") {
fileBuffer = await decodeHeic(fileBuffer);
@@ -78,12 +96,13 @@ export function registerBlurFaces(app: FastifyInstance) {
fileBuffer = await decodeToSharpCompat(fileBuffer, validation.format);
}
const { blurRadius, sensitivity } = settings;
request.log.info(
{
toolId: "blur-faces",
imageSize: fileBuffer.length,
blurRadius: settings.blurRadius,
sensitivity: settings.sensitivity,
blurRadius,
sensitivity,
},
"Starting face blur",
);
@@ -114,8 +133,8 @@ export function registerBlurFaces(app: FastifyInstance) {
fileBuffer,
join(workspacePath, "output"),
{
blurRadius: settings.blurRadius ?? 30,
sensitivity: settings.sensitivity ?? 0.5,
blurRadius,
sensitivity,
},
onProgress,
);