/*
Page output projection schema for the system manifest: controls per-page output settings like sitemap inclusion and canonical URLs.
- Do not introduce app-specific runtime composition or deployment behavior into this reusable package source file.
- RFC-0303 Phase 3: extracted from schemas/system.ts as part of the domain split.
- RFC-1106: step 4 — single-source SemanticPageType
semanticPageTypeSchema (ontology/schemas/system/page-output.ts) is now the sole declaration of the closed DNA-19 vocabulary. semantic/models.ts derives the type via z.infer and SEMANTIC_PAGE_TYPES via schema.options — the hand-synced union/array and stale circular-dependency comments are deleted.
*/
import { z } from "zod";
/**
* RFC-0042/RFC-0050: the semantic role of a page. Drives semantic model
* construction and the default llms inclusion depth. Mirrors
* SemanticPageType in @warpgogol/werkstatt-shared/semantic.
*/
// RFC-1106: this schema is the sole declaration of the SemanticPageType closed
// vocabulary (DNA-19). `semantic/models.ts` derives the type and the runtime
// array from it — do not declare a parallel union elsewhere.
export const semanticPageTypeSchema = z.enum([
"home",
"about",
"projects",
"donationContact",
"openSource",
"content",
"article",
"person",
"participant",
"legal",
"collection",
]);
/** RFC-0167: per-page article metadata (Article/BlogPosting JSON-LD + dates + author). */
export const articleMetadataSchema = z
.object({
publishedAt: z.string().min(1),
updatedAt: z.string().min(1).optional(),
author: z.string().min(1).optional(),
tags: z.array(z.string().min(1)).optional(),
})
.strict();
/** RFC-0142: per-page llms inclusion depth value (string shorthand or object). */
const llmsDepthSchema = z.enum(["full", "summary", "index-only", "exclude"]);
export const llmsPolicySchema = z.union([
llmsDepthSchema,
z
.object({
depth: llmsDepthSchema.optional(),
sections: z.object({ exclude: z.array(z.string()).optional() }).optional(),
})
.strict(),
]);
/** RFC-0143: per-page sitemap projection value (boolean shorthand or object). */
export const sitemapProjectionSchema = z.union([
z.boolean(),
z
.object({
include: z.boolean().optional(),
category: z.string().min(1).optional(),
lastmod: z.string().min(1).optional(),
includeLastmod: z.boolean().optional(),
})
.strict(),
]);
/**
* RFC-0143: the per-page `output` block — a CLOSED container of per-page
* projection generators. Each known generator owns exactly one key; unknown
* keys are a validation error. A new per-page generator extends this schema
* in the same change that adds the generator.
*/
/** RFC-0165: per-page robots/indexability (boolean shorthand or object). */
export const robotsProjectionSchema = z.union([
z.boolean(),
z
.object({
index: z.boolean().optional(),
follow: z.boolean().optional(),
})
.strict(),
]);
export const pageOutputSchema = z
.object({
sitemap: sitemapProjectionSchema.optional(),
llms: llmsPolicySchema.optional(),
robots: robotsProjectionSchema.optional(),
/** RFC-0257: enable SSG PDF generation for this app. Default false. */
printPdf: z.boolean().optional(),
})
.strict();