Show provisioning requesters and reserve Maxis for system actions

This commit is contained in:
2026-10-08 16:19:49 -04:00
parent 2b155ded8f
commit d8fb7e1d66
10 changed files with 77 additions and 15 deletions
+4 -2
View File
@@ -2,7 +2,7 @@ import { createHash, randomBytes, randomUUID, timingSafeEqual } from 'node:crypt
import { db } from '../db/index.js';
import { ensureAuthSchema } from './schema.js';
import { hashPassword, verifyPassword } from './passwords.js';
import type { AuthUser, UserRole } from '../../auth.js';
import { systemUsername, type AuthUser, type UserRole } from '../../auth.js';
export const SESSION_COOKIE = '__Host-ec_session';
export const SESSION_LIFETIME_MS = 12 * 60 * 60_000;
@@ -25,7 +25,9 @@ export function listUsers(): AuthUser[] { return (database().prepare('SELECT * F
export function setupRequired(): boolean { return !(database().prepare('SELECT 1 FROM auth_users LIMIT 1').get()); }
function username(value: unknown): string {
if (typeof value !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{2,63}$/.test(value)) throw new AuthError('Usernames need 3–64 letters, numbers, dots, underscores or hyphens.');
return value.toLowerCase();
const normalized = value.toLowerCase();
if (normalized === systemUsername.toLowerCase()) throw new AuthError(`${systemUsername} is reserved for system actions. Choose another username.`);
return normalized;
}
function displayName(value: unknown, fallback: string): string {
const name = value === undefined ? fallback : value;
+1 -1
View File
@@ -303,7 +303,7 @@ const reviewDeployment = `d.state IN ('failed', 'interrupted', 'warning') AND NO
SELECT 1 FROM retention_controls c WHERE c.category='provisioning' AND c.record_id=d.id
AND c.resolved_at >= COALESCE(d.finished_at,d.started_at))`;
const deploymentListColumns = `d.id, d.server, d.server_deleted_at, d.action, d.state, d.stage,
d.started_at, d.finished_at, d.triggered_by, d.error, d.warnings,
d.started_at, d.finished_at, d.triggered_by, d.requested_by, d.error, d.warnings,
d.phase_key AS phase, d.phase_started_at AS phaseStartedAt,
CASE WHEN json_valid(d.observation_json) THEN json_extract(d.observation_json,'$.blocker.code') END AS waitCode,
(d.server_deleted_at IS NULL AND EXISTS(SELECT 1 FROM servers s WHERE s.name = d.server AND s.destroyed_at IS NULL)) AS server_exists,