-- Accounts: every person signs in with their own username and password, and -- the agents they make belong to them alone. -- -- Before this, one shared token from `.env` opened the whole install, and one -- hard-coded local user owned every agent. Login is now per person, so a -- session resolves to exactly one user and one workspace, and the shared token -- is gone. `password_hash IS NULL` marks an account that cannot sign in yet. ALTER TABLE users ADD COLUMN IF NOT EXISTS username TEXT, ADD COLUMN IF NOT EXISTS password_hash TEXT; -- Usernames are addresses: one spelling, matched case-insensitively. CREATE UNIQUE INDEX IF NOT EXISTS users_username_key ON users (lower(username)) WHERE username IS NOT NULL; -- Server-side sessions. Only the digest of the cookie value is stored, so a -- database leak cannot be replayed as a login, and an API restart no longer -- logs everyone out. CREATE TABLE IF NOT EXISTS app_sessions ( token_hash TEXT PRIMARY KEY, user_id TEXT NOT NULL REFERENCES users (id) ON DELETE CASCADE, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), expires_at TIMESTAMPTZ NOT NULL ); CREATE INDEX IF NOT EXISTS app_sessions_user_idx ON app_sessions (user_id); CREATE INDEX IF NOT EXISTS app_sessions_expiry_idx ON app_sessions (expires_at);