feat(ql3): gate primary on shadow capture evidence

This commit is contained in:
whyour
2026-08-19 03:27:32 +08:00
parent c60a86d1bf
commit be98d6753b
28 changed files with 2227 additions and 30 deletions
@@ -1,4 +1,5 @@
import { createHash } from 'crypto';
import { constants } from 'fs';
import fs from 'fs/promises';
import path from 'path';
import {
@@ -9,6 +10,10 @@ import type {
RuntimeRolloutLoadAudit,
RuntimeRolloutLoadResult,
} from '../../ports/runtimeRolloutLoader';
import {
parseLegacyShadowPrimaryGateReceipt,
type LegacyShadowPrimaryGateReceipt,
} from '../../domain/legacyShadowPrimaryGate';
export type {
RuntimeRolloutLoadAudit,
@@ -17,6 +22,7 @@ export type {
} from '../../ports/runtimeRolloutLoader';
export const MAX_RUNTIME_ROLLOUT_MANIFEST_BYTES = 64 * 1024;
export const MAX_RUNTIME_PRIMARY_GATE_RECEIPT_BYTES = 64 * 1024;
export interface RuntimeRolloutManifestLoaderOptions {
clock?: { now(): number };
@@ -34,6 +40,47 @@ function rejected(
};
}
async function loadPrimaryGateReceipt(
manifestPath: string,
receiptFile: string,
expectedSha256: string,
approvedAtMs: number,
): Promise<LegacyShadowPrimaryGateReceipt> {
const receiptPath = path.join(path.dirname(manifestPath), receiptFile);
let handle;
try {
handle = await fs.open(
receiptPath,
constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),
);
const stat = await handle.stat();
if (
!stat.isFile() ||
(stat.mode & 0o077) !== 0 ||
stat.size < 2 ||
stat.size > MAX_RUNTIME_PRIMARY_GATE_RECEIPT_BYTES
) {
throw new TypeError('Primary gate receipt file shape is invalid');
}
const bytes = await handle.readFile();
if (createHash('sha256').update(bytes).digest('hex') !== expectedSha256) {
throw new TypeError('Primary gate receipt digest does not match');
}
const receipt = parseLegacyShadowPrimaryGateReceipt(
JSON.parse(bytes.toString('utf8')),
);
if (
receipt.assessment !== 'eligible' ||
receipt.generatedAtMs > approvedAtMs
) {
throw new TypeError('Primary gate receipt is not eligible for approval');
}
return receipt;
} finally {
await handle?.close();
}
}
export async function loadRuntimeRolloutManifest(
sourcePath: string,
options: RuntimeRolloutManifestLoaderOptions = {},
@@ -90,10 +137,29 @@ export async function loadRuntimeRolloutManifest(
try {
const decision = parseRuntimeRolloutManifest(value, evaluatedAtMs);
const status = decision.manifest.enabled ? 'accepted' : 'disabled';
let primaryGateReceipt: LegacyShadowPrimaryGateReceipt | undefined;
if (decision.manifest.enabled) {
try {
primaryGateReceipt = await loadPrimaryGateReceipt(
sourcePath,
decision.manifest.primaryGate.receiptFile,
decision.manifest.primaryGate.receiptSha256,
decision.manifest.approvedAtMs,
);
} catch (error) {
return rejected(
hashedAudit,
(error as NodeJS.ErrnoException).code === 'ENOENT'
? 'PRIMARY_GATE_READ_FAILED'
: 'PRIMARY_GATE_INVALID',
);
}
}
return {
status,
policy: decision.policy,
manifest: decision.manifest,
...(primaryGateReceipt === undefined ? {} : { primaryGateReceipt }),
audit: {
...hashedAudit,
status,
@@ -52,8 +52,25 @@ export async function bootstrapDefaultManualPrimaryRuntime(
Logger.info(`[runtime-activation] ${JSON.stringify(record)}`);
});
let stackModule: DefaultManualPrimaryStackModule | undefined;
let selectedProfile: 'edge' | 'standalone' | undefined;
if (selected) {
try {
const profile =
options.deploymentProfile ??
parseDeploymentProfile(process.env.QL_DEPLOYMENT_PROFILE);
if (profile === 'cluster-control' || profile === 'worker') {
throw new Error('Local Primary requires edge or standalone Profile');
}
if (
load.primaryGateReceipt?.assessment !== 'eligible' ||
load.primaryGateReceipt.origin !== 'manual' ||
load.primaryGateReceipt.profile !== profile
) {
throw new Error(
'Primary gate receipt does not authorize this deployment Profile',
);
}
selectedProfile = profile;
stackModule = await (
options.loadStack ?? (() => import('./defaultManualPrimaryActivation'))
)();
@@ -87,9 +104,7 @@ export async function bootstrapDefaultManualPrimaryRuntime(
}
return stackModule.createDefaultManualPrimaryActivationStack(rollout, {
...activationOptions,
deploymentProfile:
options.deploymentProfile ??
parseDeploymentProfile(process.env.QL_DEPLOYMENT_PROFILE),
deploymentProfile: selectedProfile!,
});
},
install: options.install ?? installManualPrimaryExecutionRouter,
@@ -0,0 +1,254 @@
import fs from 'fs/promises';
import path from 'path';
import config from '../../../config';
import Logger from '../../../loaders/logger';
import {
createLegacyShadowCaptureReport,
type LegacyShadowCaptureReport,
type LegacyShadowCaptureSnapshot,
} from '../../application/legacyShadowCaptureAuthority';
import {
configuredLegacyShadowOrigins,
legacyShadowCaptureSnapshot,
} from '../../compatibility/legacyExecutionBridge';
import {
parseDeploymentProfile,
type DeploymentProfile,
} from '../../domain/deploymentProfile';
import type { ExecutionOrigin } from '../../domain/run';
import type {
LegacyShadowStartupAudit,
LegacyShadowStartupDifferenceReport,
} from './bootstrapLegacyShadowStartupReconciliation';
export const LEGACY_SHADOW_CAPTURE_EVIDENCE_SCHEMA =
'qinglong/legacy-shadow-capture-evidence@v1';
export const LEGACY_SHADOW_CAPTURE_EVIDENCE_FILE_ENV =
'QL3_SHADOW_CAPTURE_EVIDENCE_FILE';
export interface LegacyShadowCaptureEvidence {
schema: typeof LEGACY_SHADOW_CAPTURE_EVIDENCE_SCHEMA;
profile: 'edge' | 'standalone';
startup: LegacyShadowStartupDifferenceReport;
capture: LegacyShadowCaptureReport;
qualification: {
passed: boolean;
startupConverged: boolean;
originCoverageExact: boolean;
captureComplete: boolean;
};
}
export type LegacyShadowCaptureEvidenceAudit =
| { state: 'disabled' }
| { state: 'profile_rejected'; profile: 'cluster-control' | 'worker' }
| { state: 'armed'; profile: 'edge' | 'standalone'; origins: number }
| {
state: 'exported';
profile: 'edge' | 'standalone';
origins: number;
qualified: boolean;
}
| { state: 'failed'; errorType: string };
export interface LegacyShadowCaptureEvidenceHandle {
active: boolean;
close(): Promise<LegacyShadowCaptureEvidenceAudit>;
}
export interface BootstrapLegacyShadowCaptureEvidenceOptions {
startup: LegacyShadowStartupAudit;
origins?: readonly ExecutionOrigin[];
profile?: DeploymentProfile;
outputPath?: string;
snapshot?: (
origins: readonly ExecutionOrigin[],
) => LegacyShadowCaptureSnapshot;
write?: (
outputPath: string,
evidence: LegacyShadowCaptureEvidence,
) => Promise<void>;
audit?: (record: LegacyShadowCaptureEvidenceAudit) => void | Promise<void>;
}
const FILE_NAME_PATTERN =
/^(?=.{1,128}$)(?!\.)(?!.*\.\.)(?:[A-Za-z0-9][A-Za-z0-9._-]*)\.json$/u;
function configuredOutputPath(): string | undefined {
const fileName = process.env[LEGACY_SHADOW_CAPTURE_EVIDENCE_FILE_ENV]?.trim();
if (!fileName) return undefined;
if (
!FILE_NAME_PATTERN.test(fileName) ||
path.basename(fileName) !== fileName
) {
throw new TypeError('Legacy Shadow capture evidence filename is invalid');
}
return path.join(config.configPath, fileName);
}
async function writeEvidence(
outputPath: string,
evidence: LegacyShadowCaptureEvidence,
): Promise<void> {
if (!path.isAbsolute(outputPath)) {
throw new TypeError('Legacy Shadow capture evidence path must be absolute');
}
const handle = await fs.open(outputPath, 'wx', 0o600);
try {
await handle.writeFile(`${JSON.stringify(evidence)}\n`, 'utf8');
await handle.sync();
} finally {
await handle.close();
}
}
function exactOriginCoverage(
origins: readonly ExecutionOrigin[],
startup: LegacyShadowStartupDifferenceReport,
): boolean {
return (
startup.configuredOriginCount === origins.length &&
startup.byOrigin.length === origins.length &&
origins.every((origin, index) => startup.byOrigin[index]?.origin === origin)
);
}
async function emitAudit(
audit: (record: LegacyShadowCaptureEvidenceAudit) => void | Promise<void>,
record: LegacyShadowCaptureEvidenceAudit,
): Promise<void> {
try {
await audit(record);
} catch {
// Evidence diagnostics must not change Legacy startup or shutdown.
}
}
/**
* Arms one process-lifetime capture window after startup reconciliation. It has
* no timer or watcher and writes exactly one owner-private report on a clean
* shutdown when an explicit filename is configured.
*/
export async function bootstrapLegacyShadowCaptureEvidence(
options: BootstrapLegacyShadowCaptureEvidenceOptions,
): Promise<LegacyShadowCaptureEvidenceHandle> {
const audit =
options.audit ??
((record: LegacyShadowCaptureEvidenceAudit) => {
Logger.info(`[ql3-shadow-capture] ${JSON.stringify(record)}`);
});
const origins = [
...new Set(options.origins ?? configuredLegacyShadowOrigins()),
];
let outputPath: string | undefined;
try {
outputPath = options.outputPath ?? configuredOutputPath();
} catch (error) {
const record: LegacyShadowCaptureEvidenceAudit = {
state: 'failed',
errorType: error instanceof Error ? error.name : 'unknown',
};
await emitAudit(audit, record);
return {
active: false,
async close() {
return record;
},
};
}
if (origins.length === 0 || outputPath === undefined) {
const record: LegacyShadowCaptureEvidenceAudit = { state: 'disabled' };
await emitAudit(audit, record);
return {
active: false,
async close() {
return record;
},
};
}
const profile =
options.profile ??
parseDeploymentProfile(process.env.QL_DEPLOYMENT_PROFILE);
if (profile === 'cluster-control' || profile === 'worker') {
const record: LegacyShadowCaptureEvidenceAudit = {
state: 'profile_rejected',
profile,
};
await emitAudit(audit, record);
return {
active: false,
async close() {
return record;
},
};
}
if (
options.startup.state !== 'reconciled' ||
options.startup.report.profile !== profile
) {
const record: LegacyShadowCaptureEvidenceAudit = {
state: 'failed',
errorType: 'LegacyShadowStartupEvidenceUnavailable',
};
await emitAudit(audit, record);
return {
active: false,
async close() {
return record;
},
};
}
const startupReport = options.startup.report;
const snapshot = options.snapshot ?? legacyShadowCaptureSnapshot;
const before = snapshot(origins);
const armed: LegacyShadowCaptureEvidenceAudit = {
state: 'armed',
profile,
origins: origins.length,
};
await emitAudit(audit, armed);
let closed: LegacyShadowCaptureEvidenceAudit | undefined;
return {
active: true,
async close() {
if (closed) return closed;
try {
const capture = createLegacyShadowCaptureReport(
profile,
origins,
before,
snapshot(origins),
);
const startupConverged = startupReport.assessment === 'converged';
const originCoverageExact = exactOriginCoverage(origins, startupReport);
const captureComplete = capture.assessment === 'captured';
const evidence: LegacyShadowCaptureEvidence = {
schema: LEGACY_SHADOW_CAPTURE_EVIDENCE_SCHEMA,
profile,
startup: startupReport,
capture,
qualification: {
passed: startupConverged && originCoverageExact && captureComplete,
startupConverged,
originCoverageExact,
captureComplete,
},
};
await (options.write ?? writeEvidence)(outputPath!, evidence);
closed = {
state: 'exported',
profile,
origins: origins.length,
qualified: evidence.qualification.passed,
};
} catch (error) {
closed = {
state: 'failed',
errorType: error instanceof Error ? error.name : 'unknown',
};
}
await emitAudit(audit, closed);
return closed;
},
};
}