Skip to content

Commit 310701b

Browse files
authored
Merge pull request #43 from aws-samples/feat/monthly-auto-recharge
feat: teams, monthly quota, Opus 4.7, UI polish
2 parents d7661a2 + 7903698 commit 310701b

30 files changed

Lines changed: 3078 additions & 182 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,4 @@ npm-debug.log*
101101
yarn-debug.log*
102102
yarn-error.log*
103103
.gitnexus
104+
kolya-br-proxy-arch/graphify-out/
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Add monthly quota, daily limit, reset policy, and quota start to api_tokens.
2+
3+
Revision ID: f7g8h9i0j1k2
4+
Revises: e6f7g8h9i0j1
5+
Create Date: 2026-04-30
6+
"""
7+
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
revision = "f7g8h9i0j1k2"
13+
down_revision = "e6f7g8h9i0j1"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade() -> None:
19+
op.add_column(
20+
"api_tokens",
21+
sa.Column("monthly_quota_usd", sa.Numeric(10, 2), nullable=True),
22+
)
23+
op.add_column(
24+
"api_tokens",
25+
sa.Column("monthly_reset_policy", sa.String(20), nullable=True),
26+
)
27+
op.add_column(
28+
"api_tokens",
29+
sa.Column("monthly_quota_start", sa.DateTime, nullable=True),
30+
)
31+
32+
33+
def downgrade() -> None:
34+
op.drop_column("api_tokens", "monthly_quota_start")
35+
op.drop_column("api_tokens", "monthly_reset_policy")
36+
op.drop_column("api_tokens", "monthly_quota_usd")
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""Add record_type to usage_records for distinguishing adjustments.
2+
3+
Revision ID: g8h9i0j1k2l3
4+
Revises: f7g8h9i0j1k2
5+
Create Date: 2026-04-30
6+
"""
7+
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
revision = "g8h9i0j1k2l3"
13+
down_revision = "f7g8h9i0j1k2"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade() -> None:
19+
op.add_column(
20+
"usage_records",
21+
sa.Column(
22+
"record_type",
23+
sa.String(20),
24+
nullable=False,
25+
server_default="usage",
26+
),
27+
)
28+
op.add_column(
29+
"usage_records",
30+
sa.Column("note", sa.String(500), nullable=True),
31+
)
32+
33+
34+
def downgrade() -> None:
35+
op.drop_column("usage_records", "note")
36+
op.drop_column("usage_records", "record_type")
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Add teams and team_members tables.
2+
3+
Revision ID: h9i0j1k2l3m4
4+
Revises: g8h9i0j1k2l3
5+
Create Date: 2026-05-01
6+
"""
7+
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects.postgresql import UUID
11+
12+
13+
revision = "h9i0j1k2l3m4"
14+
down_revision = "g8h9i0j1k2l3"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade() -> None:
20+
op.create_table(
21+
"teams",
22+
sa.Column("id", UUID(as_uuid=True), nullable=False),
23+
sa.Column("user_id", UUID(as_uuid=True), nullable=False),
24+
sa.Column("name", sa.String(255), nullable=False),
25+
sa.Column("monthly_budget_usd", sa.Numeric(10, 2), nullable=False),
26+
sa.Column(
27+
"monthly_reset_policy",
28+
sa.String(20),
29+
nullable=False,
30+
server_default="reset",
31+
),
32+
sa.Column("monthly_budget_start", sa.DateTime(), nullable=False),
33+
sa.Column("is_active", sa.Boolean(), nullable=False, server_default="true"),
34+
sa.Column("created_at", sa.DateTime(), nullable=False),
35+
sa.Column("updated_at", sa.DateTime(), nullable=False),
36+
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
37+
sa.PrimaryKeyConstraint("id"),
38+
)
39+
op.create_index("ix_teams_user_id", "teams", ["user_id"])
40+
41+
op.create_table(
42+
"team_members",
43+
sa.Column("id", UUID(as_uuid=True), nullable=False),
44+
sa.Column("team_id", UUID(as_uuid=True), nullable=False),
45+
sa.Column("token_id", UUID(as_uuid=True), nullable=False),
46+
sa.Column(
47+
"allocated_usd", sa.Numeric(10, 2), nullable=False, server_default="0.00"
48+
),
49+
sa.Column("created_at", sa.DateTime(), nullable=False),
50+
sa.Column("updated_at", sa.DateTime(), nullable=False),
51+
sa.ForeignKeyConstraint(["team_id"], ["teams.id"], ondelete="CASCADE"),
52+
sa.ForeignKeyConstraint(["token_id"], ["api_tokens.id"], ondelete="CASCADE"),
53+
sa.PrimaryKeyConstraint("id"),
54+
)
55+
op.create_index("ix_team_members_team_id", "team_members", ["team_id"])
56+
op.create_index(
57+
"ix_team_members_token_id", "team_members", ["token_id"], unique=True
58+
)
59+
op.execute(
60+
"ALTER TABLE team_members "
61+
"ADD CONSTRAINT ck_allocated_non_negative CHECK (allocated_usd >= 0)"
62+
)
63+
64+
65+
def downgrade() -> None:
66+
op.execute(
67+
"ALTER TABLE team_members DROP CONSTRAINT IF EXISTS ck_allocated_non_negative"
68+
)
69+
op.drop_index("ix_team_members_token_id", "team_members")
70+
op.drop_index("ix_team_members_team_id", "team_members")
71+
op.drop_table("team_members")
72+
op.drop_index("ix_teams_user_id", "teams")
73+
op.drop_table("teams")
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Add daily_limit_enabled to teams.
2+
3+
Revision ID: i0j1k2l3m4n5
4+
Revises: h9i0j1k2l3m4
5+
Create Date: 2026-05-01
6+
"""
7+
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
revision = "i0j1k2l3m4n5"
13+
down_revision = "h9i0j1k2l3m4"
14+
branch_labels = None
15+
depends_on = None
16+
17+
18+
def upgrade() -> None:
19+
op.add_column(
20+
"teams",
21+
sa.Column(
22+
"daily_limit_enabled",
23+
sa.Boolean(),
24+
nullable=False,
25+
server_default="true",
26+
),
27+
)
28+
29+
30+
def downgrade() -> None:
31+
op.drop_column("teams", "daily_limit_enabled")

0 commit comments

Comments
 (0)