Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions migrations/20260306000001_initial_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

-- ─── Channels ────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS channels (
CREATE TABLE channels (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep initial migration idempotent for fallback runners

Removing IF NOT EXISTS here makes the initial schema file non-idempotent, but the repo still has raw-SQL fallback paths that re-run migration files directly (scripts/run-tests.sh:118-127 and justfile:128-142) and suppress mysql errors with || true. In environments without sqlx (common in CI/dev shells), those paths will now hit "table exists" on the first CREATE TABLE, stop executing the rest of that file, and still report success, which can leave schema drift undetected.

Useful? React with 👍 / 👎.

id BINARY(16) NOT NULL,
name TEXT NOT NULL,
channel_type ENUM('stream','forum','dm','workflow') NOT NULL DEFAULT 'stream',
Expand All @@ -30,7 +30,7 @@ CREATE INDEX idx_channels_created_by ON channels (created_by);

-- ─── Channel Members ─────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS channel_members (
CREATE TABLE channel_members (
channel_id BINARY(16) NOT NULL,
pubkey VARBINARY(32) NOT NULL,
role ENUM('owner','admin','member','guest','bot') NOT NULL DEFAULT 'member',
Expand All @@ -50,7 +50,7 @@ CREATE INDEX idx_channel_members_channel ON channel_members (channel_id);

-- ─── Users ───────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS users (
CREATE TABLE users (
pubkey VARBINARY(32) NOT NULL,
nip05_handle VARCHAR(255) UNIQUE,
display_name TEXT,
Expand Down Expand Up @@ -83,7 +83,7 @@ CREATE INDEX idx_users_okta ON users (okta_user_id);
-- ⚠️ Deduplication by id alone is not enforceable via unique index across
-- partitions. SHA-256 collision resistance + app-layer INSERT IGNORE used.

CREATE TABLE IF NOT EXISTS events (
CREATE TABLE events (
id VARBINARY(32) NOT NULL,
pubkey VARBINARY(32) NOT NULL,
created_at DATETIME(6) NOT NULL,
Expand Down Expand Up @@ -121,7 +121,7 @@ CREATE INDEX idx_events_kind_created ON events (kind, created_at);

-- ─── Persistent Subscriptions ────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS subscriptions (
CREATE TABLE subscriptions (
id VARCHAR(255) NOT NULL,
name TEXT NOT NULL,
owner_pubkey VARBINARY(32) NOT NULL,
Expand Down Expand Up @@ -165,7 +165,7 @@ CREATE INDEX idx_subscriptions_status ON subscriptions (status);
-- ⚠️ MySQL does not support FK constraints on partitioned tables.
-- subscription_id → subscriptions(id) enforced at application layer.

CREATE TABLE IF NOT EXISTS delivery_log (
CREATE TABLE delivery_log (
id BIGINT NOT NULL AUTO_INCREMENT,
subscription_id VARCHAR(255) NOT NULL,
event_id VARBINARY(32) NOT NULL,
Expand All @@ -192,7 +192,7 @@ CREATE INDEX idx_delivery_log_failures ON delivery_log (subscription_id, de

-- ─── Workflows ────────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS workflows (
CREATE TABLE workflows (
id BINARY(16) NOT NULL,
name TEXT NOT NULL,
owner_pubkey VARBINARY(32) NOT NULL,
Expand Down Expand Up @@ -224,7 +224,7 @@ CREATE INDEX idx_workflows_channel ON workflows (channel_id);

-- ─── API Tokens ───────────────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS api_tokens (
CREATE TABLE api_tokens (
id BINARY(16) NOT NULL,
token_hash VARBINARY(32) NOT NULL UNIQUE,
owner_pubkey VARBINARY(32) NOT NULL,
Expand All @@ -248,7 +248,7 @@ CREATE INDEX idx_api_tokens_hash ON api_tokens (token_hash);

-- ─── Rate Limit Violations ────────────────────────────────────────────────────

CREATE TABLE IF NOT EXISTS rate_limit_violations (
CREATE TABLE rate_limit_violations (
id BIGINT NOT NULL AUTO_INCREMENT,
pubkey VARBINARY(32) NOT NULL,
violation_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
Expand Down
32 changes: 3 additions & 29 deletions scripts/dev-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
TIMEOUT=120 # seconds to wait for services to become healthy
DB_USER="${SPROUT_DB_USER:-sprout}"
DB_PASS="${SPROUT_DB_PASS:-sprout_dev}"
DB_NAME="${SPROUT_DB_NAME:-sprout}"
DOCKER_DB_HOST="${SPROUT_DOCKER_DB_HOST:-mysql}"
DOCKER_NETWORK="${SPROUT_DOCKER_NETWORK:-sprout-net}"
MYSQL_CLIENT_IMAGE="${SPROUT_DB_CLIENT_IMAGE:-mysql:8.0}"

# Colors
RED='\033[0;31m'
Expand Down Expand Up @@ -45,13 +39,6 @@ fi

cd "${REPO_ROOT}"

run_mysql_in_container() {
docker run --rm -i --network "${DOCKER_NETWORK}" \
-e MYSQL_PWD="${DB_PASS}" \
"${MYSQL_CLIENT_IMAGE}" \
mysql -h"${DOCKER_DB_HOST}" -u"${DB_USER}" "${DB_NAME}" "$@"
}

# ---- Start services ---------------------------------------------------------

log "Starting services..."
Expand Down Expand Up @@ -118,22 +105,9 @@ else
sqlx migrate run --source "${MIGRATION_DIR}"
success "Migrations applied via sqlx"
else
# Fallback: run SQL files directly via mysql in the container
log "sqlx CLI not found — applying migrations via mysql CLI..."
shopt -s nullglob
SQL_FILES=("${MIGRATION_DIR}"/*.sql)
shopt -u nullglob

if [[ ${#SQL_FILES[@]} -eq 0 ]]; then
warn "No .sql files found in ${MIGRATION_DIR}. Skipping."
else
for sql_file in "${SQL_FILES[@]}"; do
filename="$(basename "${sql_file}")"
log " Applying ${filename}..."
run_mysql_in_container < "${sql_file}"
done
success "Migrations applied via mysql"
fi
error "sqlx CLI not found. Install it with: cargo install sqlx-cli --no-default-features --features mysql"
error "Running migrations directly via mysql bypasses migration tracking and causes errors."
exit 1
fi
fi

Expand Down