feat(core-api): add verification pipeline with vertex attire adapter
This commit is contained in:
@@ -4,10 +4,23 @@ import { z } from 'zod';
|
||||
import { AppError } from '../lib/errors.js';
|
||||
import { requireAuth, requirePolicy } from '../middleware/auth.js';
|
||||
import { createSignedUrlSchema } from '../contracts/core/create-signed-url.js';
|
||||
import { createVerificationSchema } from '../contracts/core/create-verification.js';
|
||||
import { invokeLlmSchema } from '../contracts/core/invoke-llm.js';
|
||||
import { reviewVerificationSchema } from '../contracts/core/review-verification.js';
|
||||
import { invokeVertexModel } from '../services/llm.js';
|
||||
import { checkLlmRateLimit } from '../services/llm-rate-limit.js';
|
||||
import { generateReadSignedUrl, uploadToGcs, validateFileUriAccess } from '../services/storage.js';
|
||||
import {
|
||||
ensureFileExistsForActor,
|
||||
generateReadSignedUrl,
|
||||
uploadToGcs,
|
||||
validateFileUriAccess,
|
||||
} from '../services/storage.js';
|
||||
import {
|
||||
createVerificationJob,
|
||||
getVerificationJob,
|
||||
retryVerificationJob,
|
||||
reviewVerificationJob,
|
||||
} from '../services/verification-jobs.js';
|
||||
|
||||
const DEFAULT_MAX_FILE_BYTES = 10 * 1024 * 1024;
|
||||
const DEFAULT_MAX_SIGNED_URL_SECONDS = 900;
|
||||
@@ -42,6 +55,10 @@ function useMockUpload() {
|
||||
return process.env.UPLOAD_MOCK !== 'false';
|
||||
}
|
||||
|
||||
function requireVerificationFileExists() {
|
||||
return process.env.VERIFICATION_REQUIRE_FILE_EXISTS !== 'false';
|
||||
}
|
||||
|
||||
function parseBody(schema, body) {
|
||||
const parsed = schema.safeParse(body);
|
||||
if (!parsed.success) {
|
||||
@@ -177,12 +194,84 @@ async function handleInvokeLlm(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCreateVerification(req, res, next) {
|
||||
try {
|
||||
const payload = parseBody(createVerificationSchema, req.body || {});
|
||||
validateFileUriAccess({
|
||||
fileUri: payload.fileUri,
|
||||
actorUid: req.actor.uid,
|
||||
});
|
||||
|
||||
if (requireVerificationFileExists() && !useMockUpload()) {
|
||||
await ensureFileExistsForActor({
|
||||
fileUri: payload.fileUri,
|
||||
actorUid: req.actor.uid,
|
||||
});
|
||||
}
|
||||
|
||||
const created = createVerificationJob({
|
||||
actorUid: req.actor.uid,
|
||||
payload,
|
||||
});
|
||||
return res.status(202).json({
|
||||
...created,
|
||||
requestId: req.requestId,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGetVerification(req, res, next) {
|
||||
try {
|
||||
const verificationId = req.params.verificationId;
|
||||
const job = getVerificationJob(verificationId, req.actor.uid);
|
||||
return res.status(200).json({
|
||||
...job,
|
||||
requestId: req.requestId,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleReviewVerification(req, res, next) {
|
||||
try {
|
||||
const verificationId = req.params.verificationId;
|
||||
const payload = parseBody(reviewVerificationSchema, req.body || {});
|
||||
const updated = reviewVerificationJob(verificationId, req.actor.uid, payload);
|
||||
return res.status(200).json({
|
||||
...updated,
|
||||
requestId: req.requestId,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRetryVerification(req, res, next) {
|
||||
try {
|
||||
const verificationId = req.params.verificationId;
|
||||
const updated = retryVerificationJob(verificationId, req.actor.uid);
|
||||
return res.status(202).json({
|
||||
...updated,
|
||||
requestId: req.requestId,
|
||||
});
|
||||
} catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
}
|
||||
|
||||
export function createCoreRouter() {
|
||||
const router = Router();
|
||||
|
||||
router.post('/upload-file', requireAuth, requirePolicy('core.upload', 'file'), upload.single('file'), handleUploadFile);
|
||||
router.post('/create-signed-url', requireAuth, requirePolicy('core.sign-url', 'file'), handleCreateSignedUrl);
|
||||
router.post('/invoke-llm', requireAuth, requirePolicy('core.invoke-llm', 'model'), handleInvokeLlm);
|
||||
router.post('/verifications', requireAuth, requirePolicy('core.verification.create', 'verification'), handleCreateVerification);
|
||||
router.get('/verifications/:verificationId', requireAuth, requirePolicy('core.verification.read', 'verification'), handleGetVerification);
|
||||
router.post('/verifications/:verificationId/review', requireAuth, requirePolicy('core.verification.review', 'verification'), handleReviewVerification);
|
||||
router.post('/verifications/:verificationId/retry', requireAuth, requirePolicy('core.verification.retry', 'verification'), handleRetryVerification);
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user