This commit implements several security enhancements based on the findings of a new security audit report, which has also been added to the documentation. - **Security Headers:** Adds a strict Content-Security-Policy (CSP) and other security headers (X-Content-Type-Options, Referrer-Policy) via Nuxt route rules. - **Production Hardening:** Disables Nuxt DevTools in production environments to reduce the attack surface. - **Mixed Content:** All image assets are now loaded over HTTPS to resolve mixed content issues. - **Tabnabbing:** Secures `window.open` calls by adding `noopener,noreferrer`. - **Configuration:** Updates `.gitignore` to ignore all `.env.*` files. - **Docs:** Adds the full security audit report for reference. - **Build:** Corrects a case-sensitive import path to ensure cross-platform build compatibility.
87 lines
2.1 KiB
TypeScript
87 lines
2.1 KiB
TypeScript
import { defineContentConfig, defineCollection, z } from "@nuxt/content";
|
||
import { PricingPlanPropsSchema } from "./app/schemas/pricingPlanSchema";
|
||
|
||
const defineIndexSchema = () =>
|
||
z.object({
|
||
capabilities: z.object({
|
||
title: z.string(),
|
||
features: z.array(
|
||
z.object({
|
||
title: z.string(),
|
||
description: z.string(),
|
||
icon: z.string(),
|
||
})
|
||
),
|
||
}),
|
||
featuredProjects: z.object({
|
||
title: z.string(),
|
||
projects: z.array(
|
||
z.object({
|
||
title: z.string(),
|
||
description: z.string(),
|
||
image: z.string(),
|
||
demoLink: z.string(),
|
||
highlight: z.boolean(),
|
||
spotlight: z.boolean(),
|
||
})
|
||
),
|
||
}),
|
||
techStack: z.object({
|
||
title: z.string(),
|
||
}),
|
||
whyChooseUs: z.object({
|
||
title: z.string(),
|
||
features: z.array(
|
||
z.object({
|
||
title: z.string(),
|
||
description: z.string(),
|
||
icon: z.string(),
|
||
})
|
||
),
|
||
}),
|
||
});
|
||
|
||
const defineWebDevSchema = () =>
|
||
z.object({
|
||
remarks: z.string(),
|
||
services: z.array(
|
||
z.object({
|
||
id: z.string().min(1),
|
||
label: z.string().min(1),
|
||
icon: z.string().optional(), // 比如 "lucide:mouse-pointer-click"
|
||
// 你原结构里通过 createService 包装,但最终是一个对象
|
||
plans: z
|
||
.array(PricingPlanPropsSchema)
|
||
.min(1),
|
||
// 预留扩展字段(例如:category、tags、hidden 等)
|
||
category: z.string().optional(),
|
||
tags: z.array(z.string()).optional(),
|
||
})
|
||
),
|
||
});
|
||
|
||
export default defineContentConfig({
|
||
collections: {
|
||
index_en: defineCollection({
|
||
type: "page",
|
||
source: "en-US/index.yml",
|
||
schema: defineIndexSchema(),
|
||
}),
|
||
index_zh: defineCollection({
|
||
type: "page",
|
||
source: "zh-CN/index.yml",
|
||
schema: defineIndexSchema(),
|
||
}),
|
||
webDev_en: defineCollection({
|
||
type: "page",
|
||
source: "en-US/webDev.yml",
|
||
schema: defineWebDevSchema(),
|
||
}),
|
||
webDev_zh: defineCollection({
|
||
type: "page",
|
||
source: "zh-CN/webDev.yml",
|
||
schema: defineWebDevSchema(),
|
||
}),
|
||
},
|
||
});
|