refactor(backend): root scripts use legacySupabase client where possible

- Call loadDynamicConfig() without dead supabaseService argument (Cosmos-backed).
- Use getLegacySupabaseClient() for raw .from() queries in maintenance scripts.
- manualOverrideCloseTrades: typed imports + legacy client for lifecycle SELECT.
- verify_realtime: ESM .js imports and comment for subscribeToProfiles.
- verifyTenantIsolation: comment for singleton monkey-patch.

Made-with: Cursor
This commit is contained in:
Saravana Achu Mac 2026-04-04 20:44:24 -07:00
parent eb70ef6c03
commit 6fac10de9d
17 changed files with 97 additions and 42 deletions

View File

@ -1,5 +1,5 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
@ -7,6 +7,12 @@ import path from 'path';
async function applyStandardRiskProfiles() { async function applyStandardRiskProfiles() {
logger.info('🚀 APPLYING STANDARD RISK PROFILES (5 TO 1)...'); logger.info('🚀 APPLYING STANDARD RISK PROFILES (5 TO 1)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Load Data // 1. Load Data
const proposedPath = path.resolve('schema/proposed_risk_profiles.json'); const proposedPath = path.resolve('schema/proposed_risk_profiles.json');
if (!fs.existsSync(proposedPath)) { if (!fs.existsSync(proposedPath)) {
@ -27,17 +33,17 @@ async function applyStandardRiskProfiles() {
logger.info('🧹 Wiping existing data for a fresh start...'); logger.info('🧹 Wiping existing data for a fresh start...');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('positions').delete().neq('id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('positions').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('orders').delete().neq('id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('orders').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('trade_history').delete().neq('id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('trade_history').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('alerts').delete().neq('id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('alerts').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('operational_events').delete().neq('id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('operational_events').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('trade_profiles').delete().neq('user_id', '00000000-0000-0000-0000-000000000000'); await legacyClient.from('trade_profiles').delete().neq('user_id', '00000000-0000-0000-0000-000000000000');
// 4. Prepare & Insert Profiles // 4. Prepare & Insert Profiles
const insertPayload = Object.values(proposedProfiles).map((p: any) => { const insertPayload = Object.values(proposedProfiles).map((p: any) => {
@ -57,7 +63,7 @@ async function applyStandardRiskProfiles() {
}); });
// @ts-ignore // @ts-ignore
const { data, error } = await supabaseService.client const { data, error } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.insert(insertPayload); .insert(insertPayload);

View File

@ -1,9 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function createAggressiveProfile() { async function createAggressiveProfile() {
logger.info('🚀 CREATING AGGRESSIVE TEST PROFILE (70% VOTING)...'); logger.info('🚀 CREATING AGGRESSIVE TEST PROFILE (70% VOTING)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get User // 1. Get User
const users = await supabaseService.getActiveUsers(); const users = await supabaseService.getActiveUsers();
if (users.length === 0) { if (users.length === 0) {
@ -46,7 +53,7 @@ async function createAggressiveProfile() {
// 3. Insert Profile // 3. Insert Profile
// @ts-ignore // @ts-ignore
const { data, error } = await supabaseService.client const { data, error } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.insert([aggressiveProfile]) .insert([aggressiveProfile])
.select() .select()

View File

@ -1,11 +1,17 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
async function createLowRiskProfile() { async function createLowRiskProfile() {
logger.info('🛡️ CREATING LOW RISK & SCALP PROFILES EXAMPLE...'); logger.info('🛡️ CREATING LOW RISK & SCALP PROFILES EXAMPLE...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get User // 1. Get User
const users = await supabaseService.getActiveUsers(); const users = await supabaseService.getActiveUsers();
if (users.length === 0) { if (users.length === 0) {
@ -43,7 +49,7 @@ async function createLowRiskProfile() {
// Insert Low Risk Profile // Insert Low Risk Profile
// @ts-ignore // @ts-ignore
const { data, error } = await supabaseService.client const { data, error } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.insert([lowRiskProfile]) .insert([lowRiskProfile])
.select() .select()

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function debugDatabaseLogging() { async function debugDatabaseLogging() {
logger.info('🔍 Starting Database Logging Debug...'); logger.info('🔍 Starting Database Logging Debug...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('Legacy Supabase client not configured.');
return;
}
// 1. Get Real User & Profile // 1. Get Real User & Profile
const profiles = await supabaseService.getActiveProfiles(); const profiles = await supabaseService.getActiveProfiles();
if (profiles.length === 0) { if (profiles.length === 0) {
@ -35,7 +41,7 @@ async function debugDatabaseLogging() {
// Call private client directly to get full error if service swallows it // Call private client directly to get full error if service swallows it
// @ts-ignore // @ts-ignore
const { data: orderData, error: orderError } = await supabaseService.client const { data: orderData, error: orderError } = await legacyClient
.from('orders') .from('orders')
.insert([testOrder]) .insert([testOrder])
.select(); .select();
@ -65,7 +71,7 @@ async function debugDatabaseLogging() {
logger.info('📝 Attempting to insert Trade History:', testTrade); logger.info('📝 Attempting to insert Trade History:', testTrade);
// @ts-ignore // @ts-ignore
const { data: tradeData, error: tradeError } = await supabaseService.client const { data: tradeData, error: tradeError } = await legacyClient
.from('trade_history') .from('trade_history')
.insert([testTrade]) .insert([testTrade])
.select(); .select();
@ -79,7 +85,7 @@ async function debugDatabaseLogging() {
// Cleanup (Consistency) // Cleanup (Consistency)
logger.info('🧹 Cleaning up test data...'); logger.info('🧹 Cleaning up test data...');
// @ts-ignore // @ts-ignore
await supabaseService.client.from('orders').delete().eq('order_id', testOrder.order_id); await legacyClient.from('orders').delete().eq('order_id', testOrder.order_id);
} }
} }

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function fixHighRiskRules() { async function fixHighRiskRules() {
logger.info('🔧 Syncing High Risk Rules with Dashboard UI...'); logger.info('🔧 Syncing High Risk Rules with Dashboard UI...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles(); const profiles = await supabaseService.getActiveProfiles();
const highRiskProfile = profiles.find(p => p.name.includes('Scalp')); const highRiskProfile = profiles.find(p => p.name.includes('Scalp'));
@ -21,7 +27,7 @@ async function fixHighRiskRules() {
]; ];
// @ts-ignore // @ts-ignore
const { error } = await supabaseService.client const { error } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.update({ .update({
strategy_config: { strategy_config: {

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function forceResetRules() { async function forceResetRules() {
logger.info('🔨 FORCING CLEAN RULE SET (ALL RULES POPULATED)...'); logger.info('🔨 FORCING CLEAN RULE SET (ALL RULES POPULATED)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles(); const profiles = await supabaseService.getActiveProfiles();
const highRiskStart = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High')); const highRiskStart = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High'));
@ -27,7 +33,7 @@ async function forceResetRules() {
}; };
// @ts-ignore // @ts-ignore
const { error } = await supabaseService.client const { error } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.update({ strategy_config: newConfig }) .update({ strategy_config: newConfig })
.eq('id', highRiskStart.id); .eq('id', highRiskStart.id);

View File

@ -4,10 +4,11 @@ import { config, loadDynamicConfig } from '../src/config/index.js';
import { normalizeOrderAction, normalizeTradeSide } from '../src/domain/tradingEnums.js'; import { normalizeOrderAction, normalizeTradeSide } from '../src/domain/tradingEnums.js';
import { healthTracker } from '../src/services/healthTracker.js'; import { healthTracker } from '../src/services/healthTracker.js';
import { import {
ReconciliationBackfillAuditInsert, type ReconciliationBackfillAuditInsert,
ReconciliationBackfillOrderInsert, type ReconciliationBackfillOrderInsert,
supabaseService supabaseService
} from '../src/services/SupabaseService.js'; } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import { buildAlpacaSubTag } from '../src/utils/alpacaSubTag.js'; import { buildAlpacaSubTag } from '../src/utils/alpacaSubTag.js';
type CliOptions = { type CliOptions = {
@ -135,7 +136,7 @@ const run = async (): Promise<void> => {
throw new Error('Provide at least one --trade=<TRADE_ID>.'); throw new Error('Provide at least one --trade=<TRADE_ID>.');
} }
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
healthTracker.recordTradingControl({ healthTracker.recordTradingControl({
mode: 'PAUSED', mode: 'PAUSED',
@ -144,7 +145,7 @@ const run = async (): Promise<void> => {
reason: 'Manual override close cycle' reason: 'Manual override close cycle'
}); });
const client = supabaseService.getClient(); const client = getLegacySupabaseClient();
if (!client) { if (!client) {
throw new Error('Supabase client is not available.'); throw new Error('Supabase client is not available.');
} }

View File

@ -65,7 +65,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => { const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2)); const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
const originalDryRun = config.RECON_EXIT_BACKFILL_DRY_RUN; const originalDryRun = config.RECON_EXIT_BACKFILL_DRY_RUN;
const originalAllowlist = [...config.RECON_EXIT_BACKFILL_PROFILE_ALLOWLIST]; const originalAllowlist = [...config.RECON_EXIT_BACKFILL_PROFILE_ALLOWLIST];

View File

@ -96,7 +96,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => { const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2)); const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
const originalEnabled = config.ENABLE_RECON_ORDER_COVERAGE_SYNC; const originalEnabled = config.ENABLE_RECON_ORDER_COVERAGE_SYNC;
const originalDryRun = config.RECON_ORDER_COVERAGE_DRY_RUN; const originalDryRun = config.RECON_ORDER_COVERAGE_DRY_RUN;

View File

@ -186,7 +186,7 @@ const normalizeExchangeEvidence = (rows: any[]): Map<string, ExchangeEvidence> =
const run = async (): Promise<void> => { const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2)); const options = parseOptions(process.argv.slice(2));
logger.silent = true; logger.silent = true;
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
healthTracker.recordTradingControl({ healthTracker.recordTradingControl({
mode: 'PAUSED', mode: 'PAUSED',

View File

@ -71,7 +71,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => { const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2)); const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
const originalEnabled = config.ENABLE_RECON_SUBTAG_REPAIR; const originalEnabled = config.ENABLE_RECON_SUBTAG_REPAIR;
const originalDryRun = config.RECON_SUBTAG_REPAIR_DRY_RUN; const originalDryRun = config.RECON_SUBTAG_REPAIR_DRY_RUN;

View File

@ -1,8 +1,14 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function updateProfileName() { async function updateProfileName() {
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles(); const profiles = await supabaseService.getActiveProfiles();
if (profiles.length === 0) return; if (profiles.length === 0) return;
@ -11,7 +17,7 @@ async function updateProfileName() {
// Update Name in DB // Update Name in DB
// @ts-ignore // @ts-ignore
await supabaseService.client await legacyClient
.from('trade_profiles') .from('trade_profiles')
.update({ name: newName }) .update({ name: newName })
.eq('id', targetProfile.id); .eq('id', targetProfile.id);

View File

@ -1,11 +1,17 @@
import { supabaseService } from '../src/services/SupabaseService.js'; import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
async function setupHighRiskProfile() { async function setupHighRiskProfile() {
logger.info('🚀 SETTING UP HIGH-RISK SCALPER PROFILE...'); logger.info('🚀 SETTING UP HIGH-RISK SCALPER PROFILE...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get or Create Profile // 1. Get or Create Profile
const profiles = await supabaseService.getActiveProfiles(); const profiles = await supabaseService.getActiveProfiles();
let targetProfile = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High')); let targetProfile = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High'));
@ -32,7 +38,7 @@ async function setupHighRiskProfile() {
// In a real scenario, we'd update table 'trade_profiles' -> allocated_capital = 1000, risk = 5. // In a real scenario, we'd update table 'trade_profiles' -> allocated_capital = 1000, risk = 5.
// Let's try to update it if we can access the client. // Let's try to update it if we can access the client.
// @ts-ignore // @ts-ignore
const { error: updateError } = await supabaseService.client const { error: updateError } = await legacyClient
.from('trade_profiles') .from('trade_profiles')
.update({ .update({
allocated_capital: 1000, allocated_capital: 1000,
@ -81,7 +87,7 @@ async function setupHighRiskProfile() {
// A. Log Completed Trade to History // A. Log Completed Trade to History
// @ts-ignore // @ts-ignore
const { error: histError } = await supabaseService.client const { error: histError } = await legacyClient
.from('trade_history') .from('trade_history')
.insert([{ .insert([{
user_id: userId, user_id: userId,
@ -104,7 +110,7 @@ async function setupHighRiskProfile() {
// B. Log "Order" for this trade (Matched Pair) // B. Log "Order" for this trade (Matched Pair)
// 1. Entry Order // 1. Entry Order
// @ts-ignore // @ts-ignore
await supabaseService.client.from('orders').insert([{ await legacyClient.from('orders').insert([{
user_id: userId, user_id: userId,
profile_id: profileId, profile_id: profileId,
order_id: uuidv4(), order_id: uuidv4(),
@ -119,7 +125,7 @@ async function setupHighRiskProfile() {
// 2. Exit Order // 2. Exit Order
// @ts-ignore // @ts-ignore
await supabaseService.client.from('orders').insert([{ await legacyClient.from('orders').insert([{
user_id: userId, user_id: userId,
profile_id: profileId, profile_id: profileId,
order_id: uuidv4(), order_id: uuidv4(),

View File

@ -3,6 +3,7 @@ import fs from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import { ApiServer } from './src/services/apiServer.js'; import { ApiServer } from './src/services/apiServer.js';
// Direct supabaseService: monkey-patches loadLatestBotStateSnapshot on the singleton for isolation checks.
import { supabaseService } from './src/services/SupabaseService.js'; import { supabaseService } from './src/services/SupabaseService.js';
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);

View File

@ -1,16 +1,15 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { loadDynamicConfig, config } from '../src/config/index.js'; import { loadDynamicConfig, config } from '../src/config/index.js';
import logger from '../src/utils/logger.js'; import logger from '../src/utils/logger.js';
async function testDynamicConfigLoading() { async function testDynamicConfigLoading() {
logger.info('--- Testing Dynamic Config Loading from Supabase ---'); logger.info('--- Testing Dynamic Config Loading (control-plane storage) ---');
// 1. Initial State (from .env) // 1. Initial State (from .env)
const initialSymbols = [...config.SYMBOLS]; const initialSymbols = [...config.SYMBOLS];
logger.info(`Initial Symbols (.env): ${initialSymbols.join(', ')}`); logger.info(`Initial Symbols (.env): ${initialSymbols.join(', ')}`);
// 2. Load from DB // 2. Load from DB
await loadDynamicConfig(supabaseService); await loadDynamicConfig();
// 3. Final State // 3. Final State
logger.info(`Final Symbols (After DB Load): ${config.SYMBOLS.join(', ')}`); logger.info(`Final Symbols (After DB Load): ${config.SYMBOLS.join(', ')}`);

View File

@ -1,8 +1,12 @@
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import { supabaseService } from '../src/services/SupabaseService.js';
async function check() { async function check() {
const { data } = await supabaseService.client.from('trade_profiles').select('name, risk_per_trade_percent'); const client = getLegacySupabaseClient();
if (!client) {
console.error('Legacy Supabase client is not configured.');
process.exit(1);
}
const { data } = await client.from('trade_profiles').select('name, risk_per_trade_percent');
console.log('--- CURRENT PROFILES ---'); console.log('--- CURRENT PROFILES ---');
console.log(JSON.stringify(data, null, 2)); console.log(JSON.stringify(data, null, 2));
process.exit(0); process.exit(0);

View File

@ -1,7 +1,8 @@
import { supabaseService } from '../src/services/SupabaseService'; // Direct supabaseService: subscribeToProfiles is only implemented on SupabaseService (not exposed via legacySupabaseClient).
import { supabaseService } from '../src/services/SupabaseService.js';
import { createClient } from '@supabase/supabase-js'; import { createClient } from '@supabase/supabase-js';
import * as dotenv from 'dotenv'; import * as dotenv from 'dotenv';
import logger from '../src/utils/logger'; import logger from '../src/utils/logger.js';
dotenv.config(); dotenv.config();
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!); const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);