| 1 | import { NextResponse } from "next/server"; |
| 2 | import { BUILD_FACTS, getFactsWithProvenance, type RepoFacts } from "@/lib/facts"; |
| 3 | import { cloudFactsSummary } from "@/lib/cloud-facts"; |
| 4 | import { getEnv } from "@/lib/kv"; |
| 5 | |
| 6 | export const dynamic = "force-dynamic"; |
| 7 | export const revalidate = 0; |
| 8 | |
| 9 | function summary(facts: RepoFacts) { |
| 10 | return { |
| 11 | sourceRevision: facts.sourceRevision, |
| 12 | sourceCommittedAt: facts.sourceCommittedAt, |
| 13 | version: facts.version, |
| 14 | providerCount: facts.providers.length, |
| 15 | modelCount: facts.models.length, |
| 16 | toolCount: facts.toolCount, |
| 17 | }; |
| 18 | } |
| 19 | |
| 20 | /** Public, credential-free source/deployment drift receipt. */ |
| 21 | export async function GET() { |
| 22 | const resolution = await getFactsWithProvenance(); |
| 23 | // Additive: the cloud facts channel currently served by /api/facts/v1/stable |
| 24 | // (null when unconfigured or unverifiable), so deployed-facts checks can |
| 25 | // later assert served == published. |
| 26 | const cloudFacts = await cloudFactsSummary(await getEnv()); |
| 27 | return NextResponse.json( |
| 28 | { |
| 29 | schemaVersion: 1, |
| 30 | deployed: summary(BUILD_FACTS), |
| 31 | resolved: { |
| 32 | ...summary(resolution.facts), |
| 33 | source: resolution.source, |
| 34 | reason: resolution.reason, |
| 35 | }, |
| 36 | latestPublishedRelease: resolution.facts.latestPublishedRelease, |
| 37 | cloudFacts, |
| 38 | }, |
| 39 | { |
| 40 | headers: { |
| 41 | "Cache-Control": "no-store", |
| 42 | }, |
| 43 | }, |
| 44 | ); |
| 45 | } |
| 46 |