scalability-clean-code — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited scalability-clean-code (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Code readability principles and system-level scalability patterns.
// ❌ Class doing too much
class UserService {
async createUser(data: UserInput) { /* validation + DB + email + logging */ }
}
// ✅ Separated responsibilities
class UserValidator { validate(data: UserInput): ValidationResult { /* ... */ } }
class UserRepository { create(data: ValidUser): Promise<User> { /* ... */ } }
class WelcomeEmailService { send(user: User): Promise<void> { /* ... */ } }
class UserService {
constructor(
private validator: UserValidator,
private repo: UserRepository,
private emailService: WelcomeEmailService,
) {}
async createUser(data: UserInput) {
const valid = this.validator.validate(data)
const user = await this.repo.create(valid)
await this.emailService.send(user)
return user
}
}// ❌ Modifying existing code for every new payment method
function processPayment(method: string, amount: number) {
if (method === "stripe") { /* ... */ }
else if (method === "paypal") { /* ... */ }
// adding "crypto" means editing this function again
}
// ✅ Open for extension, closed for modification
interface PaymentProcessor {
process(amount: number): Promise<PaymentResult>
}
class StripeProcessor implements PaymentProcessor { /* ... */ }
class PayPalProcessor implements PaymentProcessor { /* ... */ }
class CryptoProcessor implements PaymentProcessor { /* ... */ } // new — no edits elsewhere
class PaymentService {
constructor(private processor: PaymentProcessor) {}
process(amount: number) { return this.processor.process(amount) }
}// ❌ High-level module depends on low-level concrete implementation
class OrderService {
private db = new PostgresDatabase() // tightly coupled
}
// ✅ Depend on abstractions
interface Database {
query<T>(sql: string, params: unknown[]): Promise<T[]>
}
class OrderService {
constructor(private db: Database) {} // inject any implementation
}
// Easy to swap implementations or mock for tests
const orderService = new OrderService(new PostgresDatabase())
const testService = new OrderService(new InMemoryDatabase())// ❌ Repeated validation logic
function createUser(data: any) {
if (!data.email || !data.email.includes("@")) throw new Error("Invalid email")
// ...
}
function updateUser(data: any) {
if (!data.email || !data.email.includes("@")) throw new Error("Invalid email")
// ...
}
// ✅ Extract shared logic
const emailSchema = z.string().email()
function createUser(data: unknown) {
const validated = userCreateSchema.parse(data)
// ...
}
// ⚠️ AVOID premature abstraction — the "Rule of Three"
// Don't extract a shared function until you see the SAME logic 3+ times.
// Two similar-looking pieces of code might still be conceptually different.| Smell | Symptom | Fix |
|---|---|---|
| Long function | >30-50 lines, multiple responsibilities | Extract smaller functions |
| Long parameter list | >3-4 params | Use an options object / DTO |
| Deep nesting | >3 levels of if/for | Early returns, extract conditions |
| God object | One class does everything | Split by responsibility (SRP) |
| Shotgun surgery | One change requires edits in 10 files | Consolidate related logic |
| Feature envy | Method uses another object's data more than its own | Move method to that object |
| Primitive obsession | Passing raw strings/numbers everywhere | Use value objects/branded types |
// ❌ Deep nesting
function processOrder(order: Order) {
if (order) {
if (order.items.length > 0) {
if (order.status === "pending") {
if (order.user.isVerified) {
// actual logic buried 4 levels deep
}
}
}
}
}
// ✅ Guard clauses (early returns)
function processOrder(order: Order) {
if (!order) return
if (order.items.length === 0) return
if (order.status !== "pending") return
if (!order.user.isVerified) return
// actual logic at top level — much more readable
}// ❌ Easy to mix up — both are strings
function transferMoney(fromAccountId: string, toAccountId: string, amount: number) {}
transferMoney(toAccountId, fromAccountId, amount) // bug! args swapped, compiles fine
// ✅ Branded types catch this at compile time
type AccountId = string & { readonly __brand: "AccountId" }
function asAccountId(id: string): AccountId { return id as AccountId }
function transferMoney(from: AccountId, to: AccountId, amount: number) {}
// transferMoney(toId, fromId, amount) → TYPE ERROR if order matters semantically┌─────────────────────────────────────┐
│ Presentation (UI, Routes, Controllers) │ ← depends on ↓
├─────────────────────────────────────┤
│ Application (Use Cases, Services) │ ← depends on ↓
├─────────────────────────────────────┤
│ Domain (Entities, Business Rules) │ ← depends on nothing
├─────────────────────────────────────┤
│ Infrastructure (DB, External APIs) │ ← implements Domain interfaces
└─────────────────────────────────────┘// domain/order.ts — pure business logic, no framework dependencies
export class Order {
constructor(
public readonly id: string,
public readonly items: OrderItem[],
private status: OrderStatus,
) {}
canBeCancelled(): boolean {
return this.status === "pending" || this.status === "processing"
}
cancel(): void {
if (!this.canBeCancelled()) {
throw new Error("Order cannot be cancelled in its current state")
}
this.status = "cancelled"
}
}
// application/cancel-order.usecase.ts — orchestrates domain + infra
export class CancelOrderUseCase {
constructor(private orderRepo: OrderRepository) {}
async execute(orderId: string): Promise<void> {
const order = await this.orderRepo.findById(orderId)
if (!order) throw new NotFoundError("Order not found")
order.cancel() // domain logic, throws if invalid
await this.orderRepo.save(order)
}
}
// infrastructure/postgres-order.repository.ts — implements the interface
export class PostgresOrderRepository implements OrderRepository {
async findById(id: string): Promise<Order | null> { /* SQL query */ }
async save(order: Order): Promise<void> { /* SQL update */ }
}// ❌ In-memory state — breaks with multiple instances
const sessions = new Map<string, Session>() // lost on restart, inconsistent across instances
// ✅ Externalize state to Redis/DB
async function getSession(id: string): Promise<Session | null> {
const data = await redis.get(`session:${id}`)
return data ? JSON.parse(data) : null
}[Load Balancer] → round-robin or least-connections
├── [Instance 1] — stateless, no local sessions/cache
├── [Instance 2] — stateless, no local sessions/cache
└── [Instance 3] — stateless, no local sessions/cache
│
├── [Shared Redis] — sessions, cache
└── [Shared PostgreSQL] — source of truthStep 1: Vertical scaling (bigger instance) — quick, limited ceiling
Step 2: Read replicas — scale reads, writes still single primary
Step 3: Connection pooling (pgBouncer) — handle more concurrent connections
Step 4: Caching layer (Redis) — reduce DB load for hot reads
Step 5: Sharding — only when truly necessary (high complexity cost)// Read replica routing
const writeDb = drizzle(writePool) // INSERT/UPDATE/DELETE
const readDb = drizzle(readReplicaPool) // SELECT (eventually consistent)
async function getPost(id: string) {
return readDb.select().from(posts).where(eq(posts.id, id)) // use replica
}
async function createPost(data: NewPost) {
return writeDb.insert(posts).values(data).returning() // use primary
}Request → [CDN/Edge Cache] → [App Cache (Redis)] → [Database]
(static assets) (computed results) (source of truth)| Cache Layer | TTL | Invalidation |
|---|---|---|
| CDN (static assets) | Days-weeks | Content hash in filename |
| Edge (API responses) | Seconds-minutes | Tag-based revalidation |
| App cache (Redis) | Minutes-hours | Explicit invalidation on write |
| Query cache (DB) | Seconds | Automatic, DB-managed |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.