feat: dealer flow, mirror portfolio (M21), options convexity, FINRA short interest, alert producers, vendor gate
CI / Test & Type-Check (push) Canceled after 0s

Snapshot of in-progress module work across multiple slices:

- Dealer Flow: dealerExposureEngine, dealerMapService, dealerMapExplain,
  dealerMapIntegrity, dealerMapReplay, dealerStudyEngine, hanStyleLevels
- Mirror Portfolio (M21): fundRepository, captureIngest, mirrorAlertProducers,
  fund holdings strip, live book, position capture ingest
- Options: BSM, NormalizedOptionSurface types, OptionsChainRouter,
  ConvexityGate, option legs panel
- Alert producers: vixLevel, rotation, thesis, unlock, portfolioRisk,
  mirror (fund_capture, fund_13f, mirror_diff)
- FINRA short interest adapter + queue integration
- SEC company tickers adapter + ingest (symbol search index seed)
- Vendor gate (rate-limit-first data plane, ADR-0009)
- CUSIP registry, reverse 13F refresh, stock float service
- LRU cache, portfolio backtest engine
- Frontend: dealer-flow, funds, journal, lab, monitor, plan, portfolio,
  reports, screener, strategies, theses, guided-start, exits, more pages
- Volume profile, workspace profile, visibility-aware poll
- ADRs 0010 (mirror math not advice), 0011 (symbol search index)
- VENDOR_INTEGRATIONS.md, END_USER_TEST.md
- .gitignore: exclude DBs, .DS_Store, local config, agent scratch
This commit is contained in:
Investor Flow Build
2026-08-10 13:36:26 -04:00
parent 04fc11b2fd
commit ac94acf9e3
229 changed files with 32617 additions and 3934 deletions
@@ -20,6 +20,32 @@ export interface CreateSubscriptionInput {
params?: string;
}
/** Catalog of alert types shown in the per-type toggle list. */
export const ALERT_TYPE_CATALOG: Array<{ type: string; label: string; description: string }> = [
{ type: 'informed_buy', label: 'Insider Buy', description: 'Insider Form 4 purchases outside 10b5-1 plans.' },
{ type: 'informed_sell', label: 'Insider Sell', description: 'Insider Form 4 sales outside 10b5-1 plans.' },
{ type: 'new_13da', label: 'New 13D/G Filing', description: 'New institutional 13D/13G positions and 13F-HR filings.' },
{ type: 'rotation_incipient', label: 'Rotation Signal', description: 'Incipient sector rotation detected in the rotation engine.' },
{ type: 'regime_shift', label: 'Regime Shift', description: 'Market regime transition affecting portfolio risk.' },
{ type: 'conviction_unlock', label: 'Conviction Unlock', description: 'A new conviction tier unlocks from trading history.' },
{ type: 'thesis_broken', label: 'Thesis Broken', description: 'Thesis invalidation criteria met.' },
{ type: 'thesis_weakening', label: 'Thesis Weakening', description: 'Signals suggest a thesis may be weakening.' },
{ type: 'cluster_breach', label: 'Cluster Breach', description: 'Cluster exposure exceeds the recommended cap.' },
{ type: 'drawdown_halt', label: 'Drawdown Halt', description: 'Drawdown tolerance breached; circuit breaker paused entries.' },
{ type: 'asymmetry_warning', label: 'Asymmetry Warning', description: 'Portfolio reward-to-risk below threshold.' },
{ type: 'fund_capture', label: 'Fund Capture', description: 'A tracked fund posted a position update.' },
{ type: 'fund_13f', label: 'Tracked Fund 13F', description: 'A tracked fund filed a new 13F.' },
{ type: 'mirror_diff', label: 'Mirror Diff', description: 'The mirror target book changed materially.' },
{ type: 'vix_level', label: 'VIX Level', description: 'VIX moves into a new historical volatility band.' },
];
export interface AlertTypeToggle {
type: string;
label: string;
description: string;
enabled: boolean;
}
function stmts(db: DatabaseSync) {
return {
insert: db.prepare(
@@ -171,3 +197,103 @@ export function getEffectiveAlertSubscription(
if (globalRow) return mapRow(globalRow);
return null;
}
/**
* Seed a global default subscription (symbol NULL, watchlist NULL) for every
* catalog alert type for admin users (is_admin=1). Idempotent: only creates a
* default when the user has zero enabled subscriptions of that type, so a toggled
* preference (any ticker/list/global row) is never overwritten. Runs on every
* producer tick (cheap: no-op once seeded).
*/
export function seedAdminDefaultAlertSubscriptions(db: DatabaseSync): number {
let inserted = 0;
try {
const admins = db.prepare(
`SELECT id FROM users
WHERE is_admin = 1
AND id NOT IN ('anonymous','system')
AND email NOT LIKE 'anonymous@%'`,
).all() as Array<{ id: string }>;
if (admins.length === 0) return 0;
const insert = db.prepare(
`INSERT OR IGNORE INTO alerts (id, owner_id, watchlist_id, symbol, alert_type, enabled, params, created_at)
VALUES (?, ?, NULL, NULL, ?, 1, '{}', ?)`,
);
const hasEnabled = db.prepare(
`SELECT COUNT(*) AS n FROM alerts WHERE owner_id = ? AND alert_type = ? AND enabled = 1`,
);
const now = new Date().toISOString();
for (const admin of admins) {
for (const { type } of ALERT_TYPE_CATALOG) {
const { n } = hasEnabled.get(admin.id, type) as { n: number };
if (n > 0) continue;
const id = `auto-global-${admin.id}-${type}`;
const r = insert.run(id, admin.id, type, now);
if (Number(r.changes) > 0) inserted += 1;
}
}
} catch {
/* schema may lack tables in tests */
}
return inserted;
}
/**
* Per-type enable state for the current user. A type is "on" if any enabled
* subscription of that type exists (ticker-level, list-level, or global).
*/
export function listAlertTypeToggles(db: DatabaseSync, userId: string): AlertTypeToggle[] {
let rows: Array<{ alert_type: string; max_enabled: number }> = [];
try {
rows = db.prepare(
`SELECT alert_type, MAX(enabled) AS max_enabled
FROM alerts WHERE owner_id = ?
GROUP BY alert_type`,
).all(userId) as Array<{ alert_type: string; max_enabled: number }>;
} catch {
/* schema may lack alerts table in tests */
}
const enabledByType = new Map<string, boolean>();
for (const r of rows) enabledByType.set(r.alert_type, r.max_enabled === 1);
return ALERT_TYPE_CATALOG.map(({ type, label, description }) => ({
type,
label,
description,
enabled: enabledByType.get(type) ?? false,
}));
}
/**
* Toggle a whole alert type for a user. Flipping ON creates a global default
* subscription (symbol NULL, watchlist NULL) unless one exists; flipping OFF
* disables every subscription the user has of that type (ticker + list +
* global) so the toggle is authoritative. Never deletes rows.
*/
export function toggleAlertType(
db: DatabaseSync,
userId: string,
alertType: string,
enabled: boolean,
): AlertTypeToggle[] {
const catalog = ALERT_TYPE_CATALOG.find((c) => c.type === alertType);
if (!catalog) throw new Error(`Unknown alert type: ${alertType}`);
if (enabled) {
const existing = db.prepare(
`SELECT id FROM alerts WHERE owner_id = ? AND alert_type = ? AND symbol IS NULL AND watchlist_id IS NULL LIMIT 1`,
).get(userId, alertType) as { id: string } | undefined;
if (existing) {
db.prepare('UPDATE alerts SET enabled = 1 WHERE id = ?').run(existing.id);
} else {
createAlertSubscription(db, userId, { alertType });
}
} else {
db.prepare(
'UPDATE alerts SET enabled = 0 WHERE owner_id = ? AND alert_type = ?',
).run(userId, alertType);
}
return listAlertTypeToggles(db, userId);
}