文件
hyb-oa/.trellis/tasks/archive/2026-08/07-28-all-account-login-readiness/research/auth-readiness-census.cjs
T
wangsli 45a1fa8d03
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
归档(07-28-all-account-login-readiness): 完成全员登录可用性任务
2026-08-23 19:25:01 +08:00

130 行
6.1 KiB
JavaScript

"use strict";
const path = require("node:path");
const OBSERVATION_WINDOW_DAYS = 7;
const SAFE_RESULT_KEYS = Object.freeze([
"abnormalActiveSessions",
"activeEmployeesWithSession",
"activeSessionsTotal",
"activeTotal",
"bindingConflictGroups",
"bindingCovered",
"bindingMissing",
"bindingMutationAudits7d",
"directoryMutationAudits7d",
"emailLoginLocked",
"inactiveBindingRows",
"mustChangePassword",
"passwordLoginCoveredAllTime",
"passwordLoginCovered7d",
"passwordLocked",
"passwordResetLocked",
"roleMutationAudits7d",
"wecomLoginCoveredAllTime",
"wecomLoginCovered7d",
"wecomLoginEvents7d",
]);
const READINESS_SQL = String.raw`
WITH active AS (
SELECT id
FROM employees
WHERE status = 'active' AND archived_at IS NULL
), binding_conflicts AS (
SELECT count(*)::int AS groups
FROM (
SELECT employee_id::text
FROM wecom_identity_bindings
GROUP BY employee_id
HAVING count(*) > 1
UNION ALL
SELECT external_user_id
FROM wecom_identity_bindings
GROUP BY external_user_id
HAVING count(*) > 1
) conflicts
), metrics AS (
SELECT
(SELECT count(*) FROM active)::int AS "activeTotal",
(SELECT count(*) FROM employees e JOIN active a ON a.id = e.id WHERE e.must_change_password)::int AS "mustChangePassword",
(SELECT count(*) FROM employees e JOIN active a ON a.id = e.id WHERE e.login_locked_until > now())::int AS "passwordLocked",
(SELECT count(*) FROM employees e JOIN active a ON a.id = e.id WHERE e.email_login_code_locked_until > now())::int AS "emailLoginLocked",
(SELECT count(*) FROM employees e JOIN active a ON a.id = e.id WHERE e.password_reset_locked_until > now())::int AS "passwordResetLocked",
(SELECT count(DISTINCT b.employee_id) FROM wecom_identity_bindings b JOIN active a ON a.id = b.employee_id)::int AS "bindingCovered",
(SELECT count(*) FROM active a LEFT JOIN wecom_identity_bindings b ON b.employee_id = a.id WHERE b.id IS NULL)::int AS "bindingMissing",
(SELECT groups FROM binding_conflicts)::int AS "bindingConflictGroups",
(SELECT count(*) FROM wecom_identity_bindings b JOIN employees e ON e.id = b.employee_id WHERE e.status <> 'active' OR e.archived_at IS NOT NULL)::int AS "inactiveBindingRows",
(SELECT count(DISTINCT l.actor_id) FROM audit_logs l JOIN active a ON a.id = l.actor_id WHERE l.action = 'AUTH_WECOM_LOGIN_SUCCESS')::int AS "wecomLoginCoveredAllTime",
(SELECT count(DISTINCT l.actor_id) FROM audit_logs l JOIN active a ON a.id = l.actor_id WHERE l.action = 'AUTH_WECOM_LOGIN_SUCCESS' AND l.created_at >= now() - interval '7 days')::int AS "wecomLoginCovered7d",
(SELECT count(*) FROM audit_logs l JOIN active a ON a.id = l.actor_id WHERE l.action = 'AUTH_WECOM_LOGIN_SUCCESS' AND l.created_at >= now() - interval '7 days')::int AS "wecomLoginEvents7d",
(SELECT count(DISTINCT l.actor_id) FROM audit_logs l JOIN active a ON a.id = l.actor_id WHERE l.action = 'AUTH_LOGIN_SUCCESS')::int AS "passwordLoginCoveredAllTime",
(SELECT count(DISTINCT l.actor_id) FROM audit_logs l JOIN active a ON a.id = l.actor_id WHERE l.action = 'AUTH_LOGIN_SUCCESS' AND l.created_at >= now() - interval '7 days')::int AS "passwordLoginCovered7d",
(SELECT count(*) FROM audit_logs WHERE action = 'SYSTEM_USER_ROLES_SET' AND created_at >= now() - interval '7 days')::int AS "roleMutationAudits7d",
(SELECT count(*) FROM audit_logs WHERE action LIKE 'WECOM_DIRECTORY_%' AND created_at >= now() - interval '7 days')::int AS "directoryMutationAudits7d",
(SELECT count(*) FROM audit_logs WHERE action = 'AUTH_WECOM_BIND' AND created_at >= now() - interval '7 days')::int AS "bindingMutationAudits7d",
(SELECT count(*) FROM auth_sessions s WHERE s.revoked_at IS NULL AND s.expires_at > now())::int AS "activeSessionsTotal",
(SELECT count(DISTINCT s.employee_id) FROM auth_sessions s JOIN active a ON a.id = s.employee_id WHERE s.revoked_at IS NULL AND s.expires_at > now())::int AS "activeEmployeesWithSession",
(SELECT count(*) FROM auth_sessions s JOIN employees e ON e.id = s.employee_id WHERE s.revoked_at IS NULL AND s.expires_at > now() AND (e.status <> 'active' OR e.archived_at IS NOT NULL))::int AS "abnormalActiveSessions"
)
SELECT * FROM metrics
`;
function assertSafeMetrics(metrics) {
const keys = Object.keys(metrics).sort();
if (JSON.stringify(keys) !== JSON.stringify([...SAFE_RESULT_KEYS].sort())) {
throw new Error("result_field_contract_invalid");
}
if (Object.values(metrics).some((value) => !Number.isInteger(value) || value < 0)) {
throw new Error("result_value_contract_invalid");
}
}
async function run() {
const appRoot = path.resolve(process.env.AUTH_CENSUS_APP_ROOT || process.cwd());
const { Client } = require(path.join(appRoot, "node_modules/pg"));
const { getConfig } = require(path.join(appRoot, "src/config.js"));
const config = getConfig();
const client = new Client({ connectionString: process.env.DATABASE_URL });
let inTransaction = false;
try {
await client.connect();
await client.query("BEGIN TRANSACTION READ ONLY");
inTransaction = true;
await client.query("SET LOCAL statement_timeout = '30s'");
await client.query("SET LOCAL lock_timeout = '2s'");
const readOnly = await client.query("SELECT current_setting('transaction_read_only') AS value");
if (readOnly.rows[0]?.value !== "on") throw new Error("transaction_not_read_only");
const result = await client.query(READINESS_SQL);
const metrics = result.rows[0];
assertSafeMetrics(metrics);
await client.query("COMMIT");
inTransaction = false;
process.stdout.write(`${JSON.stringify({
status: "PASS",
transactionReadOnly: true,
sourceBuildSha: config.buildSha,
observationWindowDays: OBSERVATION_WINDOW_DAYS,
metrics,
}, null, 2)}\n`);
} catch {
if (inTransaction) {
try { await client.query("ROLLBACK"); } catch { /* fail closed */ }
}
process.stderr.write("[auth-readiness-census][FAILED] code=QUERY_FAILED\n");
process.exitCode = 1;
} finally {
await client.end().catch(() => {});
}
}
module.exports = { OBSERVATION_WINDOW_DAYS, READINESS_SQL, SAFE_RESULT_KEYS, assertSafeMetrics };
if (require.main === module || process.argv[1] === "-") {
run();
}