Fix Mixpanel analytics review findings FRE-5281
P0: Fix validation bypass - validated properties now override raw properties P1: Add unit tests for shared-analytics package (3 test files) P1: Refactor spamshield to use shared-analytics, deprecate duplicate P2: Normalize phone numbers to E.164 before hashing P2: Add graceful error handling for missing env vars in config P3: Add singleton pattern to MixpanelService P3: Include timestamp in validated properties schema
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@shieldsai/shared-analytics": "workspace:*",
|
||||
"@shieldai/db": "workspace:*",
|
||||
"@shieldai/types": "workspace:*",
|
||||
"@shieldai/correlation": "workspace:*",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { mixpanelService, EventType } from '@shieldsai/shared-analytics';
|
||||
import { FieldEncryptionService } from '@shieldai/db';
|
||||
|
||||
export interface SpamBlockedEvent {
|
||||
@@ -30,6 +31,14 @@ const DEFAULT_CONFIG: Required<MixpanelConfig> = {
|
||||
enableLogging: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* SpamShield analytics adapter.
|
||||
* Delegates to the shared MixpanelService for consistent event tracking
|
||||
* across the ShieldAI platform, while maintaining spam-specific interfaces.
|
||||
*
|
||||
* @deprecated Use {@link @shieldsai/shared-analytics#MixpanelService} directly
|
||||
* for new analytics code. This wrapper maintains backward compatibility.
|
||||
*/
|
||||
export class MixpanelService {
|
||||
private readonly config: Required<MixpanelConfig>;
|
||||
private readonly events: MixpanelEventProperties[] = [];
|
||||
@@ -58,15 +67,24 @@ export class MixpanelService {
|
||||
);
|
||||
}
|
||||
|
||||
const response = await this.track('spam_blocked', properties);
|
||||
await mixpanelService.track(EventType.SPAM_BLOCKED, properties.phoneNumberHash, {
|
||||
decision: event.decision,
|
||||
confidence: event.confidence,
|
||||
ruleMatches: event.ruleMatches,
|
||||
timestamp: event.timestamp,
|
||||
});
|
||||
|
||||
return {
|
||||
...properties,
|
||||
...response,
|
||||
};
|
||||
return properties;
|
||||
}
|
||||
|
||||
async track(eventName: string, properties: Record<string, any>): Promise<Record<string, any>> {
|
||||
const mpEvent = Object.values(EventType).find(e => e === eventName) as EventType | undefined;
|
||||
|
||||
if (mpEvent) {
|
||||
await mixpanelService.track(mpEvent, properties.phoneNumberHash || 'anonymous', properties);
|
||||
return { status: 200 };
|
||||
}
|
||||
|
||||
const url = `https://${this.config.apiHost}/track`;
|
||||
|
||||
const payload = {
|
||||
|
||||
Reference in New Issue
Block a user