Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
07d17ed
feat(assets): align local API with cloud spec
luke-mino-altherr Mar 10, 2026
e767f48
Fix review issues: tags validation, size nullability, type annotation…
luke-mino-altherr Mar 10, 2026
8efd261
Add preview_url to /assets API response using /api/view endpoint
luke-mino-altherr Mar 11, 2026
acadeb8
chore: remove unused imports from asset_reference queries
luke-mino-altherr Mar 11, 2026
6c02ece
feat: resolve blake3 hashes in /view endpoint via asset database
luke-mino-altherr Mar 11, 2026
b909270
Register uploaded images in asset database when --enable-assets is set
luke-mino-altherr Mar 12, 2026
77bf530
Exclude None fields from asset API JSON responses
luke-mino-altherr Mar 12, 2026
c3a8378
Add comment explaining why /view resolves blake3 hashes
luke-mino-altherr Mar 12, 2026
aa953a2
Move blake3 hash resolution to asset_management service
luke-mino-altherr Mar 12, 2026
9cfb9c7
Require at least one tag in UploadAssetSpec
luke-mino-altherr Mar 12, 2026
58e4bbf
Add owner_id check to resolve_hash_to_path
luke-mino-altherr Mar 12, 2026
357765e
Make ReferenceData.created_at and updated_at required
luke-mino-altherr Mar 12, 2026
da0ae02
Fix double commit in create_from_hash
luke-mino-altherr Mar 12, 2026
2e35c77
Add exclude_none=True to create/upload responses
luke-mino-altherr Mar 12, 2026
23e458e
Change preview_id to reference asset by reference ID, not content ID
luke-mino-altherr Mar 12, 2026
d78c741
Filter soft-deleted and missing refs from visibility queries
luke-mino-altherr Mar 12, 2026
a322664
Pass preview_id and mime_type through all asset creation fast paths
luke-mino-altherr Mar 12, 2026
bec0e70
Remove unimplemented client-provided ID from upload API
luke-mino-altherr Mar 12, 2026
0ba183a
Make asset mime_type immutable after first ingest
luke-mino-altherr Mar 12, 2026
aa79b64
Use resolved content_type from asset lookup in /view endpoint
luke-mino-altherr Mar 12, 2026
1d1de34
Merge system+user metadata into filter projection
luke-mino-altherr Mar 12, 2026
97341de
Standardize tag ordering to alphabetical across all endpoints
luke-mino-altherr Mar 12, 2026
8006fde
Derive subfolder tags from path in register_file_in_place
luke-mino-altherr Mar 12, 2026
940b202
Reject client-provided id, fix preview URLs, rename tags→total_tags
luke-mino-altherr Mar 12, 2026
08dfff5
fix: SQLite migration 0003 FK drop fails on file-backed DBs (MB-2)
luke-mino-altherr Mar 12, 2026
fb2e70c
Fix missing tag count for is_missing references and update test for t…
luke-mino-altherr Mar 13, 2026
735fda9
Remove unused imports in scanner.py
luke-mino-altherr Mar 13, 2026
d67870f
Rename prompt_id to job_id on asset_references
luke-mino-altherr Mar 15, 2026
e86186c
Add index on asset_references.preview_id for FK cascade performance
luke-mino-altherr Mar 15, 2026
94de8af
Add clarifying comments for Asset/AssetReference naming and preview_id
luke-mino-altherr Mar 15, 2026
24a6a7c
Disallow all-null meta rows: add CHECK constraint, skip null values o…
luke-mino-altherr Mar 15, 2026
0b6d48d
Remove dead None guards on result.asset in upload handler
luke-mino-altherr Mar 15, 2026
8570fd5
Remove mime_type from asset update API
luke-mino-altherr Mar 15, 2026
b6e0df3
Fix migration constraint naming double-prefix and NULL in mixed metad…
luke-mino-altherr Mar 15, 2026
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
7 changes: 5 additions & 2 deletions alembic_db/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
config = context.config


from app.database.models import Base
from app.database.models import Base, NAMING_CONVENTION
target_metadata = Base.metadata

# other values from the config, defined by the needs of env.py,
Expand Down Expand Up @@ -51,7 +51,10 @@ def run_migrations_online() -> None:

with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
connection=connection,
target_metadata=target_metadata,
render_as_batch=True,
naming_convention=NAMING_CONVENTION,
)

with context.begin_transaction():
Expand Down
98 changes: 98 additions & 0 deletions alembic_db/versions/0003_add_metadata_job_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""
Add system_metadata and job_id columns to asset_references.
Change preview_id FK from assets.id to asset_references.id.

Revision ID: 0003_add_metadata_job_id
Revises: 0002_merge_to_asset_references
Create Date: 2026-03-09
"""

from alembic import op
import sqlalchemy as sa

from app.database.models import NAMING_CONVENTION

revision = "0003_add_metadata_job_id"
down_revision = "0002_merge_to_asset_references"
branch_labels = None
depends_on = None


def upgrade() -> None:
with op.batch_alter_table("asset_references") as batch_op:
batch_op.add_column(
sa.Column("system_metadata", sa.JSON(), nullable=True)
)
batch_op.add_column(
sa.Column("job_id", sa.String(length=36), nullable=True)
)

# Change preview_id FK from assets.id to asset_references.id (self-ref).
# Existing values are asset-content IDs that won't match reference IDs,
# so null them out first.
op.execute("UPDATE asset_references SET preview_id = NULL WHERE preview_id IS NOT NULL")
with op.batch_alter_table(
"asset_references", naming_convention=NAMING_CONVENTION
) as batch_op:
batch_op.drop_constraint(
"fk_asset_references_preview_id_assets", type_="foreignkey"
)
batch_op.create_foreign_key(
"fk_asset_references_preview_id_asset_references",
"asset_references",
["preview_id"],
["id"],
ondelete="SET NULL",
)
batch_op.create_index(
"ix_asset_references_preview_id", ["preview_id"]
)

# Purge any all-null meta rows before adding the constraint
op.execute(
"DELETE FROM asset_reference_meta"
" WHERE val_str IS NULL AND val_num IS NULL AND val_bool IS NULL AND val_json IS NULL"
)
with op.batch_alter_table("asset_reference_meta") as batch_op:
batch_op.create_check_constraint(
"ck_asset_reference_meta_has_value",
"val_str IS NOT NULL OR val_num IS NOT NULL OR val_bool IS NOT NULL OR val_json IS NOT NULL",
)


def downgrade() -> None:
# SQLite doesn't reflect CHECK constraints, so we must declare it
# explicitly via table_args for the batch recreate to find it.
# Use the fully-rendered constraint name to avoid the naming convention
# doubling the prefix.
with op.batch_alter_table(
"asset_reference_meta",
table_args=[
sa.CheckConstraint(
"val_str IS NOT NULL OR val_num IS NOT NULL OR val_bool IS NOT NULL OR val_json IS NOT NULL",
name="ck_asset_reference_meta_has_value",
),
],
) as batch_op:
batch_op.drop_constraint(
"ck_asset_reference_meta_has_value", type_="check"
)

with op.batch_alter_table(
"asset_references", naming_convention=NAMING_CONVENTION
) as batch_op:
batch_op.drop_index("ix_asset_references_preview_id")
batch_op.drop_constraint(
"fk_asset_references_preview_id_asset_references", type_="foreignkey"
)
batch_op.create_foreign_key(
Comment thread
luke-mino-altherr marked this conversation as resolved.
"fk_asset_references_preview_id_assets",
"assets",
["preview_id"],
["id"],
ondelete="SET NULL",
)

with op.batch_alter_table("asset_references") as batch_op:
batch_op.drop_column("job_id")
batch_op.drop_column("system_metadata")
Loading
Loading