431 行
20 KiB
JavaScript
431 行
20 KiB
JavaScript
"use strict";
|
|
|
|
const path = require("node:path");
|
|
|
|
const MODULE_KEYS = Object.freeze([
|
|
"portal_notifications",
|
|
"workflow_approvals",
|
|
"reimbursements_invoices",
|
|
"payments_ap",
|
|
"procurement",
|
|
"contracts",
|
|
"projects",
|
|
"assets_inventory",
|
|
"leave_wecom_history",
|
|
"attendance_presence",
|
|
"weekly_reports",
|
|
"todos",
|
|
"announcements",
|
|
"budgets",
|
|
"travel",
|
|
"people_lifecycle",
|
|
"payroll",
|
|
"performance",
|
|
"system_configuration",
|
|
"integrations",
|
|
]);
|
|
|
|
const SAFE_RESULT_KEYS = Object.freeze([
|
|
"moduleKey",
|
|
"totalRows",
|
|
"created30d",
|
|
"created90d",
|
|
"activity30d",
|
|
"activity90d",
|
|
"latestActivityAt",
|
|
"humanActors30d",
|
|
"humanActors90d",
|
|
"humanEvents30d",
|
|
"humanEvents90d",
|
|
"smokeEvents30d",
|
|
"smokeEvents90d",
|
|
"systemEvents30d",
|
|
"systemEvents90d",
|
|
"unknownEvents30d",
|
|
"unknownEvents90d",
|
|
"auditEvents30d",
|
|
"auditEvents90d",
|
|
"auditHumanActors30d",
|
|
"auditHumanActors90d",
|
|
"auditHumanEvents30d",
|
|
"auditHumanEvents90d",
|
|
"auditSmokeEvents30d",
|
|
"auditSmokeEvents90d",
|
|
"auditUnknownEvents30d",
|
|
"auditUnknownEvents90d",
|
|
"navigationMode",
|
|
"effectiveFlagState",
|
|
"queryStatus",
|
|
]);
|
|
|
|
const USAGE_SQL = String.raw`
|
|
WITH module_keys(module_key) AS (
|
|
VALUES
|
|
('portal_notifications'), ('workflow_approvals'),
|
|
('reimbursements_invoices'), ('payments_ap'), ('procurement'),
|
|
('contracts'), ('projects'), ('assets_inventory'),
|
|
('leave_wecom_history'), ('attendance_presence'), ('weekly_reports'),
|
|
('todos'), ('announcements'), ('budgets'), ('travel'),
|
|
('people_lifecycle'), ('payroll'), ('performance'),
|
|
('system_configuration'), ('integrations')
|
|
), record_events(module_key, record_id, created_at, activity_at, actor_id, forced_kind) AS (
|
|
SELECT 'portal_notifications', id::text, created_at, created_at, recipient_employee_id, 'system' FROM notifications
|
|
UNION ALL SELECT 'workflow_approvals', id::text, created_at, updated_at, submitter_id, NULL FROM workflow_instances
|
|
UNION ALL SELECT 'reimbursements_invoices', id::text, created_at, updated_at, owner_id, NULL FROM reimbursement_forms
|
|
UNION ALL SELECT 'reimbursements_invoices', id::text, created_at, updated_at, uploaded_by_employee_id, NULL FROM invoice_pool
|
|
UNION ALL SELECT 'reimbursements_invoices', id::text, created_at, created_at, NULL::uuid, 'system' FROM ocr_results
|
|
UNION ALL SELECT 'payments_ap', id::text, created_at, updated_at, created_by, NULL FROM payment_batches
|
|
UNION ALL SELECT 'payments_ap', id::text, created_at, created_at, uploaded_by, NULL FROM payment_batch_receipt_attachments
|
|
UNION ALL SELECT 'procurement', id::text, created_at, updated_at, applicant_id, NULL FROM purchase_requests
|
|
UNION ALL SELECT 'contracts', id::text, created_at, updated_at, owner_employee_id, NULL FROM contract_registry
|
|
UNION ALL SELECT 'projects', id::text, created_at, updated_at, owner_employee_id, NULL FROM projects
|
|
UNION ALL SELECT 'assets_inventory', id::text, created_at, updated_at, created_by, NULL FROM asset_cards
|
|
UNION ALL SELECT 'assets_inventory', id::text, created_at, updated_at, created_by, NULL FROM inventory_checks
|
|
UNION ALL SELECT 'leave_wecom_history', id::text, created_at, updated_at, owner_id, NULL FROM leave_requests
|
|
UNION ALL SELECT 'leave_wecom_history', id::text, created_at, updated_at, applicant_employee_id, 'system' FROM wecom_approval_archives
|
|
UNION ALL SELECT 'attendance_presence', id::text, created_at, updated_at, owner_id, NULL FROM attendance_corrections
|
|
UNION ALL SELECT 'attendance_presence', id::text, created_at, updated_at, employee_id, 'system' FROM wecom_checkin_records
|
|
UNION ALL SELECT 'attendance_presence', id::text, created_at, updated_at, updated_by, NULL FROM employee_presence
|
|
UNION ALL SELECT 'weekly_reports', id::text, created_at, updated_at, employee_id, NULL FROM weekly_reports
|
|
UNION ALL SELECT 'todos', id::text, created_at, updated_at, created_by, NULL FROM todo_items
|
|
UNION ALL SELECT 'announcements', id::text, created_at, updated_at, created_by, NULL FROM portal_announcements
|
|
UNION ALL SELECT 'announcements', id::text, created_at, COALESCE(acknowledged_at, created_at), actor_id, NULL FROM portal_announcement_acknowledgements
|
|
UNION ALL SELECT 'budgets', id::text, created_at, updated_at, created_by, NULL FROM budget_pools
|
|
UNION ALL SELECT 'travel', id::text, created_at, updated_at, applicant_employee_id, NULL FROM travel_requests
|
|
UNION ALL SELECT 'travel', id::text, created_at, updated_at, created_by, NULL FROM travel_orders
|
|
UNION ALL SELECT 'people_lifecycle', id::text, created_at, created_at, created_by, NULL FROM employee_lifecycle_events
|
|
UNION ALL SELECT 'people_lifecycle', id::text, created_at, updated_at, created_by, NULL FROM employee_contracts
|
|
UNION ALL SELECT 'people_lifecycle', id::text, created_at, updated_at, created_by, NULL FROM employee_trainings
|
|
UNION ALL SELECT 'payroll', id::text, created_at, updated_at, created_by, NULL FROM payslips
|
|
UNION ALL SELECT 'performance', id::text, created_at, updated_at, reviewer_employee_id, NULL FROM performance_reviews
|
|
UNION ALL SELECT 'system_configuration', id::text, created_at, updated_at, updated_by, NULL FROM feature_flags
|
|
UNION ALL SELECT 'system_configuration', id::text, created_at, updated_at, updated_by, NULL FROM cutover_scopes
|
|
UNION ALL SELECT 'integrations', id::text, created_at, updated_at, created_by, 'system' FROM integration_outbox
|
|
), classified_records AS (
|
|
SELECT
|
|
r.*,
|
|
CASE
|
|
WHEN r.forced_kind = 'system' THEN 'system'
|
|
WHEN r.actor_id IS NULL OR e.id IS NULL THEN 'unknown'
|
|
WHEN lower(split_part(e.email, '@', 1)) ~ '^(smoke[-_.]|oa[-_.]?smoke[-_.]?)'
|
|
OR e.employee_no ~* '^(SMOKE|OSMOKE|WFULL|PRELAUNCH|LAUNCHAUTO|HRWDTEST)'
|
|
OR e.name ~ '(测试|试运行)'
|
|
THEN 'smoke'
|
|
ELSE 'human'
|
|
END AS actor_kind
|
|
FROM record_events r
|
|
LEFT JOIN employees e ON e.id = r.actor_id
|
|
), audit_mapped AS (
|
|
SELECT
|
|
CASE
|
|
WHEN action ~ '^(APPROVAL_|DELEGATION_|WORKFLOW_)' THEN 'workflow_approvals'
|
|
WHEN action ~ '^(REIMBURSEMENT_|INVOICE_)' OR action = 'EXPORT_REIMBURSEMENTS' THEN 'reimbursements_invoices'
|
|
WHEN action ~ '^PAYMENT_' OR action = 'EXPORT_AP_OPERATIONS' THEN 'payments_ap'
|
|
WHEN action ~ '^PURCHASE_' THEN 'procurement'
|
|
WHEN action ~ '^CONTRACT_' OR action = 'EXPORT_CONTRACTS_REGISTRY' THEN 'contracts'
|
|
WHEN action ~ '^PROJECT_' THEN 'projects'
|
|
WHEN action ~ '^(ASSET_|INVENTORY_)' THEN 'assets_inventory'
|
|
WHEN action ~ '^(ATTENDANCE_|PRESENCE_)' THEN 'attendance_presence'
|
|
WHEN action ~ '^PORTAL_ANNOUNCEMENT_' THEN 'announcements'
|
|
WHEN action ~ '^BUDGET_' THEN 'budgets'
|
|
WHEN action ~ '^TRAVEL_' THEN 'travel'
|
|
WHEN action ~ '^(EMPLOYEE_|SYSTEM_USER|DEPARTMENT_)' THEN 'people_lifecycle'
|
|
WHEN action ~ '^(CREATE_SALARY_|UPDATE_SALARY_|UPSERT_EMPLOYEE_SALARY_|GENERATE_PAYSLIPS|ISSUE_PAYSLIPS|UPDATE_PAYSLIP|EXPORT_PAYSLIPS)' THEN 'payroll'
|
|
WHEN action ~ '^PERFORMANCE_' THEN 'performance'
|
|
WHEN action ~ '^(FEATURE_FLAG_|WORKSPACE_)' THEN 'system_configuration'
|
|
WHEN action ~ '^ERP_' THEN 'integrations'
|
|
ELSE NULL
|
|
END AS module_key,
|
|
a.actor_id,
|
|
a.created_at,
|
|
CASE
|
|
WHEN e.id IS NULL THEN 'unknown'
|
|
WHEN lower(split_part(e.email, '@', 1)) ~ '^(smoke[-_.]|oa[-_.]?smoke[-_.]?)'
|
|
OR e.employee_no ~* '^(SMOKE|OSMOKE|WFULL|PRELAUNCH|LAUNCHAUTO|HRWDTEST)'
|
|
OR e.name ~ '(测试|试运行)'
|
|
THEN 'smoke'
|
|
ELSE 'human'
|
|
END AS actor_kind
|
|
FROM audit_logs a
|
|
LEFT JOIN employees e ON e.id = a.actor_id
|
|
), record_metrics AS (
|
|
SELECT
|
|
module_key,
|
|
count(*)::int AS total_rows,
|
|
count(*) FILTER (WHERE created_at >= now() - interval '30 days')::int AS created_30d,
|
|
count(*) FILTER (WHERE created_at >= now() - interval '90 days')::int AS created_90d,
|
|
count(*) FILTER (WHERE activity_at >= now() - interval '30 days')::int AS activity_30d,
|
|
count(*) FILTER (WHERE activity_at >= now() - interval '90 days')::int AS activity_90d,
|
|
max(activity_at) AS latest_activity_at,
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND activity_at >= now() - interval '30 days')::int AS human_actors_30d,
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND activity_at >= now() - interval '90 days')::int AS human_actors_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND activity_at >= now() - interval '30 days')::int AS human_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND activity_at >= now() - interval '90 days')::int AS human_events_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND activity_at >= now() - interval '30 days')::int AS smoke_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND activity_at >= now() - interval '90 days')::int AS smoke_events_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'system' AND activity_at >= now() - interval '30 days')::int AS system_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'system' AND activity_at >= now() - interval '90 days')::int AS system_events_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND activity_at >= now() - interval '30 days')::int AS unknown_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND activity_at >= now() - interval '90 days')::int AS unknown_events_90d
|
|
FROM classified_records
|
|
GROUP BY module_key
|
|
), audit_metrics AS (
|
|
SELECT
|
|
module_key,
|
|
count(*) FILTER (WHERE created_at >= now() - interval '30 days')::int AS audit_events_30d,
|
|
count(*) FILTER (WHERE created_at >= now() - interval '90 days')::int AS audit_events_90d,
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '30 days')::int AS audit_human_actors_30d,
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '90 days')::int AS audit_human_actors_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '30 days')::int AS audit_human_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '90 days')::int AS audit_human_events_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND created_at >= now() - interval '30 days')::int AS audit_smoke_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND created_at >= now() - interval '90 days')::int AS audit_smoke_events_90d,
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND created_at >= now() - interval '30 days')::int AS audit_unknown_events_30d,
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND created_at >= now() - interval '90 days')::int AS audit_unknown_events_90d
|
|
FROM audit_mapped
|
|
WHERE module_key IS NOT NULL
|
|
GROUP BY module_key
|
|
)
|
|
SELECT
|
|
k.module_key AS "moduleKey",
|
|
COALESCE(r.total_rows, 0) AS "totalRows",
|
|
COALESCE(r.created_30d, 0) AS "created30d",
|
|
COALESCE(r.created_90d, 0) AS "created90d",
|
|
COALESCE(r.activity_30d, 0) AS "activity30d",
|
|
COALESCE(r.activity_90d, 0) AS "activity90d",
|
|
r.latest_activity_at AS "latestActivityAt",
|
|
COALESCE(r.human_actors_30d, 0) AS "humanActors30d",
|
|
COALESCE(r.human_actors_90d, 0) AS "humanActors90d",
|
|
COALESCE(r.human_events_30d, 0) AS "humanEvents30d",
|
|
COALESCE(r.human_events_90d, 0) AS "humanEvents90d",
|
|
COALESCE(r.smoke_events_30d, 0) AS "smokeEvents30d",
|
|
COALESCE(r.smoke_events_90d, 0) AS "smokeEvents90d",
|
|
COALESCE(r.system_events_30d, 0) AS "systemEvents30d",
|
|
COALESCE(r.system_events_90d, 0) AS "systemEvents90d",
|
|
COALESCE(r.unknown_events_30d, 0) AS "unknownEvents30d",
|
|
COALESCE(r.unknown_events_90d, 0) AS "unknownEvents90d",
|
|
COALESCE(a.audit_events_30d, 0) AS "auditEvents30d",
|
|
COALESCE(a.audit_events_90d, 0) AS "auditEvents90d",
|
|
COALESCE(a.audit_human_actors_30d, 0) AS "auditHumanActors30d",
|
|
COALESCE(a.audit_human_actors_90d, 0) AS "auditHumanActors90d",
|
|
COALESCE(a.audit_human_events_30d, 0) AS "auditHumanEvents30d",
|
|
COALESCE(a.audit_human_events_90d, 0) AS "auditHumanEvents90d",
|
|
COALESCE(a.audit_smoke_events_30d, 0) AS "auditSmokeEvents30d",
|
|
COALESCE(a.audit_smoke_events_90d, 0) AS "auditSmokeEvents90d",
|
|
COALESCE(a.audit_unknown_events_30d, 0) AS "auditUnknownEvents30d",
|
|
COALESCE(a.audit_unknown_events_90d, 0) AS "auditUnknownEvents90d"
|
|
FROM module_keys k
|
|
LEFT JOIN record_metrics r ON r.module_key = k.module_key
|
|
LEFT JOIN audit_metrics a ON a.module_key = k.module_key
|
|
ORDER BY k.module_key
|
|
`;
|
|
|
|
const AUTH_SQL = String.raw`
|
|
WITH classified AS (
|
|
SELECT
|
|
a.actor_id,
|
|
a.created_at,
|
|
CASE
|
|
WHEN e.id IS NULL THEN 'unknown'
|
|
WHEN lower(split_part(e.email, '@', 1)) ~ '^(smoke[-_.]|oa[-_.]?smoke[-_.]?)'
|
|
OR e.employee_no ~* '^(SMOKE|OSMOKE|WFULL|PRELAUNCH|LAUNCHAUTO|HRWDTEST)'
|
|
OR e.name ~ '(测试|试运行)'
|
|
THEN 'smoke'
|
|
ELSE 'human'
|
|
END AS actor_kind
|
|
FROM audit_logs a
|
|
LEFT JOIN employees e ON e.id = a.actor_id
|
|
WHERE a.action IN ('AUTH_LOGIN_SUCCESS', 'AUTH_EMAIL_LOGIN_SUCCESS', 'AUTH_OIDC_LOGIN_SUCCESS')
|
|
)
|
|
SELECT
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '30 days')::int AS "humanActors30d",
|
|
count(DISTINCT actor_id) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '90 days')::int AS "humanActors90d",
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '30 days')::int AS "humanEvents30d",
|
|
count(*) FILTER (WHERE actor_kind = 'human' AND created_at >= now() - interval '90 days')::int AS "humanEvents90d",
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND created_at >= now() - interval '30 days')::int AS "smokeEvents30d",
|
|
count(*) FILTER (WHERE actor_kind = 'smoke' AND created_at >= now() - interval '90 days')::int AS "smokeEvents90d",
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND created_at >= now() - interval '30 days')::int AS "unknownEvents30d",
|
|
count(*) FILTER (WHERE actor_kind = 'unknown' AND created_at >= now() - interval '90 days')::int AS "unknownEvents90d"
|
|
FROM classified
|
|
`;
|
|
|
|
function isSmokeLikeValue(value) {
|
|
const text = String(value ?? "").trim();
|
|
if (!text) return false;
|
|
const lower = text.toLowerCase();
|
|
const emailLocal = lower.includes("@") ? lower.split("@")[0] : lower;
|
|
return (
|
|
/^(smoke[-_.]|oa[-_.]?smoke[-_.]?)/u.test(emailLocal)
|
|
|| /^(SMOKE|OSMOKE|WFULL|PRELAUNCH|LAUNCHAUTO|HRWDTEST)[A-Z0-9_-]*/iu.test(text)
|
|
|| /测试|试运行/u.test(text)
|
|
);
|
|
}
|
|
|
|
function classifyFixtureActor(actor, forcedKind = null) {
|
|
if (forcedKind === "system") return "system";
|
|
if (!actor) return "unknown";
|
|
if ([actor.employeeNo, actor.email, actor.name].some(isSmokeLikeValue)) return "smoke";
|
|
return "human";
|
|
}
|
|
|
|
function createReadOnlyAdapter(client) {
|
|
return {
|
|
featureFlag: {
|
|
async findUnique({ where }) {
|
|
const result = await client.query(
|
|
"SELECT flag_key, override_mode, rollout_type, department_ids, note, version, created_at, created_by, updated_at, updated_by FROM feature_flags WHERE flag_key = $1",
|
|
[where.flag_key],
|
|
);
|
|
return result.rows[0] ?? null;
|
|
},
|
|
async findMany({ where }) {
|
|
const result = await client.query(
|
|
"SELECT flag_key, override_mode, rollout_type, department_ids, note, version, created_at, created_by, updated_at, updated_by FROM feature_flags WHERE flag_key = ANY($1::text[]) ORDER BY flag_key ASC",
|
|
[where.flag_key.in],
|
|
);
|
|
return result.rows;
|
|
},
|
|
},
|
|
workspaceSetting: {
|
|
async findFirst() {
|
|
const result = await client.query(
|
|
"SELECT profile, org_mode, primary_entry_mode, notification_strategy, device_priority, module_visibility_json, created_at, updated_at, updated_by FROM workspace_settings ORDER BY created_at ASC LIMIT 1",
|
|
);
|
|
return result.rows[0] ?? null;
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
function effectiveFlagState(item) {
|
|
if (item.requiresDepartment && item.effectiveReason === "department_deferred") return "partial";
|
|
return item.effectiveEnabled ? "on" : "off";
|
|
}
|
|
|
|
function applyExposure(metrics, workspace, flags) {
|
|
const flagState = new Map(flags.map((item) => [item.flagKey, effectiveFlagState(item)]));
|
|
const moduleExposure = {
|
|
portal_notifications: ["portal", "portal_home_v1"],
|
|
workflow_approvals: ["workflowTasks", null],
|
|
reimbursements_invoices: ["reimbursements", null],
|
|
payments_ap: ["paymentBatches", "payment_batch_v1"],
|
|
procurement: ["purchaseRequests", null],
|
|
contracts: ["contractsRegistry", "project_linking_v1"],
|
|
projects: ["projects", "project_domain_v1"],
|
|
assets_inventory: ["assets", null],
|
|
leave_wecom_history: ["leaveRequests", null],
|
|
attendance_presence: ["attendance", "attendance_unified_v1"],
|
|
weekly_reports: ["weeklyReports", "weekly_report_v1"],
|
|
todos: ["todos", "todo_board_v1"],
|
|
announcements: ["announcements", "announcements_v1"],
|
|
budgets: ["budgets", null],
|
|
travel: ["travelRequests", null],
|
|
people_lifecycle: ["people", "employee_lifecycle_v1"],
|
|
payroll: [null, null],
|
|
performance: [null, null],
|
|
system_configuration: ["featureFlags", null],
|
|
integrations: [null, "erp_sync"],
|
|
};
|
|
|
|
return metrics.map((metric) => {
|
|
const [navigationKey, flagKey] = moduleExposure[metric.moduleKey] ?? [null, null];
|
|
const navigationMode = navigationKey
|
|
? workspace.moduleVisibility[navigationKey] ?? "unknown"
|
|
: "no_navigation";
|
|
const effectiveState = flagKey ? flagState.get(flagKey) ?? "unknown" : "not_applicable";
|
|
return {
|
|
...metric,
|
|
latestActivityAt: metric.latestActivityAt?.toISOString?.() ?? metric.latestActivityAt ?? null,
|
|
navigationMode,
|
|
effectiveFlagState: effectiveState,
|
|
queryStatus: "PASS",
|
|
};
|
|
});
|
|
}
|
|
|
|
function assertSafeResult(metrics) {
|
|
if (!Array.isArray(metrics) || metrics.length !== MODULE_KEYS.length) {
|
|
throw new Error("result_module_count_invalid");
|
|
}
|
|
const seen = new Set();
|
|
for (const item of metrics) {
|
|
if (!MODULE_KEYS.includes(item.moduleKey) || seen.has(item.moduleKey)) {
|
|
throw new Error("result_module_key_invalid");
|
|
}
|
|
seen.add(item.moduleKey);
|
|
const keys = Object.keys(item).sort();
|
|
const expected = [...SAFE_RESULT_KEYS].sort();
|
|
if (JSON.stringify(keys) !== JSON.stringify(expected)) {
|
|
throw new Error("result_field_contract_invalid");
|
|
}
|
|
}
|
|
}
|
|
|
|
async function run() {
|
|
const appRoot = path.resolve(process.env.USAGE_CENSUS_APP_ROOT || process.cwd());
|
|
const { Client } = require(path.join(appRoot, "node_modules/pg"));
|
|
const { getConfig } = require(path.join(appRoot, "src/config.js"));
|
|
const { listFeatureFlags } = require(path.join(appRoot, "src/services/featureFlags/index.js"));
|
|
const { getWorkspaceSetting } = require(path.join(appRoot, "src/services/workspaceSettings.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 adapter = createReadOnlyAdapter(client);
|
|
const [metricResult, authResult, flags, workspace] = await Promise.all([
|
|
client.query(USAGE_SQL),
|
|
client.query(AUTH_SQL),
|
|
listFeatureFlags(adapter, config),
|
|
getWorkspaceSetting(adapter),
|
|
]);
|
|
const metrics = applyExposure(metricResult.rows, workspace, flags);
|
|
assertSafeResult(metrics);
|
|
await client.query("COMMIT");
|
|
inTransaction = false;
|
|
|
|
process.stdout.write(`${JSON.stringify({
|
|
status: "PASS",
|
|
transactionReadOnly: true,
|
|
sourceBuildSha: config.buildSha,
|
|
generatedAt: new Date().toISOString(),
|
|
authentication: authResult.rows[0],
|
|
modules: metrics,
|
|
}, null, 2)}\n`);
|
|
} catch {
|
|
if (inTransaction) {
|
|
try { await client.query("ROLLBACK"); } catch { /* fail closed */ }
|
|
}
|
|
process.stderr.write("[usage-census][FAILED] code=QUERY_FAILED\n");
|
|
process.exitCode = 1;
|
|
} finally {
|
|
await client.end().catch(() => {});
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
AUTH_SQL,
|
|
MODULE_KEYS,
|
|
SAFE_RESULT_KEYS,
|
|
USAGE_SQL,
|
|
applyExposure,
|
|
assertSafeResult,
|
|
classifyFixtureActor,
|
|
effectiveFlagState,
|
|
isSmokeLikeValue,
|
|
};
|
|
|
|
// `node -` names stdin as argv[1] and leaves require.main unset. Production
|
|
// streams this task-scoped file through stdin so it never lands on the host.
|
|
if (require.main === module || process.argv[1] === "-") {
|
|
run();
|
|
}
|