fix(rust-bridge): correct Email.addHeader() calls and IBounceDetection interface
Some checks failed
CI / Type Check & Lint (push) Failing after 4s
CI / Build Test (Current Platform) (push) Failing after 4s
CI / Build All Platforms (push) Failing after 4s

Use addHeader() instead of non-existent setHeader() for security
result headers, and align IBounceDetection with actual Rust struct
fields (bounce_type + category only).
This commit is contained in:
2026-02-10 16:38:31 +00:00
parent 9185242530
commit 6b082cee8f
13 changed files with 558 additions and 20 deletions

View File

@@ -0,0 +1,136 @@
import { tap, expect } from '@git.zone/tstest/tapbundle';
import { RustSecurityBridge } from '../ts/security/classes.rustsecuritybridge.js';
let bridge: RustSecurityBridge;
tap.test('RustSecurityBridge - should get singleton instance', async () => {
bridge = RustSecurityBridge.getInstance();
expect(bridge).toBeTruthy();
expect(bridge).toEqual(RustSecurityBridge.getInstance()); // same instance
});
tap.test('RustSecurityBridge - should start the Rust binary', async () => {
const ok = await bridge.start();
if (!ok) {
console.log('WARNING: Rust binary not available — skipping bridge tests');
console.log('Build it with: cd rust && cargo build --release');
}
// We accept both true and false — the binary may not be built yet
expect(typeof ok).toEqual('boolean');
});
tap.test('RustSecurityBridge - ping should return pong', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const pong = await bridge.ping();
expect(pong).toBeTrue();
});
tap.test('RustSecurityBridge - version should return crate versions', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const version = await bridge.getVersion();
expect(version.bin).toBeTruthy();
expect(version.core).toBeTruthy();
expect(version.security).toBeTruthy();
});
tap.test('RustSecurityBridge - validateEmail with valid address', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const result = await bridge.validateEmail('test@example.com');
expect(result.valid).toBeTrue();
expect(result.formatValid).toBeTrue();
});
tap.test('RustSecurityBridge - validateEmail with invalid address', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const result = await bridge.validateEmail('not-an-email');
expect(result.formatValid).toBeFalse();
});
tap.test('RustSecurityBridge - detectBounce with known SMTP response', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const result = await bridge.detectBounce({
smtpResponse: '550 5.1.1 User unknown',
});
expect(result.bounce_type).toBeTruthy();
expect(result.category).toBeTruthy();
});
tap.test('RustSecurityBridge - checkIpReputation', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
// Use a well-known IP that should NOT be on blacklists
const result = await bridge.checkIpReputation('8.8.8.8');
expect(result.ip).toEqual('8.8.8.8');
expect(typeof result.score).toEqual('number');
expect(result.score).toBeGreaterThan(0);
});
tap.test('RustSecurityBridge - verifyDkim with unsigned message', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const rawMessage = 'From: test@example.com\r\nTo: receiver@example.com\r\nSubject: Test\r\n\r\nHello';
const results = await bridge.verifyDkim(rawMessage);
expect(results.length).toBeGreaterThan(0);
expect(results[0].status).toEqual('none'); // no DKIM signature
});
tap.test('RustSecurityBridge - verifyEmail compound call', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
const rawMessage = 'From: test@example.com\r\nTo: receiver@example.com\r\nSubject: Test\r\n\r\nHello';
const result = await bridge.verifyEmail({
rawMessage,
ip: '93.184.216.34', // example.com IP
heloDomain: 'example.com',
hostname: 'mail.test.local',
mailFrom: 'test@example.com',
});
expect(result.dkim).toBeTruthy();
expect(result.dkim.length).toBeGreaterThan(0);
expect(result.spf).toBeTruthy();
// DMARC may or may not be present depending on DNS
});
tap.test('RustSecurityBridge - should stop gracefully', async () => {
if (!bridge.running) {
console.log('SKIP: bridge not running');
return;
}
await bridge.stop();
expect(bridge.running).toBeFalse();
});
tap.test('RustSecurityBridge - commands should fail when bridge is stopped', async () => {
// Bridge should not be running now
expect(bridge.running).toBeFalse();
try {
await bridge.ping();
// If we get here, the bridge auto-restarted or something unexpected
expect(true).toBeFalse(); // Should not reach here
} catch (err) {
expect(err).toBeTruthy(); // Expected: bridge not running error
}
});
export default tap.start();