feat: implement demo candidate 1.0.0-rc.1
This commit is contained in:
195
release-environment.js
Normal file
195
release-environment.js
Normal file
@@ -0,0 +1,195 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const { statSync } = require('fs');
|
||||
|
||||
function requireRuntimeFile(environment, field, minimumSize, maximumSize) {
|
||||
const file = String(environment[field] || '').trim();
|
||||
if (!path.isAbsolute(file)) {
|
||||
throw new Error(`${field} must be absolute`);
|
||||
}
|
||||
const stat = statSync(file, { throwIfNoEntry: false });
|
||||
if (!stat?.isFile() || stat.size < minimumSize || stat.size > maximumSize) {
|
||||
throw new Error(`${field} is unavailable or invalid`);
|
||||
}
|
||||
}
|
||||
|
||||
function requireExactReleaseEnvironment(environment = process.env) {
|
||||
const runtimeEnvironment = String(environment.NODE_ENV || '')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const localOrTest = ['local', 'test'].includes(runtimeEnvironment);
|
||||
const required =
|
||||
runtimeEnvironment === 'prod' ||
|
||||
runtimeEnvironment === 'production' ||
|
||||
environment.RPC_REQUIRE_EXACT_RELEASE === 'true';
|
||||
if (!required) return;
|
||||
|
||||
const fields = [
|
||||
'RPC_SERVICE_VERSION',
|
||||
'RPC_MIN_SCHEMA_VERSION',
|
||||
'RPC_MAX_SCHEMA_VERSION',
|
||||
'RPC_RELEASE_ID',
|
||||
'RPC_RELEASE_VERSION',
|
||||
'RPC_SCHEMA_CHECKSUM',
|
||||
'RPC_ACTION_MANIFEST_CHECKSUM',
|
||||
'RPC_RUNTIME_CONTRACT_CHECKSUM',
|
||||
'RPC_IMPLEMENTATION_MANIFEST_CHECKSUM',
|
||||
'RPC_ARTIFACT_DIGEST',
|
||||
'BUILD_SHA',
|
||||
'SAAS_CONTROL_PLANE_URL',
|
||||
'SAAS_TENANT_CREDENTIALS_FILE',
|
||||
];
|
||||
const missing = fields.filter(
|
||||
field => !String(environment[field] || '').trim()
|
||||
);
|
||||
if (missing.length) {
|
||||
throw new Error(
|
||||
`Exact SaaS Release environment is incomplete: ${missing.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
const bootstrapTicketFile = String(
|
||||
environment.SAAS_RUNTIME_BOOTSTRAP_TOKEN_FILE || ''
|
||||
).trim();
|
||||
const bootstrapStateFile = String(
|
||||
environment.SAAS_RUNTIME_BOOTSTRAP_STATE_FILE || ''
|
||||
).trim();
|
||||
const configuredIdentityReady = [
|
||||
'RPC_INSTANCE_ID',
|
||||
'SAAS_RUNTIME_NODE_ID',
|
||||
'SAAS_SERVICE_TOKEN_FILE',
|
||||
].every(field => String(environment[field] || '').trim());
|
||||
if (
|
||||
String(environment.SAAS_RUNTIME_BOOTSTRAP_TOKEN || '').trim() &&
|
||||
['prod', 'production'].includes(runtimeEnvironment)
|
||||
) {
|
||||
throw new Error(
|
||||
'Production SaaS runtime bootstrap tokens must be mounted as a file'
|
||||
);
|
||||
}
|
||||
if (
|
||||
!bootstrapTicketFile &&
|
||||
!bootstrapStateFile &&
|
||||
!(localOrTest && configuredIdentityReady)
|
||||
) {
|
||||
throw new Error(
|
||||
'Strict SaaS runtime identity requires an authenticated orchestrator bootstrap ticket/state; configured RPC_INSTANCE_ID and SAAS_RUNTIME_NODE_ID are local/test migration compatibility only'
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
environment.RPC_MODULE_CODE &&
|
||||
!/^[a-z][a-z0-9_]{0,62}$/.test(environment.RPC_MODULE_CODE)
|
||||
) {
|
||||
throw new Error('RPC_MODULE_CODE is invalid');
|
||||
}
|
||||
if (
|
||||
environment.RPC_INSTANCE_ID &&
|
||||
!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
|
||||
environment.RPC_INSTANCE_ID
|
||||
)
|
||||
) {
|
||||
throw new Error('RPC_INSTANCE_ID must be a UUID');
|
||||
}
|
||||
|
||||
const releaseId = Number(environment.RPC_RELEASE_ID);
|
||||
const minSchema = Number(environment.RPC_MIN_SCHEMA_VERSION);
|
||||
const maxSchema = Number(environment.RPC_MAX_SCHEMA_VERSION);
|
||||
const runtimeNodeId = environment.SAAS_RUNTIME_NODE_ID
|
||||
? Number(environment.SAAS_RUNTIME_NODE_ID)
|
||||
: undefined;
|
||||
if (
|
||||
!Number.isSafeInteger(releaseId) ||
|
||||
releaseId < 1 ||
|
||||
!Number.isSafeInteger(minSchema) ||
|
||||
minSchema < 1 ||
|
||||
minSchema !== maxSchema ||
|
||||
(runtimeNodeId !== undefined &&
|
||||
(!Number.isSafeInteger(runtimeNodeId) ||
|
||||
runtimeNodeId < 0 ||
|
||||
runtimeNodeId > 65_535))
|
||||
) {
|
||||
throw new Error('Exact SaaS Release numeric identity is invalid');
|
||||
}
|
||||
|
||||
for (const field of [
|
||||
'RPC_SCHEMA_CHECKSUM',
|
||||
'RPC_ACTION_MANIFEST_CHECKSUM',
|
||||
'RPC_RUNTIME_CONTRACT_CHECKSUM',
|
||||
'RPC_IMPLEMENTATION_MANIFEST_CHECKSUM',
|
||||
]) {
|
||||
if (!/^[a-f0-9]{64}$/.test(environment[field])) {
|
||||
throw new Error(`${field} must be a SHA-256 checksum`);
|
||||
}
|
||||
}
|
||||
if (!/^sha256:[a-f0-9]{64}$/.test(environment.RPC_ARTIFACT_DIGEST)) {
|
||||
throw new Error('RPC_ARTIFACT_DIGEST must be a sha256 digest');
|
||||
}
|
||||
if (!/^[0-9A-Za-z._-]{6,128}$/.test(environment.BUILD_SHA)) {
|
||||
throw new Error('BUILD_SHA is invalid');
|
||||
}
|
||||
if (
|
||||
!/^\d+\.\d+\.\d+(?:-rc\.\d+)?(?:\+[0-9A-Za-z.-]+)?$/.test(
|
||||
environment.RPC_SERVICE_VERSION
|
||||
)
|
||||
) {
|
||||
throw new Error('RPC_SERVICE_VERSION is invalid');
|
||||
}
|
||||
if (
|
||||
!/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,95}$/.test(
|
||||
environment.RPC_RELEASE_VERSION
|
||||
)
|
||||
) {
|
||||
throw new Error('RPC_RELEASE_VERSION is invalid');
|
||||
}
|
||||
|
||||
let controlPlane;
|
||||
try {
|
||||
controlPlane = new URL(environment.SAAS_CONTROL_PLANE_URL);
|
||||
} catch {
|
||||
throw new Error('SAAS_CONTROL_PLANE_URL is invalid');
|
||||
}
|
||||
if (!['http:', 'https:'].includes(controlPlane.protocol)) {
|
||||
throw new Error('SAAS_CONTROL_PLANE_URL is invalid');
|
||||
}
|
||||
if (
|
||||
['prod', 'production'].includes(runtimeEnvironment) &&
|
||||
controlPlane.protocol !== 'https:'
|
||||
) {
|
||||
throw new Error('Production SAAS_CONTROL_PLANE_URL must use HTTPS');
|
||||
}
|
||||
|
||||
if (bootstrapTicketFile) {
|
||||
requireRuntimeFile(
|
||||
environment,
|
||||
'SAAS_RUNTIME_BOOTSTRAP_TOKEN_FILE',
|
||||
32,
|
||||
16_384
|
||||
);
|
||||
}
|
||||
if (bootstrapStateFile) {
|
||||
requireRuntimeFile(
|
||||
environment,
|
||||
'SAAS_RUNTIME_BOOTSTRAP_STATE_FILE',
|
||||
2,
|
||||
1024 * 1024
|
||||
);
|
||||
}
|
||||
if (environment.SAAS_SERVICE_TOKEN_FILE) {
|
||||
requireRuntimeFile(
|
||||
environment,
|
||||
'SAAS_SERVICE_TOKEN_FILE',
|
||||
32,
|
||||
16_384
|
||||
);
|
||||
}
|
||||
requireRuntimeFile(
|
||||
environment,
|
||||
'SAAS_TENANT_CREDENTIALS_FILE',
|
||||
2,
|
||||
1024 * 1024
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = { requireExactReleaseEnvironment };
|
||||
Reference in New Issue
Block a user