From 33acf408c319b1d5643f04206c10aaa7b8622b21 Mon Sep 17 00:00:00 2001 From: ololadedavidvictor-bit Date: Mon, 28 Sep 2026 12:54:21 +0000 Subject: [PATCH] fix: resolve migration and Stellar asset issues --- .../src/lib/stellar/validate-asset-pairs.ts | 28 ++++++++++++++- .../github-app-installation.service.ts | 2 +- .../backend/src/services/job-queue.service.ts | 2 +- .../multi-provider-auth.service.test.ts | 2 +- apps/backend/src/services/template.service.ts | 2 +- .../src/services/webhook-delivery.service.ts | 2 +- docs/admin-ops-dlq.md | 2 +- docs/cross-region-deployment-guide.md | 2 +- docs/github-vercel-deployment-triggering.md | 2 +- package.json | 4 +-- packages/stellar/src/index.ts | 1 + packages/stellar/src/stellar-asset.test.ts | 21 +++++++++++ packages/stellar/src/stellar-asset.ts | 31 ++++++++++++++++ .../stellar/src/upgrade-orchestrator.test.ts | 5 +++ scripts/check-migration-numbering.js | 32 +++++++++++++++++ scripts/check-migration-numbering.test.js | 35 +++++++++++++++++++ ...orage.sql => 007_secure_token_storage.sql} | 0 ...pe.sql => 008_field_encryption_stripe.sql} | 0 ....sql => 009_github_vercel_deployments.sql} | 0 ...sql => 010_deployment_updates_rollout.sql} | 0 ...l => 011_auth_audit_logs_cross_region.sql} | 0 ...ete.sql => 012_deployment_soft_delete.sql} | 0 ...s.sql => 013_github_app_installations.sql} | 0 ....sql => 014_vercel_blue_green_aliases.sql} | 0 ...l => 015_analytics_query_optimization.sql} | 0 ... => 016_branding_asset_storage_policy.sql} | 0 ...=> 017_metered_billing_usage_tracking.sql} | 0 ...oauth.sql => 018_multi_provider_oauth.sql} | 0 ...p.sql => 019_pgcron_automated_cleanup.sql} | 0 ... 020_github_webhook_delivery_tracking.sql} | 0 ...sql => 021_artifact_storage_namespace.sql} | 0 ...eckpoints.sql => 022_cron_checkpoints.sql} | 0 ...failures.sql => 023_cron_job_failures.sql} | 0 ...eliveries.sql => 024_email_deliveries.sql} | 0 .../{014_job_queue.sql => 025_job_queue.sql} | 2 +- ...> 026_orphaned_artifact_cleanup_audit.sql} | 0 ...cache.sql => 027_region_latency_cache.sql} | 0 ...im_rpc.sql => 028_job_queue_claim_rpc.sql} | 2 +- ..._rollups.sql => 029_analytics_rollups.sql} | 0 ...h.sql => 030_template_fulltext_search.sql} | 2 +- ...ql => 031_atomic_provider_connections.sql} | 0 ... => 032_cron_failure_atomic_increment.sql} | 0 ...=> 033_cron_job_failure_increment_rpc.sql} | 4 +-- ...> 034_provider_connections_atomic_rpc.sql} | 2 +- ...35_atomic_deployment_build_cache_hash.sql} | 0 ...ty.sql => 036_dlq_reprocess_atomicity.sql} | 0 ...ls.sql => 037_fix_auth_audit_logs_rls.sql} | 4 +-- ...rds.sql => 038_fee_bump_usage_records.sql} | 2 +- ...ent_idempotency_atomic_key_generation.sql} | 0 ...40_usage_records_atomic_increment_rpc.sql} | 2 +- .../tests/rls/auth-audit-logs-rls.test.ts | 2 +- .../tests/rls/policy-verification.test.ts | 4 +-- 52 files changed, 175 insertions(+), 24 deletions(-) create mode 100644 packages/stellar/src/stellar-asset.test.ts create mode 100644 packages/stellar/src/stellar-asset.ts create mode 100644 scripts/check-migration-numbering.js create mode 100644 scripts/check-migration-numbering.test.js rename supabase/migrations/{006_secure_token_storage.sql => 007_secure_token_storage.sql} (100%) rename supabase/migrations/{007_field_encryption_stripe.sql => 008_field_encryption_stripe.sql} (100%) rename supabase/migrations/{008_github_vercel_deployments.sql => 009_github_vercel_deployments.sql} (100%) rename supabase/migrations/{009_deployment_updates_rollout.sql => 010_deployment_updates_rollout.sql} (100%) rename supabase/migrations/{010_auth_audit_logs_cross_region.sql => 011_auth_audit_logs_cross_region.sql} (100%) rename supabase/migrations/{010_deployment_soft_delete.sql => 012_deployment_soft_delete.sql} (100%) rename supabase/migrations/{010_github_app_installations.sql => 013_github_app_installations.sql} (100%) rename supabase/migrations/{010_vercel_blue_green_aliases.sql => 014_vercel_blue_green_aliases.sql} (100%) rename supabase/migrations/{011_analytics_query_optimization.sql => 015_analytics_query_optimization.sql} (100%) rename supabase/migrations/{011_branding_asset_storage_policy.sql => 016_branding_asset_storage_policy.sql} (100%) rename supabase/migrations/{011_metered_billing_usage_tracking.sql => 017_metered_billing_usage_tracking.sql} (100%) rename supabase/migrations/{012_multi_provider_oauth.sql => 018_multi_provider_oauth.sql} (100%) rename supabase/migrations/{012_pgcron_automated_cleanup.sql => 019_pgcron_automated_cleanup.sql} (100%) rename supabase/migrations/{013_github_webhook_delivery_tracking.sql => 020_github_webhook_delivery_tracking.sql} (100%) rename supabase/migrations/{014_artifact_storage_namespace.sql => 021_artifact_storage_namespace.sql} (100%) rename supabase/migrations/{014_cron_checkpoints.sql => 022_cron_checkpoints.sql} (100%) rename supabase/migrations/{014_cron_job_failures.sql => 023_cron_job_failures.sql} (100%) rename supabase/migrations/{014_email_deliveries.sql => 024_email_deliveries.sql} (100%) rename supabase/migrations/{014_job_queue.sql => 025_job_queue.sql} (99%) rename supabase/migrations/{014_orphaned_artifact_cleanup_audit.sql => 026_orphaned_artifact_cleanup_audit.sql} (100%) rename supabase/migrations/{014_region_latency_cache.sql => 027_region_latency_cache.sql} (100%) rename supabase/migrations/{015_job_queue_claim_rpc.sql => 028_job_queue_claim_rpc.sql} (97%) rename supabase/migrations/{016_analytics_rollups.sql => 029_analytics_rollups.sql} (100%) rename supabase/migrations/{016_template_fulltext_search.sql => 030_template_fulltext_search.sql} (99%) rename supabase/migrations/{017_atomic_provider_connections.sql => 031_atomic_provider_connections.sql} (100%) rename supabase/migrations/{017_cron_failure_atomic_increment.sql => 032_cron_failure_atomic_increment.sql} (100%) rename supabase/migrations/{017_cron_job_failure_increment_rpc.sql => 033_cron_job_failure_increment_rpc.sql} (90%) rename supabase/migrations/{017_provider_connections_atomic_rpc.sql => 034_provider_connections_atomic_rpc.sql} (97%) rename supabase/migrations/{018_atomic_deployment_build_cache_hash.sql => 035_atomic_deployment_build_cache_hash.sql} (100%) rename supabase/migrations/{018_dlq_reprocess_atomicity.sql => 036_dlq_reprocess_atomicity.sql} (100%) rename supabase/migrations/{019_fix_auth_audit_logs_rls.sql => 037_fix_auth_audit_logs_rls.sql} (96%) rename supabase/migrations/{020_fee_bump_usage_records.sql => 038_fee_bump_usage_records.sql} (98%) rename supabase/migrations/{021_payment_idempotency_atomic_key_generation.sql => 039_payment_idempotency_atomic_key_generation.sql} (100%) rename supabase/migrations/{021_usage_records_atomic_increment_rpc.sql => 040_usage_records_atomic_increment_rpc.sql} (97%) diff --git a/apps/backend/src/lib/stellar/validate-asset-pairs.ts b/apps/backend/src/lib/stellar/validate-asset-pairs.ts index 1b454470..025938a7 100644 --- a/apps/backend/src/lib/stellar/validate-asset-pairs.ts +++ b/apps/backend/src/lib/stellar/validate-asset-pairs.ts @@ -16,6 +16,7 @@ import type { AssetPair, StellarAsset } from '@craft/types'; import type { ValidationError } from '@craft/types'; +import { makeStellarAsset } from '@craft/stellar'; // ── Constants ───────────────────────────────────────────────────────────────── @@ -153,7 +154,32 @@ export function validateAssetPairs(pairs: unknown): ValidationError[] { const pairHasAssetErrors = errors.some(e => e.field.startsWith(pairPrefix)); if (pairHasAssetErrors) continue; - const typedPair = pair as AssetPair; + const rawBase = p['base'] as Record; + const rawCounter = p['counter'] as Record; + const typedPair: AssetPair = { + base: rawBase['type'] === 'native' + ? { + type: 'native', + code: typeof rawBase['code'] === 'string' ? rawBase['code'] : 'XLM', + issuer: '', + } + : makeStellarAsset( + rawBase['type'] as StellarAsset['type'], + rawBase['code'] as string, + rawBase['issuer'] as string, + ), + counter: rawCounter['type'] === 'native' + ? { + type: 'native', + code: typeof rawCounter['code'] === 'string' ? rawCounter['code'] : 'XLM', + issuer: '', + } + : makeStellarAsset( + rawCounter['type'] as StellarAsset['type'], + rawCounter['code'] as string, + rawCounter['issuer'] as string, + ), + }; // Base and counter must differ if (assetKey(typedPair.base) === assetKey(typedPair.counter)) { diff --git a/apps/backend/src/services/github-app-installation.service.ts b/apps/backend/src/services/github-app-installation.service.ts index 43b2ff6e..33314faf 100644 --- a/apps/backend/src/services/github-app-installation.service.ts +++ b/apps/backend/src/services/github-app-installation.service.ts @@ -14,7 +14,7 @@ * via a non-atomic read-modify-write, so handleInstallationRepositoriesAdded * and handleInstallationRepositoriesRemoved use optimistic concurrency * control keyed on the row's `updated_at` (maintained by a DB trigger, - * see supabase/migrations/010_github_app_installations.sql): the update is + * see supabase/migrations/013_github_app_installations.sql): the update is * conditioned on `updated_at` still matching the value read, and a losing * writer retries against the freshly-read state instead of clobbering the * other handler's change. diff --git a/apps/backend/src/services/job-queue.service.ts b/apps/backend/src/services/job-queue.service.ts index 3a7a99f6..70d134cf 100644 --- a/apps/backend/src/services/job-queue.service.ts +++ b/apps/backend/src/services/job-queue.service.ts @@ -26,7 +26,7 @@ * * Persistence * ──────────── - * All state lives in Supabase (see migration 014_job_queue.sql), so jobs + * All state lives in Supabase (see migration 025_job_queue.sql), so jobs * survive server restarts automatically. * * Design doc properties satisfied: diff --git a/apps/backend/src/services/multi-provider-auth.service.test.ts b/apps/backend/src/services/multi-provider-auth.service.test.ts index e4681eec..b0295ae4 100644 --- a/apps/backend/src/services/multi-provider-auth.service.test.ts +++ b/apps/backend/src/services/multi-provider-auth.service.test.ts @@ -101,7 +101,7 @@ describe('MultiProviderAuthService', () => { // provider_connections, merge in memory, then write the whole object // back — a race between two concurrent requests could silently drop // one side's change. The merge now happens inside a single row-locked - // Postgres function (see supabase/migrations/017_provider_connections_atomic_rpc.sql), + // Postgres function (see supabase/migrations/034_provider_connections_atomic_rpc.sql), // so the client only ever sends its own provider's value, never a // merged snapshot of the whole column. const supabase = makeSupabase({ provider_connections: { someOther: { data: 'value' } } }); diff --git a/apps/backend/src/services/template.service.ts b/apps/backend/src/services/template.service.ts index 3cc4dd8c..d8fbd45b 100644 --- a/apps/backend/src/services/template.service.ts +++ b/apps/backend/src/services/template.service.ts @@ -5,7 +5,7 @@ * * Full-text search (searchTemplates / listTemplates with `q` filter): * - Backed by a Postgres tsvector column on name (weight A), tags (weight B), - * and description (weight C) — see migration 016_template_fulltext_search.sql. + * and description (weight C) — see migration 030_template_fulltext_search.sql. * - Results are ranked by ts_rank (most relevant first). * - Supports: keyword search, phrase search ("liquidity pool"), * prefix search (decentral:*), and category filter combined with text search. diff --git a/apps/backend/src/services/webhook-delivery.service.ts b/apps/backend/src/services/webhook-delivery.service.ts index d5392944..193f8e6f 100644 --- a/apps/backend/src/services/webhook-delivery.service.ts +++ b/apps/backend/src/services/webhook-delivery.service.ts @@ -12,7 +12,7 @@ * - Support replay of failed or missed deliveries * - Query deliveries for monitoring and troubleshooting * - * Database schema: supabase/migrations/013_github_webhook_delivery_tracking.sql + * Database schema: supabase/migrations/020_github_webhook_delivery_tracking.sql */ import { createClient } from '@/lib/supabase/server'; diff --git a/docs/admin-ops-dlq.md b/docs/admin-ops-dlq.md index 0db88874..f17a9fa2 100644 --- a/docs/admin-ops-dlq.md +++ b/docs/admin-ops-dlq.md @@ -82,7 +82,7 @@ operators discover the combined view. ``` apps/backend/src/services/job-queue.service.ts (class JobQueueService) -supabase/migrations/014_job_queue.sql (schema) +supabase/migrations/025_job_queue.sql (schema) ``` ### What goes in diff --git a/docs/cross-region-deployment-guide.md b/docs/cross-region-deployment-guide.md index f68794c3..69661386 100644 --- a/docs/cross-region-deployment-guide.md +++ b/docs/cross-region-deployment-guide.md @@ -74,7 +74,7 @@ Or use the SQL migration directly: ```bash # For each region's Supabase project: -psql -h your-region.db.supabase.co -U postgres -d postgres < supabase/migrations/010_auth_audit_logs_cross_region.sql +psql -h your-region.db.supabase.co -U postgres -d postgres < supabase/migrations/011_auth_audit_logs_cross_region.sql ``` ### Step 3: Deploy Edge Functions diff --git a/docs/github-vercel-deployment-triggering.md b/docs/github-vercel-deployment-triggering.md index 87985bbd..7fcd672b 100644 --- a/docs/github-vercel-deployment-triggering.md +++ b/docs/github-vercel-deployment-triggering.md @@ -408,4 +408,4 @@ Logs are structured JSON and can be shipped to your log aggregation service. - `apps/backend/src/lib/github/webhook-verification.ts` - Signature verification - `apps/backend/src/services/github-to-vercel-deployment.service.ts` - Deployment service - `apps/backend/src/services/vercel.service.ts` - Vercel API client -- `supabase/migrations/008_github_vercel_deployments.sql` - Database schema +- `supabase/migrations/009_github_vercel_deployments.sql` - Database schema diff --git a/package.json b/package.json index 91ecc15c..57824271 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "scripts": { "dev": "turbo run dev --filter=@craft/frontend --filter=@craft/backend", "build": "turbo run build", - "test": "turbo run test", - "lint": "turbo run lint", + "test": "node --test scripts/check-migration-numbering.test.js && turbo run test", + "lint": "node scripts/check-migration-numbering.js && turbo run lint", "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, "devDependencies": { diff --git a/packages/stellar/src/index.ts b/packages/stellar/src/index.ts index ef7fd580..b02c5325 100644 --- a/packages/stellar/src/index.ts +++ b/packages/stellar/src/index.ts @@ -18,3 +18,4 @@ export * from './account-merge-protection'; export * from './asset-compliance'; export * from './circuit-breaker'; export * from './horizon-client'; +export * from './stellar-asset'; diff --git a/packages/stellar/src/stellar-asset.test.ts b/packages/stellar/src/stellar-asset.test.ts new file mode 100644 index 00000000..b0bcce08 --- /dev/null +++ b/packages/stellar/src/stellar-asset.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'vitest'; +import { makeStellarAsset } from './stellar-asset'; + +describe('makeStellarAsset', () => { + it('constructs valid native and credit assets', () => { + expect(makeStellarAsset('native', 'XLM', '')).toEqual({ type: 'native', code: 'XLM', issuer: '' }); + expect(makeStellarAsset('credit_alphanum4', 'USDC', 'GISSUER')).toEqual({ + type: 'credit_alphanum4', code: 'USDC', issuer: 'GISSUER', + }); + expect(makeStellarAsset('credit_alphanum12', 'LONGCOIN', 'GISSUER')).toEqual({ + type: 'credit_alphanum12', code: 'LONGCOIN', issuer: 'GISSUER', + }); + }); + + it('rejects a code/type length mismatch with a clear error', () => { + expect(() => makeStellarAsset('credit_alphanum4', 'TOOLONG', 'GISSUER')) + .toThrow('credit_alphanum4 asset codes must be 1-4 characters.'); + expect(() => makeStellarAsset('credit_alphanum12', 'USDC', 'GISSUER')) + .toThrow('credit_alphanum12 asset codes must be 5-12 characters.'); + }); +}); \ No newline at end of file diff --git a/packages/stellar/src/stellar-asset.ts b/packages/stellar/src/stellar-asset.ts new file mode 100644 index 00000000..f6b8207e --- /dev/null +++ b/packages/stellar/src/stellar-asset.ts @@ -0,0 +1,31 @@ +import type { StellarAsset, StellarAssetType } from '@craft/types'; + +/** Create a Stellar asset after enforcing its code/type length invariant. */ +export function makeStellarAsset( + type: StellarAssetType, + code: string, + issuer: string, +): StellarAsset { + if (type !== 'native' && type !== 'credit_alphanum4' && type !== 'credit_alphanum12') { + throw new Error('Stellar asset type must be native, credit_alphanum4, or credit_alphanum12.'); + } + + if (type === 'native') { + if (code !== 'XLM' || issuer !== '') { + throw new Error('A native Stellar asset must use code XLM and an empty issuer.'); + } + return { type, code, issuer }; + } + + if (!/^[A-Z0-9]{1,12}$/.test(code)) { + throw new Error('A credit Stellar asset code must be 1-12 uppercase alphanumeric characters.'); + } + if (type === 'credit_alphanum4' && code.length > 4) { + throw new Error('credit_alphanum4 asset codes must be 1-4 characters.'); + } + if (type === 'credit_alphanum12' && code.length < 5) { + throw new Error('credit_alphanum12 asset codes must be 5-12 characters.'); + } + + return { type, code, issuer }; +} \ No newline at end of file diff --git a/packages/stellar/src/upgrade-orchestrator.test.ts b/packages/stellar/src/upgrade-orchestrator.test.ts index 1832bf64..cece2ee7 100644 --- a/packages/stellar/src/upgrade-orchestrator.test.ts +++ b/packages/stellar/src/upgrade-orchestrator.test.ts @@ -3,6 +3,7 @@ import type { ContractAbiSchema } from './upgrade-orchestrator'; const mocks = vi.hoisted(() => ({ mockSimulate: vi.fn(), + mockSubmitTransaction: vi.fn(), mockFromXDR: vi.fn(), })); @@ -26,6 +27,7 @@ vi.mock('stellar-sdk', () => ({ vi.mock('./soroban', () => ({ createSorobanClient: vi.fn(() => ({ simulateTransaction: mocks.mockSimulate, + sendTransaction: mocks.mockSubmitTransaction, })), })); @@ -351,6 +353,8 @@ describe('orchestrateContractUpgrade', () => { expect(result.dryRun).toBe(false); expect(result.diffReport.safe).toBe(true); } + expect(mocks.mockSimulate).not.toHaveBeenCalled(); + expect(mocks.mockSubmitTransaction).not.toHaveBeenCalled(); }); it('blocks upgrade when breaking changes are detected', async () => { @@ -417,6 +421,7 @@ describe('orchestrateContractUpgrade', () => { 'Test SDF Network ; September 2015', ); expect(mocks.mockSimulate).toHaveBeenCalledWith(mockTx); + expect(mocks.mockSubmitTransaction).not.toHaveBeenCalled(); }); it('handles simulation errors gracefully', async () => { diff --git a/scripts/check-migration-numbering.js b/scripts/check-migration-numbering.js new file mode 100644 index 00000000..1d274b77 --- /dev/null +++ b/scripts/check-migration-numbering.js @@ -0,0 +1,32 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +function findDuplicateMigrationPrefixes(directory) { + const migrations = new Map(); + for (const filename of fs.readdirSync(directory)) { + const match = /^(\d+)_.*\.sql$/.exec(filename); + if (!match) continue; + const files = migrations.get(match[1]) ?? []; + files.push(filename); + migrations.set(match[1], files); + } + return [...migrations.entries()].filter(([, files]) => files.length > 1); +} + +function checkMigrationNumbering(directory) { + const duplicates = findDuplicateMigrationPrefixes(directory); + if (duplicates.length === 0) return true; + + console.error('Duplicate Supabase migration number prefixes:'); + for (const [prefix, files] of duplicates) { + console.error(` ${prefix}: ${files.join(', ')}`); + } + return false; +} + +if (require.main === module) { + const migrationDirectory = path.join(__dirname, '..', 'supabase', 'migrations'); + if (!checkMigrationNumbering(migrationDirectory)) process.exitCode = 1; +} + +module.exports = { checkMigrationNumbering, findDuplicateMigrationPrefixes }; \ No newline at end of file diff --git a/scripts/check-migration-numbering.test.js b/scripts/check-migration-numbering.test.js new file mode 100644 index 00000000..8679a136 --- /dev/null +++ b/scripts/check-migration-numbering.test.js @@ -0,0 +1,35 @@ +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); +const { afterEach, describe, it } = require('node:test'); +const assert = require('node:assert/strict'); +const { findDuplicateMigrationPrefixes } = require('./check-migration-numbering'); + +const fixtureDirectories = []; + +function makeFixture(filenames) { + const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'migration-numbering-')); + fixtureDirectories.push(directory); + for (const filename of filenames) fs.writeFileSync(path.join(directory, filename), ''); + return directory; +} + +afterEach(() => { + for (const directory of fixtureDirectories.splice(0)) { + fs.rmSync(directory, { recursive: true, force: true }); + } +}); + +describe('findDuplicateMigrationPrefixes', () => { + it('returns no groups when migration numbers are unique', () => { + const directory = makeFixture(['001_initial.sql', '002_next.sql']); + assert.deepEqual(findDuplicateMigrationPrefixes(directory), []); + }); + + it('lists every file in each duplicate prefix group', () => { + const directory = makeFixture(['014_first.sql', '014_second.sql', '015_next.sql']); + assert.deepEqual(findDuplicateMigrationPrefixes(directory), [ + ['014', ['014_first.sql', '014_second.sql']], + ]); + }); +}); \ No newline at end of file diff --git a/supabase/migrations/006_secure_token_storage.sql b/supabase/migrations/007_secure_token_storage.sql similarity index 100% rename from supabase/migrations/006_secure_token_storage.sql rename to supabase/migrations/007_secure_token_storage.sql diff --git a/supabase/migrations/007_field_encryption_stripe.sql b/supabase/migrations/008_field_encryption_stripe.sql similarity index 100% rename from supabase/migrations/007_field_encryption_stripe.sql rename to supabase/migrations/008_field_encryption_stripe.sql diff --git a/supabase/migrations/008_github_vercel_deployments.sql b/supabase/migrations/009_github_vercel_deployments.sql similarity index 100% rename from supabase/migrations/008_github_vercel_deployments.sql rename to supabase/migrations/009_github_vercel_deployments.sql diff --git a/supabase/migrations/009_deployment_updates_rollout.sql b/supabase/migrations/010_deployment_updates_rollout.sql similarity index 100% rename from supabase/migrations/009_deployment_updates_rollout.sql rename to supabase/migrations/010_deployment_updates_rollout.sql diff --git a/supabase/migrations/010_auth_audit_logs_cross_region.sql b/supabase/migrations/011_auth_audit_logs_cross_region.sql similarity index 100% rename from supabase/migrations/010_auth_audit_logs_cross_region.sql rename to supabase/migrations/011_auth_audit_logs_cross_region.sql diff --git a/supabase/migrations/010_deployment_soft_delete.sql b/supabase/migrations/012_deployment_soft_delete.sql similarity index 100% rename from supabase/migrations/010_deployment_soft_delete.sql rename to supabase/migrations/012_deployment_soft_delete.sql diff --git a/supabase/migrations/010_github_app_installations.sql b/supabase/migrations/013_github_app_installations.sql similarity index 100% rename from supabase/migrations/010_github_app_installations.sql rename to supabase/migrations/013_github_app_installations.sql diff --git a/supabase/migrations/010_vercel_blue_green_aliases.sql b/supabase/migrations/014_vercel_blue_green_aliases.sql similarity index 100% rename from supabase/migrations/010_vercel_blue_green_aliases.sql rename to supabase/migrations/014_vercel_blue_green_aliases.sql diff --git a/supabase/migrations/011_analytics_query_optimization.sql b/supabase/migrations/015_analytics_query_optimization.sql similarity index 100% rename from supabase/migrations/011_analytics_query_optimization.sql rename to supabase/migrations/015_analytics_query_optimization.sql diff --git a/supabase/migrations/011_branding_asset_storage_policy.sql b/supabase/migrations/016_branding_asset_storage_policy.sql similarity index 100% rename from supabase/migrations/011_branding_asset_storage_policy.sql rename to supabase/migrations/016_branding_asset_storage_policy.sql diff --git a/supabase/migrations/011_metered_billing_usage_tracking.sql b/supabase/migrations/017_metered_billing_usage_tracking.sql similarity index 100% rename from supabase/migrations/011_metered_billing_usage_tracking.sql rename to supabase/migrations/017_metered_billing_usage_tracking.sql diff --git a/supabase/migrations/012_multi_provider_oauth.sql b/supabase/migrations/018_multi_provider_oauth.sql similarity index 100% rename from supabase/migrations/012_multi_provider_oauth.sql rename to supabase/migrations/018_multi_provider_oauth.sql diff --git a/supabase/migrations/012_pgcron_automated_cleanup.sql b/supabase/migrations/019_pgcron_automated_cleanup.sql similarity index 100% rename from supabase/migrations/012_pgcron_automated_cleanup.sql rename to supabase/migrations/019_pgcron_automated_cleanup.sql diff --git a/supabase/migrations/013_github_webhook_delivery_tracking.sql b/supabase/migrations/020_github_webhook_delivery_tracking.sql similarity index 100% rename from supabase/migrations/013_github_webhook_delivery_tracking.sql rename to supabase/migrations/020_github_webhook_delivery_tracking.sql diff --git a/supabase/migrations/014_artifact_storage_namespace.sql b/supabase/migrations/021_artifact_storage_namespace.sql similarity index 100% rename from supabase/migrations/014_artifact_storage_namespace.sql rename to supabase/migrations/021_artifact_storage_namespace.sql diff --git a/supabase/migrations/014_cron_checkpoints.sql b/supabase/migrations/022_cron_checkpoints.sql similarity index 100% rename from supabase/migrations/014_cron_checkpoints.sql rename to supabase/migrations/022_cron_checkpoints.sql diff --git a/supabase/migrations/014_cron_job_failures.sql b/supabase/migrations/023_cron_job_failures.sql similarity index 100% rename from supabase/migrations/014_cron_job_failures.sql rename to supabase/migrations/023_cron_job_failures.sql diff --git a/supabase/migrations/014_email_deliveries.sql b/supabase/migrations/024_email_deliveries.sql similarity index 100% rename from supabase/migrations/014_email_deliveries.sql rename to supabase/migrations/024_email_deliveries.sql diff --git a/supabase/migrations/014_job_queue.sql b/supabase/migrations/025_job_queue.sql similarity index 99% rename from supabase/migrations/014_job_queue.sql rename to supabase/migrations/025_job_queue.sql index d57a2bbe..bf6fc26b 100644 --- a/supabase/migrations/014_job_queue.sql +++ b/supabase/migrations/025_job_queue.sql @@ -1,4 +1,4 @@ --- Migration: 014_job_queue.sql +-- Migration: 025_job_queue.sql -- Creates the job_queue table for background deployment processing with -- priority lanes (high / normal / low) and dead-letter escalation after -- MAX_ATTEMPTS failures. diff --git a/supabase/migrations/014_orphaned_artifact_cleanup_audit.sql b/supabase/migrations/026_orphaned_artifact_cleanup_audit.sql similarity index 100% rename from supabase/migrations/014_orphaned_artifact_cleanup_audit.sql rename to supabase/migrations/026_orphaned_artifact_cleanup_audit.sql diff --git a/supabase/migrations/014_region_latency_cache.sql b/supabase/migrations/027_region_latency_cache.sql similarity index 100% rename from supabase/migrations/014_region_latency_cache.sql rename to supabase/migrations/027_region_latency_cache.sql diff --git a/supabase/migrations/015_job_queue_claim_rpc.sql b/supabase/migrations/028_job_queue_claim_rpc.sql similarity index 97% rename from supabase/migrations/015_job_queue_claim_rpc.sql rename to supabase/migrations/028_job_queue_claim_rpc.sql index e3684714..7c10c3ac 100644 --- a/supabase/migrations/015_job_queue_claim_rpc.sql +++ b/supabase/migrations/028_job_queue_claim_rpc.sql @@ -1,4 +1,4 @@ --- Migration: 015_job_queue_claim_rpc.sql +-- Migration: 028_job_queue_claim_rpc.sql -- Atomic "claim next job" function used by workers to avoid double-processing. -- -- Priority mapping (CASE → integer) keeps ordering deterministic: diff --git a/supabase/migrations/016_analytics_rollups.sql b/supabase/migrations/029_analytics_rollups.sql similarity index 100% rename from supabase/migrations/016_analytics_rollups.sql rename to supabase/migrations/029_analytics_rollups.sql diff --git a/supabase/migrations/016_template_fulltext_search.sql b/supabase/migrations/030_template_fulltext_search.sql similarity index 99% rename from supabase/migrations/016_template_fulltext_search.sql rename to supabase/migrations/030_template_fulltext_search.sql index 37a9609c..d9df9a91 100644 --- a/supabase/migrations/016_template_fulltext_search.sql +++ b/supabase/migrations/030_template_fulltext_search.sql @@ -1,4 +1,4 @@ --- Migration: 016_template_fulltext_search.sql +-- Migration: 030_template_fulltext_search.sql -- -- Adds full-text search to the templates table via: -- 1. A `tags` TEXT[] column for keyword tagging diff --git a/supabase/migrations/017_atomic_provider_connections.sql b/supabase/migrations/031_atomic_provider_connections.sql similarity index 100% rename from supabase/migrations/017_atomic_provider_connections.sql rename to supabase/migrations/031_atomic_provider_connections.sql diff --git a/supabase/migrations/017_cron_failure_atomic_increment.sql b/supabase/migrations/032_cron_failure_atomic_increment.sql similarity index 100% rename from supabase/migrations/017_cron_failure_atomic_increment.sql rename to supabase/migrations/032_cron_failure_atomic_increment.sql diff --git a/supabase/migrations/017_cron_job_failure_increment_rpc.sql b/supabase/migrations/033_cron_job_failure_increment_rpc.sql similarity index 90% rename from supabase/migrations/017_cron_job_failure_increment_rpc.sql rename to supabase/migrations/033_cron_job_failure_increment_rpc.sql index c3cff161..5f8368ba 100644 --- a/supabase/migrations/017_cron_job_failure_increment_rpc.sql +++ b/supabase/migrations/033_cron_job_failure_increment_rpc.sql @@ -1,4 +1,4 @@ --- Migration: 017_cron_job_failure_increment_rpc.sql +-- Migration: 033_cron_job_failure_increment_rpc.sql -- Atomic increment function for cron_job_failures.consecutive_failures. -- Replaces the read-then-upsert pattern that could lose increments under -- concurrent calls (see issue #986). @@ -28,5 +28,5 @@ BEGIN END; $$; --- Grant execute to the service role only (matches 015_job_queue_claim_rpc.sql pattern) +-- Grant execute to the service role only (matches 028_job_queue_claim_rpc.sql pattern) GRANT EXECUTE ON FUNCTION increment_cron_failure(TEXT, TEXT) TO service_role; diff --git a/supabase/migrations/017_provider_connections_atomic_rpc.sql b/supabase/migrations/034_provider_connections_atomic_rpc.sql similarity index 97% rename from supabase/migrations/017_provider_connections_atomic_rpc.sql rename to supabase/migrations/034_provider_connections_atomic_rpc.sql index 5540b2ac..d1d9ef61 100644 --- a/supabase/migrations/017_provider_connections_atomic_rpc.sql +++ b/supabase/migrations/034_provider_connections_atomic_rpc.sql @@ -1,4 +1,4 @@ --- Migration: 017_provider_connections_atomic_rpc.sql +-- Migration: 034_provider_connections_atomic_rpc.sql -- Atomic read-modify-write for profiles.provider_connections. -- -- MultiProviderAuthService.connectStellar()/disconnectProvider() previously diff --git a/supabase/migrations/018_atomic_deployment_build_cache_hash.sql b/supabase/migrations/035_atomic_deployment_build_cache_hash.sql similarity index 100% rename from supabase/migrations/018_atomic_deployment_build_cache_hash.sql rename to supabase/migrations/035_atomic_deployment_build_cache_hash.sql diff --git a/supabase/migrations/018_dlq_reprocess_atomicity.sql b/supabase/migrations/036_dlq_reprocess_atomicity.sql similarity index 100% rename from supabase/migrations/018_dlq_reprocess_atomicity.sql rename to supabase/migrations/036_dlq_reprocess_atomicity.sql diff --git a/supabase/migrations/019_fix_auth_audit_logs_rls.sql b/supabase/migrations/037_fix_auth_audit_logs_rls.sql similarity index 96% rename from supabase/migrations/019_fix_auth_audit_logs_rls.sql rename to supabase/migrations/037_fix_auth_audit_logs_rls.sql index 1983d483..710bddc4 100644 --- a/supabase/migrations/019_fix_auth_audit_logs_rls.sql +++ b/supabase/migrations/037_fix_auth_audit_logs_rls.sql @@ -1,8 +1,8 @@ --- Migration: 019_fix_auth_audit_logs_rls.sql +-- Migration: 037_fix_auth_audit_logs_rls.sql -- Issue: #975 — Close RLS Blanket-Read Gap on Cross-Region auth_audit_logs -- -- Problem: --- The SELECT policy created in 010_auth_audit_logs_cross_region.sql contained +-- The SELECT policy created in 011_auth_audit_logs_cross_region.sql contained -- a second OR clause: -- -- EXISTS ( diff --git a/supabase/migrations/020_fee_bump_usage_records.sql b/supabase/migrations/038_fee_bump_usage_records.sql similarity index 98% rename from supabase/migrations/020_fee_bump_usage_records.sql rename to supabase/migrations/038_fee_bump_usage_records.sql index a484de90..f638fd2e 100644 --- a/supabase/migrations/020_fee_bump_usage_records.sql +++ b/supabase/migrations/038_fee_bump_usage_records.sql @@ -1,4 +1,4 @@ --- Migration: 020_fee_bump_usage_records.sql +-- Migration: 038_fee_bump_usage_records.sql -- Issue: #1111 — Persist Fee-Bump Usage Records So a Restart Cannot Silently -- Reset Monthly Billing Counters -- diff --git a/supabase/migrations/021_payment_idempotency_atomic_key_generation.sql b/supabase/migrations/039_payment_idempotency_atomic_key_generation.sql similarity index 100% rename from supabase/migrations/021_payment_idempotency_atomic_key_generation.sql rename to supabase/migrations/039_payment_idempotency_atomic_key_generation.sql diff --git a/supabase/migrations/021_usage_records_atomic_increment_rpc.sql b/supabase/migrations/040_usage_records_atomic_increment_rpc.sql similarity index 97% rename from supabase/migrations/021_usage_records_atomic_increment_rpc.sql rename to supabase/migrations/040_usage_records_atomic_increment_rpc.sql index ddcc6488..ff99e438 100644 --- a/supabase/migrations/021_usage_records_atomic_increment_rpc.sql +++ b/supabase/migrations/040_usage_records_atomic_increment_rpc.sql @@ -1,4 +1,4 @@ --- Migration: 021_usage_records_atomic_increment_rpc.sql +-- Migration: 040_usage_records_atomic_increment_rpc.sql -- Atomic increment RPC for usage_records.idempotency_key conflicts. -- Prevents the lost-update race when two concurrent calls hit the same -- (user_id, operation_type) within the same second. diff --git a/supabase/tests/rls/auth-audit-logs-rls.test.ts b/supabase/tests/rls/auth-audit-logs-rls.test.ts index 734d4976..b9dc1eb9 100644 --- a/supabase/tests/rls/auth-audit-logs-rls.test.ts +++ b/supabase/tests/rls/auth-audit-logs-rls.test.ts @@ -1,7 +1,7 @@ /** * RLS Tests — auth_audit_logs policy fix (Issue #975) * - * Verifies that migration 019_fix_auth_audit_logs_rls.sql correctly scopes + * Verifies that migration 037_fix_auth_audit_logs_rls.sql correctly scopes * the SELECT policy to the row owner and service_role only. * * The bug: the old policy granted SELECT when the *requester's* profile had diff --git a/supabase/tests/rls/policy-verification.test.ts b/supabase/tests/rls/policy-verification.test.ts index 92d934ca..16299607 100644 --- a/supabase/tests/rls/policy-verification.test.ts +++ b/supabase/tests/rls/policy-verification.test.ts @@ -544,7 +544,7 @@ describe('RLS: payment_events — per-user direct-identity SELECT', () => { describe('RLS: audit_logs (auth_audit_logs) — per-user SELECT with tier expansion', () => { /** - * Policy from migration 010_auth_audit_logs_cross_region.sql: + * Policy from migration 011_auth_audit_logs_cross_region.sql: * FOR SELECT USING ( * auth.uid() = user_id OR * EXISTS (SELECT 1 FROM profiles WHERE profiles.id = auth.uid() @@ -604,7 +604,7 @@ describe('RLS: audit_logs (auth_audit_logs) — per-user SELECT with tier expans describe('RLS: branding_assets (storage.objects) — path-based user namespace', () => { /** - * Policy from migration 011_branding_asset_storage_policy.sql: + * Policy from migration 016_branding_asset_storage_policy.sql: * INSERT WITH CHECK: bucket_id = 'branding_assets' AND foldername(name)[1] = auth.uid() * SELECT USING: bucket_id = 'branding_assets' AND foldername(name)[1] = auth.uid() *