-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Problem
The current ES6 class implementations (*Impl
classes) in src/classes/[sdo, smo, sro, common]/
are sparse and require several TypeScript linting suppressions. The current approach uses interface declaration merging to extend STIX objects, which is not ideal:
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
export class AnalyticImpl extends AttackBaseImpl implements Analytic {
constructor(readonly analytic: Analytic) {
super();
Object.assign(this, analytic);
}
}
// Suppress the lint error for the empty interface
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface AnalyticImpl extends Analytic {}
/* eslint-enable @typescript-eslint/no-unsafe-declaration-merging */
Issues with current approach:
- Requires multiple linting error suppressions
- Uses interface declaration merging as a workaround
- Lacks comprehensive relationship management
- Missing domain-specific utility methods
Proposed Solution
Replace the current implementation pattern with a more robust approach using a Validated
base class that leverages Zod schemas for type safety:
New Architecture
- Schema-based validation: Classes extend
Validated(schema)
to inherit validated properties from Zod schemas - Private relationship tracking: Use private fields (
#property
) for mutable relationship state - Comprehensive API: Add domain-specific methods for relationship management and utility operations
- Type safety: Eliminate need for linting suppressions and declaration merging
Example Implementation
export class TechniqueImpl extends Validated(techniqueSchema) {
// Relationship tracking (mutable, not part of JSON data)
#subTechniques: TechniqueImpl[] = [];
#tactics: TacticImpl[] = [];
#mitigations: MitigationImpl[] = [];
#parentTechnique?: TechniqueImpl;
// ... other relationships
// Relationship management
addSubTechnique(subTechnique: TechniqueImpl): void {
if (!this.#subTechniques.includes(subTechnique)) {
this.#subTechniques.push(subTechnique);
}
}
getSubTechniques(): readonly TechniqueImpl[] {
return [...this.#subTechniques];
}
// Domain-specific utilities
getAttackId(): string | undefined {
return this.external_references?.[0]?.external_id;
}
getDisplayName(): string {
const attackId = this.getAttackId();
return attackId ? `${attackId}: ${this.name}` : this.name;
}
supportsPlatform(platform: string): boolean {
return this.x_mitre_platforms?.includes(platform as XMitrePlatform) ?? false;
}
// Immutable updates
with(updates: Partial<TechniqueImpl>): TechniqueImpl {
const newData = { ...this, ...updates };
return new TechniqueImpl(newData);
}
}
Benefits
- No linting suppressions needed: Clean TypeScript without workarounds
- Better encapsulation: Private fields for relationship state management
- Rich API: Domain-specific methods for common operations
- Type safety: Schema-based validation ensures data integrity
- Relationship management: Built-in support for navigating object relationships via SROs
- Immutable patterns: Support for functional updates with
with()
andtouch()
methods
Implementation Plan
- Create
Validated
base class that accepts Zod schema parameter - Refactor existing
*Impl
classes to use new pattern - Add comprehensive relationship management methods
- Implement domain-specific utility methods for each object type
- Update relationship processing logic to populate private relationship fields
- Remove all linting suppressions and declaration merging interfaces
Acceptance Criteria
- All
*Impl
classes useValidated
base class approach - Zero TypeScript linting suppressions in class implementations
- Comprehensive relationship management APIs
- Domain-specific utility methods for each object type
- SRO processing populates relationship fields for easy navigation
- All existing functionality preserved
- Type safety maintained throughout
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request