npm package: @lanitamarihuanera/suspicious-companies
Description: NestJS library for tracking suspicious companies with red flags, threat scoring, and fraud detection
Author: Javier Collipal
Latest version: 1.1.0

# @neko-arc/suspicious-companies

> NestJS library for tracking suspicious companies with red flags, threat scoring, and fraud detection

[![NPM Version](https://img.shields.io/npm/v/@neko-arc/suspicious-companies.svg)](https://www.npmjs.com/package/@neko-arc/suspicious-companies)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

- 🚩 **Red Flag Tracking** - 15+ categories of suspicious activities
- 📊 **Automatic Threat Scoring** - 0-100 scale with algorithmic calculation
- ⚖️ **Risk Classification** - LOW/MEDIUM/HIGH/CRITICAL levels
- 🔍 **Evidence Management** - Track sources, documents, and testimony
- 📝 **Investigation Workflow** - INITIAL → ACTIVE → VERIFIED → RESOLVED
- 💾 **MongoDB Integration** - Persistent storage with full TypeScript support
- 🎯 **Worker Protection** - Identify fake job postings and employment scams
- 🇨🇱 **Labor Law Support** - Chilean labor law integration ready

## Installation

```bash
npm install @neko-arc/suspicious-companies
```

### Peer Dependencies

```bash
npm install @nestjs/common@^10.0.0 @nestjs/core@^10.0.0 mongodb@^6.0.0
```

## Quick Start

### 1. Import the Module

```typescript
import { Module } from '@nestjs/common';
import { SuspiciousCompanyModule } from '@neko-arc/suspicious-companies';

@Module({
  imports: [
    SuspiciousCompanyModule.forRoot({
      mongodbUri: process.env.MONGODB_URI,
      database: 'hannibal-forensic-archives',     // optional
      collection: 'suspicious-companies',         // optional
    }),
  ],
})
export class AppModule {}
```

### 2. Inject the Service

```typescript
import { Injectable } from '@nestjs/common';
import {
  SuspiciousCompanyService,
  CreateSuspiciousCompanyDto,
  RedFlagCategory,
  RedFlagSeverity,
} from '@neko-arc/suspicious-companies';

@Injectable()
export class FraudDetectionService {
  constructor(
    private readonly suspiciousCompanyService: SuspiciousCompanyService,
  ) {}

  async investigateCompany(name: string) {
    const company = await this.suspiciousCompanyService.create({
      legalName: name,
      country: 'Chile',
      industry: 'Tourism',
      companyType: 'SPA',
      investigatedBy: ['Neko-Arc', 'Hannibal'],
      redFlags: [
        {
          category: RedFlagCategory.NO_DIGITAL_PRESENCE,
          severity: RedFlagSeverity.CRITICAL,
          title: 'No online presence',
          description: 'Company has zero digital footprint in 2025',
          discoveredBy: 'Neko-Arc',
        },
      ],
      digitalFootprint: {
        hasWebsite: false,
        hasSocialMedia: false,
        hasReviews: false,
        searchResultCount: 0,
      },
    });

    console.log(`Threat Score: ${company.overallThreatScore}/100`);
    console.log(`Risk Level: ${company.riskLevel}`);

    return company;
  }
}
```

## API Reference

### SuspiciousCompanyService

#### create(dto: CreateSuspiciousCompanyDto): Promise<ISuspiciousCompany>

Create a new suspicious company record with automatic threat scoring.

```typescript
const company = await service.create({
  legalName: 'ACME Corporation SPA',
  country: 'Chile',
  industry: 'Technology',
  companyType: 'SPA',
  investigatedBy: ['Investigator 1'],
  redFlags: [...],
});
```

#### findById(companyId: string): Promise<ISuspiciousCompany | null>

Find a company by its unique ID.

```typescript
const company = await service.findById('company-1731276000000');
```

#### findByName(legalName: string): Promise<ISuspiciousCompany[]>

Search companies by legal name (case-insensitive partial match).

```typescript
const companies = await service.findByName('ACME');
```

#### findByRiskLevel(riskLevel: RiskLevel): Promise<ISuspiciousCompany[]>

Find all companies with a specific risk level.

```typescript
import { RiskLevel } from '@neko-arc/suspicious-companies';

const critical = await service.findByRiskLevel(RiskLevel.CRITICAL);
```

#### update(companyId: string, dto: UpdateSuspiciousCompanyDto): Promise<ISuspiciousCompany | null>

Update a company record. Scores are automatically recalculated if relevant fields change.

```typescript
const updated = await service.update('company-1731276000000', {
  rut: '12.345.678-9',
  legalStatus: {
    registrationVerified: true,
  },
});
```

#### getStatistics(): Promise<Statistics>

Get database statistics including total count and risk level breakdown.

```typescript
const stats = await service.getStatistics();
// { total: 100, byRiskLevel: { critical: 10, high: 20, medium: 30, low: 40 } }
```

### ThreatScoringService

#### calculateThreatScore(company: ISuspiciousCompany): number

Calculate threat score (0-100) based on red flags and company attributes.

#### getRiskLevel(score: number): RiskLevel

Determine risk level classification from threat score.

#### updateScores(company: ISuspiciousCompany): ISuspiciousCompany

Update company with calculated threat score and risk level.

## Red Flag Categories

```typescript
enum RedFlagCategory {
  NO_DIGITAL_PRESENCE = 'NO_DIGITAL_PRESENCE',
  FAKE_CREDENTIALS = 'FAKE_CREDENTIALS',
  LABOR_VIOLATIONS = 'LABOR_VIOLATIONS',
  UNPAID_WAGES = 'UNPAID_WAGES',
  FRAUDULENT_ACTIVITY = 'FRAUDULENT_ACTIVITY',
  TAX_EVASION = 'TAX_EVASION',
  HARASSMENT = 'HARASSMENT',
  WRONGFUL_TERMINATION = 'WRONGFUL_TERMINATION',
  SHELL_COMPANY = 'SHELL_COMPANY',
  DEFUNCT_BUSINESS = 'DEFUNCT_BUSINESS',
  SUSPICIOUS_REGISTRATION = 'SUSPICIOUS_REGISTRATION',
  NO_PHYSICAL_ADDRESS = 'NO_PHYSICAL_ADDRESS',
  UNREACHABLE = 'UNREACHABLE',
  FAKE_JOB_POSTINGS = 'FAKE_JOB_POSTINGS',
  INVESTMENT_SCAM = 'INVESTMENT_SCAM',
  OTHER = 'OTHER',
}
```

## Threat Scoring Algorithm

The threat score (0-100) is calculated based on multiple factors:

### Red Flag Severity
- **CRITICAL**: +25 points per flag
- **WARNING**: +15 points per flag
- **INFO**: +5 points per flag

### Digital Presence Penalties
- No website: +20 points
- No social media: +15 points
- No reviews: +10 points
- Low search results (<5): +15 points

### Legal Status Penalties
- Unverified registration: +20 points
- Dormant status: +10 points
- Labor violations: +25 points
- Pending litigation: +15 points

### Risk Levels
- **0-25**: LOW - Minor concerns
- **26-50**: MEDIUM - Suspicious patterns
- **51-75**: HIGH - Significant red flags
- **76-100**: CRITICAL - Severe threats

## TypeScript Support

Full TypeScript support with complete type definitions included:

```typescript
import {
  ISuspiciousCompany,
  IRedFlag,
  CreateSuspiciousCompanyDto,
  RiskLevel,
} from '@neko-arc/suspicious-companies';

const company: ISuspiciousCompany = await service.findById('company-123');
```

## Use Cases

### 1. Worker Protection

Identify fraudulent job postings and protect job seekers:

```typescript
const company = await service.create({
  legalName: 'Fake Recruitment Inc',
  country: 'Chile',
  industry: 'Recruitment',
  companyType: 'LTDA',
  investigatedBy: ['HR Security Team'],
  redFlags: [
    {
      category: RedFlagCategory.FAKE_JOB_POSTINGS,
      severity: RedFlagSeverity.CRITICAL,
      title: 'Fraudulent job ads',
      description: 'Company posting fake jobs to collect personal data',
      discoveredBy: 'Security Team',
    },
  ],
});
```

### 2. Investment Due Diligence

Verify companies before investment:

```typescript
const companies = await service.findByName('Investment Opportunity LLC');

for (const company of companies) {
  if (company.riskLevel === RiskLevel.CRITICAL) {
    console.warn(`⚠️ HIGH RISK: ${company.legalName}`);
    console.warn(`Threat Score: ${company.overallThreatScore}/100`);
    console.warn(`Red Flags: ${company.redFlags.length}`);
  }
}
```

### 3. Labor Law Compliance

Track companies with labor violations:

```typescript
const company = await service.create({
  legalName: 'Labor Violator SA',
  country: 'Chile',
  industry: 'Construction',
  companyType: 'SA',
  investigatedBy: ['Labor Inspector'],
  legalStatus: {
    hasLaborViolations: true,
    laborViolationDetails: ['Unpaid wages', 'Workplace harassment'],
  },
  redFlags: [
    {
      category: RedFlagCategory.UNPAID_WAGES,
      severity: RedFlagSeverity.CRITICAL,
      title: 'Systematic wage theft',
      description: '20 employees unpaid for 3 months',
      discoveredBy: 'Labor Inspector',
    },
  ],
});
```

## Security

- ✅ **No hardcoded credentials** - All configuration via environment variables
- ✅ **MongoDB connection string** - Provided at runtime
- ✅ **Private repository** - Source code is private
- ✅ **Public package** - NPM distribution for easy installation
- ✅ **Security audited** - Pre-publishing security scan

## Configuration Options

```typescript
interface ISuspiciousCompanyModuleOptions {
  mongodbUri: string;      // Required: MongoDB Atlas connection string
  database?: string;       // Optional: Database name (default: 'hannibal-forensic-archives')
  collection?: string;     // Optional: Collection name (default: 'suspicious-companies')
}
```

## Environment Variables

```bash
# .env file
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/?retryWrites=true&w=majority
```

```typescript
// app.module.ts
SuspiciousCompanyModule.forRoot({
  mongodbUri: process.env.MONGODB_URI,
})
```

## Examples

### Complete Investigation Workflow

```typescript
// 1. Create initial investigation
const company = await service.create({
  legalName: 'Suspicious Company SPA',
  country: 'Chile',
  industry: 'Tourism',
  companyType: 'SPA',
  investigatedBy: ['Neko-Arc', 'Hannibal'],
  digitalFootprint: {
    hasWebsite: false,
    searchResultCount: 0,
  },
  suspiciousPatterns: [
    'No digital presence despite being in tourism',
    'Formal legal structure without operations',
  ],
  tags: ['ghost-company', 'patagonia', 'tourism-fraud'],
});

// 2. Add verification after registry check
await service.update(company.companyId, {
  rut: '12.345.678-9',
  legalStatus: {
    registrationVerified: true,
    isActive: true,
    isDormant: false,
  },
});

// 3. Add new red flag after discovery
const updated = await service.findById(company.companyId);
updated.redFlags.push({
  flagId: `flag-${Date.now()}`,
  category: RedFlagCategory.SHELL_COMPANY,
  severity: RedFlagSeverity.CRITICAL,
  title: 'Active registration without operations',
  description: 'Registered and active but no commercial activity',
  discoveredDate: new Date(),
  discoveredBy: 'Hannibal',
  verified: true,
});

await service.update(company.companyId, {
  redFlags: updated.redFlags,
  investigationStatus: InvestigationStatus.VERIFIED,
});
```

## License

MIT

## Author

Javier Collipal

## Repository

- **Source Code**: Private (GitHub)
- **NPM Package**: Public (npmjs.com)

## Support

For issues and questions:
- GitHub Issues: https://github.com/JavierCollipal/neko-suspicious-companies/issues

---

**Part of the Neko-Arc Six-Personality System** 🐾

Developed with forensic precision by:
- 🐾 Neko-Arc - Technical Coordination
- 🎭 Mario - Procedural Orchestration
- 🗡️ Noel - Precision Analysis
- 🎸 Glam - Worker Advocacy
- 🧠 Hannibal - Forensic Dissection
- 🧠 Tetora - Multi-Perspective Analysis