chore: stabilize Zhinian pilot delivery

This commit is contained in:
inman
2026-05-12 19:44:44 +08:00
parent 45389855e1
commit 20b5aff4ad
174 changed files with 41428 additions and 784 deletions

View File

@@ -2,6 +2,7 @@
import { spawnSync } from 'node:child_process';
import {
chmodSync,
cpSync,
existsSync,
mkdirSync,
@@ -137,7 +138,9 @@ function collectSecretLikeEnvValues(sourceDir) {
function shouldCopyPublic(src) {
const name = basename(src);
if (name === 'uploads' || name === 'generated-results') return false;
if (name === 'uploads') return false;
const publicRelative = relative(publicDir, src).split('\\').join('/');
if (publicRelative === 'generated-results' || publicRelative.startsWith('generated-results/')) return false;
if (name.startsWith('.env')) return false;
return true;
}
@@ -146,7 +149,11 @@ function shouldCopyRuntime(src) {
const name = basename(src);
if (name.startsWith('.env')) return false;
if (name === '.data' || name === '.git' || name === '.next-cache') return false;
if (name === 'uploads' || name === 'generated-results') return false;
const runtimeRelative = relative(standaloneDir, src).split('\\').join('/');
if (runtimeRelative === 'public/uploads' || runtimeRelative.startsWith('public/uploads/')) return false;
if (runtimeRelative === 'public/generated-results' || runtimeRelative.startsWith('public/generated-results/')) return false;
if (runtimeRelative === 'uploads' || runtimeRelative.startsWith('uploads/')) return false;
if (runtimeRelative === 'generated-results' || runtimeRelative.startsWith('generated-results/')) return false;
return true;
}
@@ -161,6 +168,26 @@ function copyDir(from, to, filter = () => true) {
return true;
}
function normalizeBundlePermissions(dir) {
if (!existsSync(dir)) return;
const stats = statSync(dir);
try {
if (stats.isDirectory()) {
chmodSync(dir, 0o755);
for (const entry of readdirSync(dir)) {
normalizeBundlePermissions(join(dir, entry));
}
return;
}
if (stats.isFile()) {
const executable = (stats.mode & 0o111) !== 0;
chmodSync(dir, executable ? 0o755 : 0o644);
}
} catch (error) {
fail(`Unable to normalize bundle permissions for ${relative(ROOT, dir)}: ${error.message}`);
}
}
function dirSizeBytes(dir) {
if (!existsSync(dir)) return 0;
const stats = statSync(dir);
@@ -192,6 +219,19 @@ function assertNoEnvFiles(dir) {
}
}
function assertNoForbiddenBundlePaths(outputDir) {
const forbidden = [
join(outputDir, 'public', 'uploads'),
join(outputDir, 'public', 'generated-results'),
join(outputDir, '.next', 'cache'),
];
for (const target of forbidden) {
if (existsSync(target)) {
fail(`Refusing to ship development/user data path: ${relative(ROOT, target)}`);
}
}
}
function shouldScanForSecrets(filePath) {
const stats = statSync(filePath);
if (!stats.isFile()) return false;
@@ -266,7 +306,9 @@ copyDir(publicDir, join(OUTPUT_DIR, 'public'), shouldCopyPublic);
copyDir(contentDir, join(OUTPUT_DIR, 'content'), shouldCopyRuntime);
const runtimeEnv = writeRuntimeEnvFile(SOURCE_DIR, OUTPUT_DIR);
normalizeBundlePermissions(OUTPUT_DIR);
assertNoEnvFiles(OUTPUT_DIR);
assertNoForbiddenBundlePaths(OUTPUT_DIR);
assertNoSecretValues(OUTPUT_DIR, secretLikeEnvValues);
const manifest = {
@@ -276,7 +318,7 @@ const manifest = {
bundledAt: new Date().toISOString(),
runtime: 'next-standalone',
entry: 'server.js',
excludes: ['.env*', '.data', 'public/uploads', 'public/generated-results'],
excludes: ['.env*', '.data', 'public/uploads', 'public/generated-results', 'development caches'],
secretScan: {
checked: true,
sourceEnvValues: secretLikeEnvValues.length,