feat(ql3): add strong cluster run management

This commit is contained in:
whyour
2026-08-12 07:28:43 +08:00
parent e38b143dbb
commit c0ab62e64a
58 changed files with 3087 additions and 105 deletions
@@ -65,6 +65,10 @@ const EXPECTED_ROLES = Object.freeze({
connectionLimit: 32,
secret: 'ql3-postgres-runtime-auth',
}),
ql3_run_manager: Object.freeze({
connectionLimit: 4,
secret: 'ql3-postgres-run-manager-auth',
}),
ql3_worker_credential_executor: Object.freeze({
connectionLimit: 4,
secret: 'ql3-postgres-worker-credential-executor-auth',
@@ -258,7 +262,7 @@ function assertRolesAndDatabase(readFile, root, findings) {
findings.push(
finding(
'QL3_CNPG_DATABASE_ROLE',
'DatabaseRole resources must match the thirteen fixed least-privilege identities',
'DatabaseRole resources must match the fourteen fixed least-privilege identities',
),
);
break;
@@ -272,7 +276,7 @@ function assertRolesAndDatabase(readFile, root, findings) {
findings.push(
finding(
'QL3_CNPG_DATABASE_ROLE_SET',
'exactly the thirteen reviewed migration, runtime, AI maintenance, AI credential management/testing, admin, automation, Approval, package and Worker roles are required',
'exactly the fourteen reviewed migration, runtime, AI maintenance, AI credential management/testing, admin, automation, Approval, Run, package and Worker roles are required',
),
);
}
@@ -332,6 +336,7 @@ function assertSecretBoundary(readFile, root, findings) {
['ql3-postgres-admin-auth', 'ql3_admin'],
['ql3-postgres-automation-manager-auth', 'ql3_automation_manager'],
['ql3-postgres-approval-manager-auth', 'ql3_approval_manager'],
['ql3-postgres-run-manager-auth', 'ql3_run_manager'],
['ql3-postgres-worker-ingress-auth', 'ql3_worker_ingress'],
['ql3-postgres-package-manager-auth', 'ql3_package_manager'],
['ql3-postgres-package-executor-auth', 'ql3_package_executor'],
@@ -417,7 +422,7 @@ function assertSecretBoundary(readFile, root, findings) {
findings.push(
finding(
'QL3_CNPG_SECRET_EXAMPLE_SET',
'the example must describe all thirteen database credentials and the reviewed workload Secrets',
'the example must describe all fourteen database credentials and the reviewed workload Secrets',
),
);
}
+5
View File
@@ -2366,6 +2366,11 @@ function auditSourceImports(root, packagePath, findings) {
'src/approval-management/approvalManagementProcess.ts',
].includes(path.relative(packageDirectory, filePath)) &&
specifier === '@qinglong/cluster-postgres/approval-manager') ||
([
'src/run-management/runManagement.ts',
'src/run-management/runManagementProcess.ts',
].includes(path.relative(packageDirectory, filePath)) &&
specifier === '@qinglong/cluster-postgres/run-manager') ||
([
'src/prompt-output/retention/promptOutputGcCli.ts',
'src/prompt-output/retention/promptOutputGcProcess.ts',
+51 -12
View File
@@ -201,6 +201,9 @@ const {
const {
assertPostgresApprovalManagerSchemaReady,
} = require('../packages/ql3-cluster-postgres/dist/approval-management/index.js');
const {
assertPostgresRunManagerSchemaReady,
} = require('../packages/ql3-cluster-postgres/dist/entrypoints/runManager.js');
const {
assertPostgresPackageExecutorSchemaReady,
PostgresPluginPackageMaterializedRevisionRepository,
@@ -341,6 +344,8 @@ const AUTOMATION_MANAGER_USER = 'ql3_automation_manager';
const AUTOMATION_MANAGER_PASSWORD = 'ql3_automation_manager_test';
const APPROVAL_MANAGER_USER = 'ql3_approval_manager';
const APPROVAL_MANAGER_PASSWORD = 'ql3_approval_manager_test';
const RUN_MANAGER_USER = 'ql3_run_manager';
const RUN_MANAGER_PASSWORD = 'ql3_run_manager_test';
const PACKAGE_MANAGER_USER = 'ql3_package_manager';
const PACKAGE_MANAGER_PASSWORD = 'ql3_package_manager_test';
const PACKAGE_EXECUTOR_USER = 'ql3_package_executor';
@@ -3721,6 +3726,9 @@ async function provisionCredentialRoles(database) {
await database.pool.query(
`CREATE ROLE ${APPROVAL_MANAGER_USER} LOGIN PASSWORD '${APPROVAL_MANAGER_PASSWORD}'`,
);
await database.pool.query(
`CREATE ROLE ${RUN_MANAGER_USER} LOGIN PASSWORD '${RUN_MANAGER_PASSWORD}'`,
);
await database.pool.query(
`CREATE ROLE ${PACKAGE_MANAGER_USER} LOGIN PASSWORD '${PACKAGE_MANAGER_PASSWORD}'`,
);
@@ -5010,54 +5018,70 @@ async function runIdentityKeysetLedgerMatrix(options) {
authority === 'plugin-package-management' ||
authority === 'worker-credential-management' ||
authority === 'automation-management' ||
authority === 'approval-management',
authority === 'approval-management' ||
authority === 'run-management',
);
const workerAuthority = authority === 'worker-credential-management';
const automationAuthority = authority === 'automation-management';
const approvalAuthority = authority === 'approval-management';
const user = approvalAuthority
const runAuthority = authority === 'run-management';
const user = runAuthority
? RUN_MANAGER_USER
: approvalAuthority
? APPROVAL_MANAGER_USER
: automationAuthority
? AUTOMATION_MANAGER_USER
: workerAuthority
? WORKER_CREDENTIAL_MANAGER_USER
: PACKAGE_MANAGER_USER;
const password = approvalAuthority
const password = runAuthority
? RUN_MANAGER_PASSWORD
: approvalAuthority
? APPROVAL_MANAGER_PASSWORD
: automationAuthority
? AUTOMATION_MANAGER_PASSWORD
: workerAuthority
? WORKER_CREDENTIAL_MANAGER_PASSWORD
: PACKAGE_MANAGER_PASSWORD;
const role = approvalAuthority
const role = runAuthority
? 'run-manager'
: approvalAuthority
? 'approval-manager'
: automationAuthority
? 'automation-manager'
: workerAuthority
? 'worker-credential-manager'
: 'package-manager';
const applicationPrefix = approvalAuthority
const applicationPrefix = runAuthority
? 'ql3-ha-run-keyset-ledger'
: approvalAuthority
? 'ql3-ha-approval-keyset-ledger'
: automationAuthority
? 'ql3-ha-automation-keyset-ledger'
: workerAuthority
? 'ql3-ha-worker-keyset-ledger'
: 'ql3-ha-keyset-ledger';
const keyPrefix = approvalAuthority
const keyPrefix = runAuthority
? 'ha-run-identity-key'
: approvalAuthority
? 'ha-approval-identity-key'
: automationAuthority
? 'ha-automation-identity-key'
: workerAuthority
? 'ha-worker-identity-key'
: 'ha-identity-key';
const issuer = approvalAuthority
const issuer = runAuthority
? 'https://run-identity.ha.example.test/'
: approvalAuthority
? 'https://approval-identity.ha.example.test/'
: automationAuthority
? 'https://automation-identity.ha.example.test/'
: workerAuthority
? 'https://worker-identity.ha.example.test/'
: 'https://identity.ha.example.test/';
const audience = approvalAuthority
const audience = runAuthority
? 'qinglong3-run-management'
: approvalAuthority
? 'qinglong3-approval-management'
: automationAuthority
? 'qinglong3-automation-management'
@@ -9446,13 +9470,13 @@ async function runManualRunRetryHaEvidence(options) {
})
).definition;
const firstRuntime = await databaseOpener(
'runtime',
databaseUrl(RUNTIME_USER, RUNTIME_PASSWORD, primaryPort),
'run-manager',
databaseUrl(RUN_MANAGER_USER, RUN_MANAGER_PASSWORD, primaryPort),
'ql3-ha-manual-run-retry-a',
)();
const secondRuntime = await databaseOpener(
'runtime',
databaseUrl(RUNTIME_USER, RUNTIME_PASSWORD, primaryPort),
'run-manager',
databaseUrl(RUN_MANAGER_USER, RUN_MANAGER_PASSWORD, primaryPort),
'ql3-ha-manual-run-retry-b',
)();
try {
@@ -9707,6 +9731,7 @@ async function main(argv = process.argv.slice(2)) {
let workerCredentialIdentityKeysetLedger;
let automationIdentityKeysetLedger;
let approvalIdentityKeysetLedger;
let runManagementIdentityKeysetLedger;
let automationManagementInspection;
let pluginPackageLifecycle;
let pluginPackageQuarantine;
@@ -9933,6 +9958,11 @@ async function main(argv = process.argv.slice(2)) {
),
'ql3-ha-approval-manager-readiness',
)();
const runManagerReadinessDatabase = await databaseOpener(
'run-manager',
databaseUrl(RUN_MANAGER_USER, RUN_MANAGER_PASSWORD, primaryPort),
'ql3-ha-run-manager-readiness',
)();
const packageManagerReadinessDatabase = await databaseOpener(
'package-manager',
databaseUrl(PACKAGE_MANAGER_USER, PACKAGE_MANAGER_PASSWORD, primaryPort),
@@ -9974,6 +10004,9 @@ async function main(argv = process.argv.slice(2)) {
await assertPostgresApprovalManagerSchemaReady(
approvalManagerReadinessDatabase.pool,
);
await assertPostgresRunManagerSchemaReady(
runManagerReadinessDatabase.pool,
);
await assertPostgresPackageManagerSchemaReady(
packageManagerReadinessDatabase.pool,
);
@@ -9992,6 +10025,7 @@ async function main(argv = process.argv.slice(2)) {
adminReadinessDatabase.close(),
automationManagerReadinessDatabase.close(),
approvalManagerReadinessDatabase.close(),
runManagerReadinessDatabase.close(),
packageManagerReadinessDatabase.close(),
packageExecutorReadinessDatabase.close(),
workerManagerReadinessDatabase.close(),
@@ -10031,6 +10065,10 @@ async function main(argv = process.argv.slice(2)) {
primaryPort,
authority: 'approval-management',
});
runManagementIdentityKeysetLedger = await runIdentityKeysetLedgerMatrix({
primaryPort,
authority: 'run-management',
});
timeline.push({
state: 'durable_identity_keyset_ledger_verified',
atMs: Number((performance.now() - startedAt).toFixed(3)),
@@ -11968,6 +12006,7 @@ async function main(argv = process.argv.slice(2)) {
workerCredentialIdentityKeysetLedger,
automationIdentityKeysetLedger,
approvalIdentityKeysetLedger,
runManagementIdentityKeysetLedger,
automationManagementInspection,
pluginPackageLifecycle: pluginPackageLifecycle.report,
pluginPackageQuarantine: pluginPackageQuarantine.report,