feat(server/ops-api): add operations console backend

Stand up an internal ops-api service with operator account, auth, and
audit log subsystems backed by a dedicated migrations_ops migration set.
Wire Makefile targets and the migrate Dockerfile stage so the new schema
ships alongside the existing tenant + monitoring databases.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-28 11:32:50 +08:00
parent 299e7c311e
commit c091ad7aed
20 changed files with 1778 additions and 1 deletions
@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS ops.audit_logs;
DROP TABLE IF EXISTS ops.operator_accounts;
DROP SCHEMA IF EXISTS ops;
@@ -0,0 +1,48 @@
CREATE SCHEMA IF NOT EXISTS ops;
CREATE TABLE ops.operator_accounts (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(64) NOT NULL,
email VARCHAR(255),
password_hash VARCHAR(255) NOT NULL,
display_name VARCHAR(100) NOT NULL,
role VARCHAR(32) NOT NULL DEFAULT 'admin',
status VARCHAR(20) NOT NULL DEFAULT 'active',
last_login_at TIMESTAMPTZ,
created_by BIGINT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX uk_ops_operator_username
ON ops.operator_accounts(username)
WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX uk_ops_operator_email
ON ops.operator_accounts(email)
WHERE email IS NOT NULL AND deleted_at IS NULL;
CREATE TABLE ops.audit_logs (
id BIGSERIAL PRIMARY KEY,
operator_id BIGINT,
operator_name VARCHAR(100),
action VARCHAR(64) NOT NULL,
target_type VARCHAR(64),
target_id VARCHAR(128),
metadata JSONB,
ip VARCHAR(64),
user_agent TEXT,
request_id VARCHAR(64),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ops_audit_created_at
ON ops.audit_logs(created_at DESC);
CREATE INDEX idx_ops_audit_operator
ON ops.audit_logs(operator_id, created_at DESC)
WHERE operator_id IS NOT NULL;
CREATE INDEX idx_ops_audit_action
ON ops.audit_logs(action, created_at DESC);