Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
8818844
Fix format_id vs id mismatch preventing format checkboxes from pre-ch…
bokelley Oct 16, 2025
d33b358
Changes auto-committed by Conductor (#481)
bokelley Oct 16, 2025
5250721
Fix product list showing legacy format IDs instead of friendly names …
bokelley Oct 16, 2025
d408740
Fix Wonderstruck product formats display and save issues (#483)
bokelley Oct 16, 2025
3aef133
Fix 500 error on product add page by correcting error handler (#485)
bokelley Oct 16, 2025
9fd2a5d
Fix product formats not saving on add/edit (#486)
bokelley Oct 16, 2025
4f333fb
Fix mock adapter product form issues with enhanced error handling (#487)
bokelley Oct 16, 2025
b80fccc
Add debug logging to diagnose GAM product format save issue (#488)
bokelley Oct 16, 2025
42d6cce
Fix AttributeError: Session has no attribute 'get_attribute_history' …
bokelley Oct 16, 2025
6c0c5cf
Fix FormatId serialization and remove unused experimental code (#490)
bokelley Oct 16, 2025
3b727c1
Fix product formats not saving on add/edit (#491)
bokelley Oct 16, 2025
454eb8f
Fix: Auto-create user records for authorized emails on tenant login (…
kmoegling-scope3 Oct 17, 2025
f86ec4f
Fix delivery_type to use underscore per AdCP spec (#493)
bokelley Oct 17, 2025
4215fe6
Remove disallowed fields from GAM responses (#494)
bokelley Oct 17, 2025
c9cffbc
Fix AdCP schema compliance issues across all adapters (#496)
bokelley Oct 17, 2025
9bef942
Fix: Normalize agent URL variations for consistent validation (#497)
bokelley Oct 17, 2025
f55c8f5
Fix creative agent MCP connection issues (#498)
bokelley Oct 17, 2025
c1135c5
Changes auto-committed by Conductor (#499)
bokelley Oct 17, 2025
404c653
Fix: Remove non-existent impressions field from AdCPPackageUpdate (#500)
bokelley Oct 17, 2025
d38c96f
Enforce auth and principal filter on list_creatives (#501)
bokelley Oct 17, 2025
453c329
fix: Remove non-existent fields from SyncCreativesResponse
EmmaLouise2018 Oct 17, 2025
acf07ed
Update AdCP format schema to latest from registry
EmmaLouise2018 Oct 17, 2025
9bf3da7
Merge pull request #502 from adcontextprotocol/fix/sync-creatives-res…
EmmaLouise2018 Oct 17, 2025
a3c77ff
Changes auto-committed by Conductor (#505)
bokelley Oct 18, 2025
5bb8b26
Fix inventory sync UX issues (#506)
bokelley Oct 18, 2025
48102da
Fix SQLAlchemy session error in background sync (#507)
bokelley Oct 19, 2025
085917d
Update schemas and fix creative preview logic (#504)
bokelley Oct 19, 2025
936aec4
Add automatic GCP service account provisioning for GAM integration (#…
bokelley Oct 19, 2025
0421af6
Add real-time progress tracking to inventory sync (#508)
bokelley Oct 19, 2025
27bb8af
Fix migration head conflict causing 503 errors (#510)
bokelley Oct 19, 2025
65b2df7
Enhance GCP service account creation logging (#511)
bokelley Oct 19, 2025
3fb037d
Fix 409 handling for sync resume functionality (#512)
bokelley Oct 19, 2025
5c5a8b4
Fix stale sync detection - allow fresh sync after 1+ hour (#514)
bokelley Oct 19, 2025
4cfe715
Fix service account creation to handle existing accounts and maintain…
bokelley Oct 19, 2025
81bfec5
Fix timezone-aware datetime comparison in stale sync detection (#516)
bokelley Oct 19, 2025
c36aef6
Fix: Include service_account_email in adapter_config dict for templat…
bokelley Oct 20, 2025
0548626
Refactor: Validate creative asset structure (#518)
bokelley Oct 20, 2025
c72e396
Remove session.tenant_name usage (#519)
bokelley Oct 20, 2025
4308c46
Changes auto-committed by Conductor (#521)
bokelley Oct 20, 2025
c6d6a1a
Changes auto-committed by Conductor (#520)
bokelley Oct 20, 2025
1343902
Fix get_products A2A error: remove invalid .root attribute access (#522)
bokelley Oct 20, 2025
7cbba7f
Fix targeting browser display and navigation issues (#523)
bokelley Oct 20, 2025
163f8d2
Changes auto-committed by Conductor (#525)
bokelley Oct 20, 2025
4faf169
Fix inventory sync not showing running status on page reload (#526)
bokelley Oct 21, 2025
ae4bc61
Fix list_creatives A2A response mapping (#527)
bokelley Oct 21, 2025
9dcc697
Changes auto-committed by Conductor (#528)
bokelley Oct 21, 2025
ddbfee2
Fix GAM inventory OOM and add reset stuck sync (#529)
bokelley Oct 21, 2025
9cd90b4
Fix service account GAM connection flow (#530)
bokelley Oct 21, 2025
87eed9c
Fix Admin UI inventory sync to actually use streaming approach (#531)
bokelley Oct 21, 2025
8da2bc4
Fix AI creative review auto-reject threshold to require high confiden…
bokelley Oct 22, 2025
b51751d
Fix inventory browser UX issues for large GAM inventories (#534)
bokelley Oct 22, 2025
71c6737
Fix sync_creatives asyncio and variable scoping errors (#535)
bokelley Oct 22, 2025
886ee03
Add Approximated DNS widget for custom domain CNAME setup (#536)
bokelley Oct 22, 2025
3128230
Fix service account network code update validation (#538)
bokelley Oct 22, 2025
89b4afb
Prioritize ad server configuration in setup checklist (#539)
bokelley Oct 22, 2025
fc4191e
Fix Approximated DNS widget 404 and add stuck sync reset button (#537)
bokelley Oct 22, 2025
cc7ce6f
Improve media buy approval UX with direct approve/reject actions (#540)
bokelley Oct 22, 2025
2671fcb
Fix A2A update_media_buy to use 'packages' per AdCP v2.0+ spec (#541)
bokelley Oct 22, 2025
d906fe4
Add domain registration management for custom domains (#543)
bokelley Oct 22, 2025
1e978f3
Fix format_ids serialization to return proper FormatId objects (#542)
bokelley Oct 22, 2025
42b7db1
Fix A2A update_media_buy and update_performance_index response serial…
bokelley Oct 22, 2025
8e4d643
🔒 Fix critical tenant isolation breach in MCP authentication (#544)
bokelley Oct 23, 2025
b272a62
Add creative assignments display to media buy detail view (#547)
bokelley Oct 23, 2025
84db1b9
Fix 400 error when saving GAM service account network code (#546)
bokelley Oct 23, 2025
014acbd
Fix tenant context error caused by overly strict security fix (#548)
bokelley Oct 23, 2025
e59c043
Make list_authorized_properties public (no auth required) (#551)
bokelley Oct 23, 2025
69632dc
Fix AttributeError when Context object lacks meta attribute (#552)
bokelley Oct 23, 2025
d9ab73c
Fix discovery endpoint auth handling and remove fallback behavior (#553)
bokelley Oct 23, 2025
53af075
Fix Approximated API endpoints for domain status check (#554)
bokelley Oct 23, 2025
6a269cd
Fix tenant context detection in MCP tools (#555)
bokelley Oct 23, 2025
98e5763
Remove promoted_offering support per AdCP v2.2.0 spec (#549)
bokelley Oct 23, 2025
3929ed3
Fix get_products MCP tool registration with missing parentheses (#556)
bokelley Oct 23, 2025
7dad603
Fix A2A list_authorized_properties tenant detection without auth (#557)
bokelley Oct 23, 2025
58d1a37
Fix MCP tenant detection by capturing Host header (#558)
bokelley Oct 23, 2025
e1bdb22
Fix nginx binding to 0.0.0.0:8000 for Fly.io load balancer (#559)
bokelley Oct 23, 2025
99cdcdc
Fix: Implement creative assignment in update_media_buy (#560)
bokelley Oct 23, 2025
76a1289
Fix creative assignment to support buyer_ref lookup (#561)
bokelley Oct 23, 2025
b577cc7
Fix list_authorized_properties to use AdCP v2.4 spec-compliant publis…
bokelley Oct 23, 2025
3b18f89
Fix A2A authentication header reading for Approximated proxy compatib…
bokelley Oct 23, 2025
64b7e77
Fix GAM service account authentication missing scope parameter (#565)
bokelley Oct 23, 2025
dcac65a
Fix BrandAsset schema to use asset_type and regenerate schemas (#566)
bokelley Oct 23, 2025
d73569a
Fix list_authorized_properties schema and add comprehensive tests (#564)
bokelley Oct 23, 2025
ae40021
Fix creative approval 500 error and webhook auth bug (#567)
bokelley Oct 23, 2025
3379390
Add duplicate product validation and assignment reporting (#568)
bokelley Oct 23, 2025
e6897c2
Fix A2A tenant authentication by resolving tenant from headers before…
bokelley Oct 23, 2025
59bccc2
Fix inventory sync to support service account authentication (#570)
kmoegling-scope3 Oct 23, 2025
e324a3e
Add AGENTS symlink to CLAUDE instructions (#524)
patmmccann Oct 23, 2025
bcb1686
Fix: Correct AdManagerClient signature for service account auth (#571)
kmoegling-scope3 Oct 23, 2025
b3bd180
Update generated schemas to match AdCP v2.2.0 spec (#572)
bokelley Oct 23, 2025
99be8a0
Fix authentication and tenant detection issues (#573)
bokelley Oct 23, 2025
8522505
Add comprehensive debug logging for virtual host tenant detection (#575)
bokelley Oct 24, 2025
7f55df9
Fix schema generator to use union operator for consistency (#574)
bokelley Oct 24, 2025
9a6777d
Fix A2A list_authorized_properties tenant detection without auth (#577)
bokelley Oct 24, 2025
b21672b
Fix MCP list_authorized_properties tenant detection without context (…
bokelley Oct 24, 2025
6d7a378
Fix GAM service account authentication (#579)
bokelley Oct 24, 2025
4228a93
Enable FastMCP sessions for proper HTTP context in unauthenticated ca…
bokelley Oct 24, 2025
b9fa85d
Fix remaining service account credential wrapping issues (#581)
bokelley Oct 24, 2025
5e00818
Fix service account credential wrapping in GAM setup flow (#584)
bokelley Oct 24, 2025
b773aea
Add comprehensive MCP debugging for list_authorized_properties (#583)
bokelley Oct 24, 2025
6090e09
Add service_account_json support to GoogleAdManagerAdapter validation…
bokelley Oct 24, 2025
8240f76
Switch to logger.info() for MCP debugging visibility (#586)
bokelley Oct 24, 2025
4ce0125
Fix get_gam_advertisers endpoint to support service account auth (#588)
bokelley Oct 24, 2025
c88ab38
Add explicit logging for tenant detection header values (#589)
bokelley Oct 24, 2025
b615290
Add timeouts to GAM operations to prevent indefinite hangs (#587)
bokelley Oct 24, 2025
4893c04
Add detailed logging to debug MCP header extraction (#591)
bokelley Oct 24, 2025
70bf497
Add stderr debugging output for MCP header extraction (#592)
bokelley Oct 24, 2025
0518f4b
Fix database commit timeout - sync hangs on write phase (#593)
bokelley Oct 24, 2025
3504ef0
Add comprehensive stderr debugging to get_principal_from_context (#594)
bokelley Oct 24, 2025
2f3d24e
URGENT: Fix deployment crash - product.adapter_type doesn't exist (#595)
bokelley Oct 24, 2025
649ae3a
Use logger.error() for MCP debugging visibility (#596)
bokelley Oct 24, 2025
6c56b5c
Fix virtual host detection: check virtual_host before subdomain (#598)
bokelley Oct 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 10 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,16 @@ DATABASE_URL=postgresql://adcp_user:secure_password_change_me@postgres:5432/adcp
# ============================================
# Only needed if using real ad server adapters

# Google Ad Manager
# Google Ad Manager OAuth (for GAM Admin UI configuration)
GAM_OAUTH_CLIENT_ID=your-gam-oauth-client-id.apps.googleusercontent.com
GAM_OAUTH_CLIENT_SECRET=your-gam-oauth-client-secret

# Google Cloud Platform (for auto-provisioning service accounts)
# Required if you want to use the "Create Service Account" feature in Admin UI
# This is the GCP project ID where service accounts will be created
# GCP_PROJECT_ID=your-gcp-project-id

# Legacy: Manual GAM configuration (not needed if using Admin UI)
# GAM_NETWORK_CODE=123456789
# GAM_SERVICE_ACCOUNT_JSON='{"type":"service_account"...}'

Expand Down
15 changes: 11 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ gam_ad_units.json
client_secret*.json
credentials*.json

# GCP Service Account Keys
*-key.json
adcp-manager-key.json

# Build artifacts
*.egg-info/
*.egg-info
Expand Down Expand Up @@ -44,6 +48,12 @@ Thumbs.db

# Python
*.pyc

# Diagnostic scripts (one-off debugging tools)
check_*.py
diagnose_*.py
fix_*.py
test_sync.py
*.pyo
*.pyd
.Python
Expand Down Expand Up @@ -91,7 +101,4 @@ test_*.db
test_*.db-*
test_*[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/
.env.test

# Schema cache metadata (ETag tracking)
# Don't commit .meta files - they're local cache metadata
tests/e2e/schemas/**/*.meta
test_sync.py
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ repos:
files: '^(src/core/schemas\.py|src/core/main\.py)$'
pass_filenames: false

# Check generated schemas are in sync with JSON schemas
# NOTE: Removed this hook - script doesn't exist and check_schema_sync.py
# already validates schema alignment (runs on every commit via adcp-schema-sync)

# Test MCP endpoints (requires server running)
- id: mcp-endpoint-tests
name: Test MCP endpoints
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
9 changes: 7 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ pytest tests/unit/test_adcp_contract.py -v
```

**Current Schema Version:**
- AdCP Version: v2.4
- AdCP Version: 2.2.0 (official spec version)
- Schema Version: v1
- Last Verified: 2025-09-02
- Last Verified: 2025-10-22
- Source: https://adcontextprotocol.org/schemas/v1/index.json
- Note: Internal "v2.4" references in codebase refer to feature evolution, not official spec versions

---

Expand Down Expand Up @@ -307,6 +308,10 @@ def create_media_buy_raw(promoted_offering: str, ...) -> CreateMediaBuyResponse:
- PostgreSQL (production and testing)
- We'll support your deployment approach as best we can

**Known Test Agent Issues:**
- **`create_media_buy` auth failure** (2025-10-04): Rejects valid auth tokens. See [postmortem](docs/testing/postmortems/2025-10-04-test-agent-auth-bug.md)
- **`get_media_buy_delivery` parameter mismatch** (2025-10-04): Expects `media_buy_id` (singular) instead of spec-compliant `media_buy_ids` (plural)

**When Test Agent is Down:**
- Check Fly.io logs first: `fly logs --app <test-agent-app-name>`
- Check Fly.io status: `fly status --app <test-agent-app-name>`
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# syntax=docker/dockerfile:1.4
# Multi-stage build for smaller image
# Cache bust: 2025-10-22-2135
FROM python:3.12-slim AS builder

# Disable man pages and docs to speed up apt operations
Expand Down Expand Up @@ -64,6 +65,10 @@ RUN useradd -m -u 1000 adcp

WORKDIR /app

# Cache bust for COPY layer - change this value to force rebuild
ARG CACHE_BUST=2025-10-23-FIX-PROMOTED-OFFERING-V4
RUN echo "Cache bust: $CACHE_BUST"

# Copy application code
COPY . .

Expand Down
137 changes: 137 additions & 0 deletions MIGRATION_REQUIRED_delivery_type_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# URGENT: Production Migration Required - delivery_type Validation Failure

## Issue Summary

**Status:** 🔴 BLOCKING PRODUCTION
**Date Discovered:** 2025-10-16
**Affected Systems:** All production sales agents (Wonderstruck, Test Agent, etc.)

### Problem

Production databases contain products with invalid `delivery_type` values:
- **Current (invalid):** `'non-guaranteed'` (hyphen)
- **Required (spec-compliant):** `'non_guaranteed'` (underscore)

This causes **all `get_products` calls to fail** with validation errors:

```
Product 'prod_e8fd6012' in database failed AdCP schema validation.
Error: 1 validation error for Product
delivery_type
Input should be 'guaranteed' or 'non_guaranteed' [type=literal_error, input_value='non-guaranteed', input_type=str]
```

### Root Cause

1. **AdCP Spec** defines delivery_type enum as: `["guaranteed", "non_guaranteed"]` (underscore)
2. **Historic Data** used hyphenated format: `'non-guaranteed'`
3. **Schema Enforcement** now strictly validates per AdCP spec (src/core/schemas.py:654)
4. **Migration Exists** (`f9300bf2246d`) but **hasn't been run on production**

## Impact

- ❌ `get_products` fails for all agents
- ❌ Product discovery broken
- ❌ Cannot create new media buys (no products available)
- ❌ Wonderstruck integration test failing
- ❌ All AdCP workflows blocked

## Solution

### Migration Details

**File:** `alembic/versions/f9300bf2246d_fix_delivery_type_values_hyphen_to_.py`
**Revision:** `f9300bf2246d`
**Depends On:** `2453043b72da`
**Created:** 2025-10-16 10:00:09

**What it does:**
```sql
UPDATE products
SET delivery_type = 'non_guaranteed'
WHERE delivery_type = 'non-guaranteed'
```

### Deployment Steps

#### For Fly.io Production (Wonderstruck, Test Agent)

```bash
# 1. Check current migration state
fly ssh console --app wonderstruck-sales-agent
cd /app
uv run alembic current

# 2. Run pending migrations (includes f9300bf2246d)
uv run python migrate.py

# 3. Verify migration applied
uv run alembic current # Should show f9300bf2246d or later

# 4. Verify data fixed
uv run python -c "
from src.core.database.database_session import get_db_session
from src.core.database.models import Product
from sqlalchemy import select

with get_db_session() as session:
stmt = select(Product).where(Product.delivery_type == 'non-guaranteed')
bad_products = session.scalars(stmt).all()
print(f'Products with old format: {len(bad_products)}')

stmt = select(Product).where(Product.delivery_type == 'non_guaranteed')
good_products = session.scalars(stmt).all()
print(f'Products with new format: {len(good_products)}')
"

# 5. Test get_products endpoint
curl -H "x-adcp-auth: <principal_token>" \
https://wonderstruck.sales-agent.scope3.com/mcp/get_products
```

#### Repeat for Test Agent

```bash
fly ssh console --app test-agent
cd /app
uv run python migrate.py
# ... verify as above
```

### Verification

After migration:
- ✅ No products should have `delivery_type = 'non-guaranteed'`
- ✅ All products should have `delivery_type = 'guaranteed'` OR `'non_guaranteed'`
- ✅ `get_products` should return results without validation errors
- ✅ Run: `tsx scripts/manual-testing/full-wonderstruck-test.ts` should pass

## Prevention

1. **Schema Validation Tests:** `tests/unit/test_adcp_contract.py` enforces spec compliance
2. **Pre-commit Hooks:** Check for spec violations before commit
3. **Migration Testing:** Always test migrations locally before production
4. **CI/CD Integration:** Migrations run automatically on deploy

## References

- **AdCP Spec:** https://adcontextprotocol.org/schemas/v1/
- **Schema Definition:** `src/core/schemas.py:654`
- **Migration File:** `alembic/versions/f9300bf2246d_fix_delivery_type_values_hyphen_to_.py`
- **Related Issue:** Product validation blocking all workflows
- **Documentation:** `CLAUDE.md` sections on AdCP compliance and PostgreSQL-only architecture

## Next Steps

1. ✅ Document issue (this file)
2. ⏳ Deploy migration to Wonderstruck production
3. ⏳ Deploy migration to Test Agent production
4. ⏳ Verify all agents return products successfully
5. ⏳ Re-run Wonderstruck integration test
6. ⏳ Delete this file after successful deployment

---

**Created:** 2025-10-16
**Author:** Conductor Workspace (vatican-v3)
**Branch:** fix-delivery-type-validation
73 changes: 73 additions & 0 deletions alembic/versions/1a7693edad5d_ensure_default_property_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""ensure_default_property_tags

Ensures all tenants have a default 'all_inventory' PropertyTag.
This tag is commonly used in products to indicate coverage of all properties.

Revision ID: 1a7693edad5d
Revises: 0d4fe6eb03ab
Create Date: 2025-10-16 16:43:51.255012

"""

from collections.abc import Sequence

from sqlalchemy import text

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "1a7693edad5d"
down_revision: str | Sequence[str] | None = "0d4fe6eb03ab"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
"""Ensure all tenants have default property tags."""
conn = op.get_bind()

# Get all tenants
result = conn.execute(text("SELECT tenant_id FROM tenants"))
tenant_ids = [row[0] for row in result]

# For each tenant, ensure 'all_inventory' property tag exists
for tenant_id in tenant_ids:
# Check if tag already exists
existing = conn.execute(
text("SELECT COUNT(*) FROM property_tags WHERE tenant_id = :tenant_id AND tag_id = 'all_inventory'"),
{"tenant_id": tenant_id},
).scalar()

if not existing:
# Insert the default tag
conn.execute(
text(
"""
INSERT INTO property_tags (tenant_id, tag_id, name, description, created_at, updated_at)
VALUES (:tenant_id, 'all_inventory', 'All Inventory',
'All available inventory across all properties', NOW(), NOW())
"""
),
{"tenant_id": tenant_id},
)
print(f"✅ Created 'all_inventory' PropertyTag for tenant {tenant_id}")
else:
print(f"ℹ️ 'all_inventory' PropertyTag already exists for tenant {tenant_id}")


def downgrade() -> None:
"""Remove default property tags created by this migration."""
conn = op.get_bind()

# Remove all 'all_inventory' tags that were created by this migration
# Note: We only remove tags with the exact description we created
conn.execute(
text(
"""
DELETE FROM property_tags
WHERE tag_id = 'all_inventory'
AND description = 'All available inventory across all properties'
"""
)
)
print("Removed default 'all_inventory' PropertyTags")
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""add_gam_service_account_email_to_adapter_config

Revision ID: 661c474053fa
Revises: 1a7693edad5d
Create Date: 2025-10-19 04:41:52.439532

"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "661c474053fa"
down_revision: str | Sequence[str] | None = "1a7693edad5d"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
"""Upgrade schema."""
# Only add service account email - GCP project ID is environment config, not per-tenant
op.add_column("adapter_config", sa.Column("gam_service_account_email", sa.String(length=255), nullable=True))


def downgrade() -> None:
"""Downgrade schema."""
op.drop_column("adapter_config", "gam_service_account_email")
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Add progress tracking to sync_jobs

Revision ID: ed7d05fea3be
Revises: 1a7693edad5d
Create Date: 2025-10-19 06:43:06.718520

"""

from collections.abc import Sequence

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "ed7d05fea3be"
down_revision: str | Sequence[str] | None = "661c474053fa"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
"""Upgrade schema."""
# Add progress column to sync_jobs table
op.add_column("sync_jobs", sa.Column("progress", sa.dialects.postgresql.JSONB, nullable=True))


def downgrade() -> None:
"""Downgrade schema."""
# Remove progress column from sync_jobs table
op.drop_column("sync_jobs", "progress")
Loading