oracle-architect — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited oracle-architect (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.
Precise vocabulary for every architectural decision. Use these terms exactly — consistency is the point.
Key principles (apply to every decision):
Domain-Driven Design and hexagonal architecture with functional core pattern for feature design.
Unified view of functional core and effectful edge:
Effectful Edge (IO) Functional Core (Pure)
┌─────────────────────────────────┐ ┌──────────────────────────┐
│ Router → request parsing │ │ Service → orchestration│
│ Consumer → event handling │───▶│ Entity → domain rules │
│ Client → external APIs │ │ → validation │
│ Producer → event publishing │◀───│ → transforms │
│ Repository→ data persistence │ │ │
└─────────────────────────────────┘ └──────────────────────────┘Key Principle: Business logic lives in the functional core (Service + Entity). IO operations live in the effectful edge. Core defines interfaces; edge implements them (dependency inversion).
Before creating a new module, run these checks:
Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
When to apply: Before extracting a new Service, Repository, or utility class.
Example:
❌ Shallow: OrderFormatterService with 1 method per field
→ Deleting it just moves 6 lines into the Router
→ Interface is as complex as implementation
✅ Deep: OrderService with validate → reserve → save → publish
→ Deleting it replicates orchestration across N handlers
→ Small interface (createOrder), large implementationCallers and tests cross the same seam. If you want to test past the interface, the module is probably the wrong shape.
Implication:
One adapter = hypothetical seam. Two adapters = real seam.
When to apply: Deciding whether to extract an interface.
Examples:
// ❌ Hypothetical seam — only one adapter exists
interface IEmailClient { send(email: Email): Promise<void>; }
class SendgridClient implements IEmailClient { ... }
// No second adapter. The interface adds indirection without value.
// ✅ Real seam — two adapters exist
interface IOrderRepository { save(order: Order): Promise<Order>; }
class PostgresOrderRepository implements IOrderRepository { ... }
class InMemoryOrderRepository implements IOrderRepository { ... } // for tests
// The seam earns its keep because callers vary (production vs test).Prefer deep modules over shallow ones:
| Module | Interface Size | Implementation | Depth |
|---|---|---|---|
OrderValidator | 3 methods (validate, validateItems, validateAddress) | 30 lines each | Shallow |
Order (entity) | 4 methods (fromRequest, toRecord, toResponse, validate) | 200 lines of rules, transforms, invariants | Deep |
Rule of thumb: A module's interface should hide at least 3x the complexity it exposes.
Pure, deterministic components containing all business logic.
Responsibility: Orchestrate business operations, coordinate between entities and repositories.
Characteristics:
Example:
class OrderService {
async createOrder(request: CreateOrderRequest): Promise<Result<Order>> {
// Validate with entity
const order = Order.fromRequest(request);
const validation = order.validate();
if (!validation.ok) return validation;
// Check business rules
const inventory = await this.inventoryRepo.checkAvailability(order.items);
if (!inventory.available) return Err('Items not available');
// Coordinate persistence
await this.inventoryRepo.reserve(order.items);
const saved = await this.orderRepo.save(order.toRecord());
return Ok(Order.fromRecord(saved));
}
}Responsibility: Domain models, validation, business rules, data transformations.
Characteristics:
Example:
class Order {
constructor(
public readonly id: string,
public readonly customerId: string,
public readonly items: OrderItem[],
public readonly status: OrderStatus,
public readonly total: number
) {}
static fromRequest(req: CreateOrderRequest): Order {
return new Order(
generateId(),
req.customerId,
req.items.map(i => new OrderItem(i)),
'pending',
req.items.reduce((sum, i) => sum + i.price * i.quantity, 0)
);
}
toRecord(): OrderRecord {
return {
id: this.id,
customer_id: this.customerId,
items: JSON.stringify(this.items),
status: this.status,
total: this.total
};
}
validate(): Result<Order> {
if (this.items.length === 0) {
return Err('Order must have at least one item');
}
if (this.total < 0) {
return Err('Order total cannot be negative');
}
return Ok(this);
}
canCancel(): boolean {
return ['pending', 'confirmed'].includes(this.status);
}
}IO-performing components that interact with the outside world.
Responsibility: HTTP request handling, parsing, response formatting.
Characteristics:
Example:
router.post('/orders', async (req, res) => {
const result = await orderService.createOrder(req.body);
if (result.ok) {
res.status(201).json(result.value.toResponse());
} else {
res.status(400).json({ error: result.error });
}
});Responsibility: Data persistence and retrieval.
Characteristics:
Example:
class OrderRepository {
async save(record: OrderRecord): Promise<OrderRecord> {
return await db.orders.create(record);
}
async findById(id: string): Promise<OrderRecord | null> {
return await db.orders.findOne({ id });
}
}Quick reference for where things belong:
| Concern | Component | Layer | Testability |
|---|---|---|---|
| Domain model | Entity | Core | Unit test (pure) |
| Validation | Entity | Core | Unit test (pure) |
| Business rules | Entity | Core | Unit test (pure) |
| Orchestration | Service | Core | Unit test (stub repos) |
| Data transforms | Entity | Core | Unit test (pure) |
| HTTP parsing | Router | Edge | Integration test |
| Data access | Repository | Edge | Integration test |
| External APIs | Client | Edge | Integration test |
| Event handling | Consumer | Edge | Integration test |
| Event publishing | Producer | Edge | Integration test |
Implementation order follows dependency chain:
1. Entity → Domain models, validation, transforms
2. Repository → Data access interfaces and implementations
3. Service → Business logic orchestration
4. Router → HTTP endpointsRationale: Each layer depends on layers below. Can't implement service without entity, can't implement router without service.
One task per layer:
For complex features, break down further:
Architectural decisions inform testing strategy:
Architect Outputs → Testing Inputs
────────────────────────────────────────────────
Component responsibilities → What to test
Layer boundaries → Where to test
Pure vs effectful → Unit vs integration
Entity transformations → Property-based tests
Service orchestration → Stub-driven testsThe testing skill uses architectural structure to determine:
For detailed patterns and examples:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.