v0.71.0: admin panel — users table, login/sessions, generic DB CRUD modal
CI / build + unit + e2e (pull_request) Failing after 13m35s

This commit is contained in:
2026-09-24 09:24:31 +00:00
parent 034d7a8d94
commit b89d351587
25 changed files with 2089 additions and 6 deletions
+20
View File
@@ -84,7 +84,27 @@ export const simState = sqliteTable('sim_state', {
lastSelectedTimeScale: real('last_selected_time_scale').notNull().default(1),
});
// v0.71.0: accounts + login sessions for the admin panel (and later multiplayer auth).
// The seeded admin row is inserted by lib/db/client.ts on every open() — hash-only, see there.
export const users = sqliteTable('users', {
id: text('id').primaryKey().notNull(),
username: text('username').notNull().unique(),
// scrypt digest as "salt$hex" (16-byte hex salt, 32-byte hex hash) — verified with node:crypto.
passwordHash: text('password_hash').notNull(),
admin: integer('admin', { mode: 'boolean' }).notNull().default(false),
createdAt: integer('created_at').notNull(),
});
export const sessions = sqliteTable('sessions', {
id: text('id').primaryKey().notNull(),
userId: text('user_id').notNull(),
// Real-time (Date.now()) epoch ms — 7 days from creation; expired rows are pruned lazily on login.
expiresAt: integer('expires_at').notNull(),
});
export type PlaneRow = typeof planes.$inferSelect;
export type PackageRow = typeof packages.$inferSelect;
export type AccountRow = typeof account.$inferSelect;
export type SimStateRow = typeof simState.$inferSelect;
export type UserRow = typeof users.$inferSelect;
export type SessionRow = typeof sessions.$inferSelect;