NoteStack-Test / backend /alembic /versions /0024_plan_limits.py
HumeraR's picture
feat: add artifact feedback component and related hooks
55d0eca
Raw History Blame Contribute Delete
2.76 kB
"""plan_limits: posts indexed across every source, Free allowances that are totals, new Writer and Studio numbers
Revision ID: 0024_plan_limits
Revises: 0023_drop_brand_kit
Create Date: 2026-10-08
"""
import sqlalchemy as sa
from alembic import op
revision = "0024_plan_limits"
down_revision = "0023_drop_brand_kit"
branch_labels = None
depends_on = None
PLANS = {
"free": dict(sources=-1, indexed_posts=5, audio_minutes=-1, audio_overviews=1, videos=2, launch_kits=2, reports=2,
infographics=2, videos_monthly=False, features=[
"Up to 5 posts indexed, from any source", "Grounded research chat with citations",
"1 audio overview, any length", "2 videos", "2 Launch Kits", "2 infographics", "2 reports a month"]),
"writer": dict(sources=-1, indexed_posts=100, audio_minutes=60, audio_overviews=-1, videos=10, launch_kits=20,
reports=30, infographics=30, features=[
"Up to 100 posts indexed, from any source", "60 min of audio overviews a month", "10 videos a month",
"20 Launch Kits a month", "30 reports a month", "30 infographics a month",
"Voice cloning with consent"]),
"studio": dict(sources=-1, indexed_posts=250, audio_minutes=240, audio_overviews=-1, videos=20, launch_kits=50,
reports=-1, infographics=-1, features=[
"Up to 250 posts indexed, from any source", "240 min of audio overviews a month",
"20 videos a month", "50 Launch Kits a month", "Unlimited reports", "Unlimited infographics",
"Launchpad calendar and resurfacing", "Priority rendering"]),
}
def upgrade() -> None:
columns = {c["name"] for c in sa.inspect(op.get_bind()).get_columns("plans")}
if "audio_overviews" not in columns:
op.add_column("plans", sa.Column("audio_overviews", sa.Integer(), nullable=False, server_default="-1"))
plans = sa.table("plans", sa.column("id", sa.String), sa.column("sources", sa.Integer),
sa.column("indexed_posts", sa.Integer), sa.column("audio_minutes", sa.Integer),
sa.column("audio_overviews", sa.Integer), sa.column("videos", sa.Integer),
sa.column("launch_kits", sa.Integer), sa.column("reports", sa.Integer),
sa.column("infographics", sa.Integer), sa.column("videos_monthly", sa.Boolean),
sa.column("features", sa.JSON))
for plan_id, values in PLANS.items():
op.execute(plans.update().where(plans.c.id == plan_id).values(**values))
def downgrade() -> None:
with op.batch_alter_table("plans") as batch:
batch.drop_column("audio_overviews")