@bernierllc/email-mitm-masking 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.initializeDatabase = initializeDatabase;
11
+ /**
12
+ * Initialize database schema for email masking
13
+ */
14
+ async function initializeDatabase(pool) {
15
+ await pool.query(`
16
+ CREATE TABLE IF NOT EXISTS proxy_addresses (
17
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
18
+ proxy_email TEXT UNIQUE NOT NULL,
19
+ real_email TEXT NOT NULL,
20
+ user_id TEXT NOT NULL,
21
+ external_email TEXT,
22
+ conversation_id TEXT,
23
+ status TEXT NOT NULL DEFAULT 'active',
24
+ created_at TIMESTAMP NOT NULL DEFAULT NOW(),
25
+ activated_at TIMESTAMP,
26
+ expires_at TIMESTAMP,
27
+ last_used_at TIMESTAMP,
28
+ routing_count INTEGER NOT NULL DEFAULT 0,
29
+ metadata JSONB
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_proxy_email ON proxy_addresses(proxy_email);
33
+ CREATE INDEX IF NOT EXISTS idx_user_id ON proxy_addresses(user_id);
34
+ CREATE INDEX IF NOT EXISTS idx_real_email ON proxy_addresses(real_email);
35
+ CREATE INDEX IF NOT EXISTS idx_status ON proxy_addresses(status);
36
+ CREATE INDEX IF NOT EXISTS idx_expires_at ON proxy_addresses(expires_at) WHERE status = 'active';
37
+
38
+ CREATE TABLE IF NOT EXISTS routing_audit (
39
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
40
+ proxy_id UUID NOT NULL,
41
+ direction TEXT NOT NULL,
42
+ from_address TEXT NOT NULL,
43
+ to_address TEXT NOT NULL,
44
+ routed_at TIMESTAMP NOT NULL DEFAULT NOW(),
45
+ success BOOLEAN NOT NULL,
46
+ error TEXT,
47
+ metadata JSONB
48
+ );
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_audit_proxy_id ON routing_audit(proxy_id);
51
+ CREATE INDEX IF NOT EXISTS idx_routed_at ON routing_audit(routed_at);
52
+ CREATE INDEX IF NOT EXISTS idx_direction ON routing_audit(direction);
53
+
54
+ CREATE TABLE IF NOT EXISTS masking_rules (
55
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
56
+ user_id TEXT NOT NULL,
57
+ type TEXT NOT NULL,
58
+ criteria TEXT NOT NULL,
59
+ action TEXT NOT NULL,
60
+ priority INTEGER NOT NULL DEFAULT 0,
61
+ enabled BOOLEAN NOT NULL DEFAULT true,
62
+ created_at TIMESTAMP NOT NULL DEFAULT NOW()
63
+ );
64
+
65
+ CREATE INDEX IF NOT EXISTS idx_rules_user_id ON masking_rules(user_id);
66
+ CREATE INDEX IF NOT EXISTS idx_priority ON masking_rules(priority);
67
+ CREATE INDEX IF NOT EXISTS idx_enabled ON masking_rules(enabled);
68
+ `);
69
+ }
@@ -0,0 +1,2 @@
1
+ export { EmailMaskingService } from './EmailMaskingService.js';
2
+ export type { EmailMaskingConfig, DatabaseConfig, ProxyAddress, MaskingRule, RoutingResult, RoutingAudit, MaskingResult, CreateProxyOptions, EmailContent } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.EmailMaskingService = void 0;
11
+ var EmailMaskingService_js_1 = require("./EmailMaskingService.js");
12
+ Object.defineProperty(exports, "EmailMaskingService", { enumerable: true, get: function () { return EmailMaskingService_js_1.EmailMaskingService; } });
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Configuration for email masking service
3
+ */
4
+ export interface EmailMaskingConfig {
5
+ /** Proxy domain for masked addresses (e.g., proxy.example.com) */
6
+ proxyDomain: string;
7
+ /** Database connection for proxy storage */
8
+ database: DatabaseConfig;
9
+ /** Default TTL for proxy addresses (in days, 0 = unlimited) */
10
+ defaultTTL?: number;
11
+ /** Maximum proxies per user (0 = unlimited) */
12
+ maxProxiesPerUser?: number;
13
+ /** Enable audit logging */
14
+ auditEnabled?: boolean;
15
+ /** Masking strategy */
16
+ strategy?: 'per-user' | 'per-contact' | 'per-conversation';
17
+ }
18
+ /**
19
+ * Database configuration
20
+ */
21
+ export interface DatabaseConfig {
22
+ host: string;
23
+ port: number;
24
+ database: string;
25
+ user: string;
26
+ password: string;
27
+ }
28
+ /**
29
+ * Proxy email address record
30
+ */
31
+ export interface ProxyAddress {
32
+ /** Unique proxy identifier */
33
+ id: string;
34
+ /** Proxy email address (e.g., user-abc123@proxy.domain.com) */
35
+ proxyEmail: string;
36
+ /** Real user email address */
37
+ realEmail: string;
38
+ /** User identifier */
39
+ userId: string;
40
+ /** Optional external contact email (for per-contact masking) */
41
+ externalEmail?: string;
42
+ /** Optional conversation identifier (for per-conversation masking) */
43
+ conversationId?: string;
44
+ /** Proxy status */
45
+ status: 'active' | 'inactive' | 'expired' | 'revoked';
46
+ /** Creation timestamp */
47
+ createdAt: Date;
48
+ /** Activation timestamp */
49
+ activatedAt?: Date;
50
+ /** Expiration timestamp (null = no expiration) */
51
+ expiresAt?: Date;
52
+ /** Last used timestamp */
53
+ lastUsedAt?: Date;
54
+ /** Routing count */
55
+ routingCount: number;
56
+ /** Metadata */
57
+ metadata?: Record<string, unknown>;
58
+ }
59
+ /**
60
+ * Masking rule configuration
61
+ */
62
+ export interface MaskingRule {
63
+ /** Rule identifier */
64
+ id: string;
65
+ /** User identifier */
66
+ userId: string;
67
+ /** Rule type */
68
+ type: 'domain' | 'address' | 'pattern';
69
+ /** Match criteria */
70
+ criteria: string;
71
+ /** Action (mask or allow) */
72
+ action: 'mask' | 'allow';
73
+ /** Priority (higher = evaluated first) */
74
+ priority: number;
75
+ /** Enabled flag */
76
+ enabled: boolean;
77
+ }
78
+ /**
79
+ * Routing result
80
+ */
81
+ export interface RoutingResult {
82
+ success: boolean;
83
+ routedTo?: string;
84
+ proxyUsed?: string;
85
+ direction: 'inbound' | 'outbound';
86
+ error?: string;
87
+ auditId?: string;
88
+ }
89
+ /**
90
+ * Audit entry
91
+ */
92
+ export interface RoutingAudit {
93
+ id: string;
94
+ proxyId: string;
95
+ direction: 'inbound' | 'outbound';
96
+ fromAddress: string;
97
+ toAddress: string;
98
+ routedAt: Date;
99
+ success: boolean;
100
+ error?: string;
101
+ metadata?: Record<string, unknown>;
102
+ }
103
+ /**
104
+ * Result wrapper for masking operations
105
+ */
106
+ export interface MaskingResult<T = unknown> {
107
+ success: boolean;
108
+ data?: T;
109
+ error?: string;
110
+ }
111
+ /**
112
+ * Options for creating a proxy
113
+ */
114
+ export interface CreateProxyOptions {
115
+ externalEmail?: string;
116
+ conversationId?: string;
117
+ ttlDays?: number;
118
+ metadata?: Record<string, unknown>;
119
+ }
120
+ /**
121
+ * Email content for outbound routing
122
+ */
123
+ export interface EmailContent {
124
+ subject: string;
125
+ text?: string;
126
+ html?: string;
127
+ }
128
+ /**
129
+ * Database row type for proxy addresses
130
+ */
131
+ export interface ProxyAddressRow {
132
+ id: string;
133
+ proxy_email: string;
134
+ real_email: string;
135
+ user_id: string;
136
+ external_email: string | null;
137
+ conversation_id: string | null;
138
+ status: string;
139
+ created_at: string;
140
+ activated_at: string | null;
141
+ expires_at: string | null;
142
+ last_used_at: string | null;
143
+ routing_count: string;
144
+ metadata: string | null;
145
+ }
146
+ /**
147
+ * Database row type for routing audit
148
+ */
149
+ export interface RoutingAuditRow {
150
+ id: string;
151
+ proxy_id: string;
152
+ direction: string;
153
+ from_address: string;
154
+ to_address: string;
155
+ routed_at: string;
156
+ success: boolean;
157
+ error: string | null;
158
+ metadata: string | null;
159
+ }
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,28 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ roots: ['<rootDir>/__tests__'],
5
+ testMatch: ['**/__tests__/**/*.test.ts'],
6
+ setupFilesAfterEnv: ['<rootDir>/__tests__/setup.ts'],
7
+ collectCoverageFrom: [
8
+ 'src/**/*.{ts,tsx}',
9
+ '!src/**/*.d.ts',
10
+ '!src/index.ts'
11
+ ],
12
+ coverageThreshold: {
13
+ global: {
14
+ branches: 85,
15
+ functions: 85,
16
+ lines: 85,
17
+ statements: 85
18
+ }
19
+ },
20
+ coverageReporters: ['text', 'lcov', 'html'],
21
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
22
+ moduleNameMapper: {
23
+ '^(\\.{1,2}/.*)\\.js$': '$1',
24
+ '^pg$': '<rootDir>/__tests__/__mocks__/database.ts',
25
+ '^../src/database\\.js$': '<rootDir>/__tests__/__mocks__/database.ts'
26
+ },
27
+ verbose: true
28
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@bernierllc/email-mitm-masking",
3
+ "version": "1.0.0",
4
+ "description": "Email masking and man-in-the-middle routing service for privacy-focused email communication",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "test": "jest --watch",
10
+ "test:run": "jest",
11
+ "test:coverage": "jest --coverage",
12
+ "lint": "eslint src --ext .ts",
13
+ "clean": "rm -rf dist"
14
+ },
15
+ "keywords": [
16
+ "email",
17
+ "masking",
18
+ "privacy",
19
+ "proxy",
20
+ "routing",
21
+ "mitm",
22
+ "anonymization",
23
+ "email-privacy"
24
+ ],
25
+ "author": "Bernier LLC",
26
+ "license": "SEE LICENSE IN LICENSE",
27
+ "dependencies": {
28
+ "@bernierllc/email-parser": "^1.0.0",
29
+ "@bernierllc/email-sender": "^2.0.0",
30
+ "@bernierllc/crypto-utils": "^1.2.0",
31
+ "@bernierllc/logger": "^1.1.0",
32
+ "@bernierllc/neverhub-adapter": "^1.0.0",
33
+ "pg": "^8.11.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/jest": "^29.0.0",
37
+ "@types/node": "^20.0.0",
38
+ "@types/pg": "^8.10.0",
39
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
40
+ "@typescript-eslint/parser": "^6.0.0",
41
+ "eslint": "^8.0.0",
42
+ "jest": "^29.0.0",
43
+ "ts-jest": "^29.0.0",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "bernierllc": {
50
+ "integration": {
51
+ "neverhub": "required",
52
+ "neveradmin": "not-applicable",
53
+ "logger": "integrated"
54
+ }
55
+ }
56
+ }