Create ModuleSAFE
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
Overview
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
81b3f9a4c850OBSERVED · 2026-10-14What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: create-module
description: Create a new NestJS module with repository, service, controller, schema, and Drizzle table definition. Use when adding new feature modules, API endpoints, or business domains.
argument-hint: <module-name>
disable-model-invocation: true
---
# Create NestJS Module (PostgreSQL / Drizzle)
Create a new NestJS module for Mix Space project. Module name: `$ARGUMENTS`
## Directory Structure
Create the following files under `apps/core/src/modules/<module-name>/`:
```
<module-name>/
├── <name>.module.ts # Module definition
├── <name>.controller.ts # HTTP controller
├── <name>.service.ts # Business logic
├── <name>.repository.ts # Drizzle repository (extends BaseRepository)
├── <name>.schema.ts # Zod validation schemas for API DTOs
├── <name>.types.ts # TypeScript row/input types
└── <name>.enum.ts # Enums (optional, only if needed)
```
Also add the Drizzle table definition in `apps/core/src/database/schema/`.
## File Templates
### 0. Drizzle Table (`database/schema/<name>.ts`)
Create a new schema file (or append to an existing one) in `apps/core/src/database/schema/`.
```typescript
import { index, pgTable, text, uniqueIndex } from 'drizzle-orm/pg-core'
import { createdAt, pkText, refText, tsCol, updatedAt } from './columns'
export const <name>s = pgTable(
'<name>s',
{
id: pkText(),
createdAt: createdAt(),
name: text('name').notNull(),
// Add other columns...
},
(table) => [
// Add indexes and unique constraints
// uniqueIndex('<name>s_name_uniq').on(table.name),
// index('<name>s_created_at_idx').on(table.createdAt),
],
)
```
Then re-export it from `apps/core/src/database/schema/index.ts`:
```typescript
export * from './<name>'
```
**Column helpers** (from `columns.ts`):
- `pkText()` — Snowflake primary key as text (auto-named `id`)
- `refText(name)` — Snowflake foreign-key reference as text
- `createdAt()` — `created_at` timestamp with default `now()`
- `updatedAt()` — `updated_at` nullable timestamp
- `tsCol(name)` — generic timestamp column
**Common column types**:
- `text('col')` — string
- `integer('col')` — number
- `boolean('col')` — boolean (use `.default(false)`)
- `jsonb('col').$type<T>()` — JSON data
- `text('col').array()` — text array (e.g., tags)
### 1. Types (`<name>.types.ts`)
```typescript
import type { EntityId } from '~/shared/id/entity-id'
export interface <Name>Row {
id: EntityId
name: string
createdAt: Date
}
export interface <Name>CreateInput {
name: string
}
export type <Name>PatchInput = Partial<<Name>CreateInput>
```
### 2. Repository (`<name>.repository.ts`)
```typescript
import { Inject, Injectable } from '@nestjs/common'
import { desc, eq, sql } from 'drizzle-orm'
import { PG_DB_TOKEN } from '~/constants/system.constant'
import { <name>s } from '~/database/schema'
import {
BaseRepository,
type PaginationResult,
toEntityId,
} from '~/processors/database/base.repository'
import type { AppDatabase } from '~/processors/database/postgres.provider'
import { type EntityId, parseEntityId } from '~/shared/id/entity-id'
import { SnowflakeService } from '~/shared/id/snowflake.service'
import type { <Name>CreateInput, <Name>PatchInput, <Name>Row } from './<name>.types'
const mapRow = (row: typeof <name>s.$inferSelect): <Name>Row => ({
id: toEntityId(row.id) as EntityId,
name: row.name,
createdAt: row.createdAt,
})
@Injectable()
export class <Name>Repository extends BaseRepository {
constructor(
@Inject(PG_DB_TOKEN) db: AppDatabase,
private readonly snowflake: SnowflakeService,
) {
super(db)
}
async list(
page = 1,
size = 10,
filter?: Record<string, unknown>,
): Promise<PaginationResult<<Name>Row>> {
page = Math.max(1, page)
size = Math.min(50, Math.max(1, size))
const offset = (page - 1) * size
const [rows, [{ count }]] = await Promise.all([
this.db
.select()
.from(<name>s)
.orderBy(desc(<name>s.createdAt))
.limit(size)
.offset(offset),
this.db.select({ count: sql<number>`count(*)::int` }).from(<name>s),
])
return {
data: rows.map(mapRow),
pagination: this.paginationOf(Number(count ?? 0), page, size),
}
}
async findAll(): Promise<<Name>Row[]> {
const rows = await this.db
.select()
.from(<name>s)
.orderBy(desc(<name>s.createdAt))
return rows.map(mapRow)
}
async findById(id: EntityId | string): Promise<<Name>Row | null> {
const idBig = parseEntityId(id)
const [row] = await this.db
.select()
.from(<name>s)
.where(eq(<name>s.id, idBig))
.limit(1)
return row ? mapRow(row) : null
}
async create(input: <Name>CreateInput): Promise<<Name>Row> {
const id = this.snowflake.nextId()
const [row] = await this.db
.insert(<name>s)
.values({
id,
name: input.name,
})
.returning()
return mapRow(row)
}
async update(
id: EntityId | string,
patch: <Name>PatchInput,
): Promise<<Name>Row | null> {
const idBig = parseEntityId(id)
const update: Partial<typeof <name>s.$inferInsert> = {}
if (patch.name !== undefined) update.name = patch.name
if (Object.keys(update).length === 0) {
const [existing] = await this.db
.select()
.from(<name>s)
.where(eq(<name>s.id, idBig))
.limit(1)
return existing ? mapRow(existing) : null
}
const [row] = await this.db
.update(<name>s)
.set(update)
.where(eq(<name>s.id, idBig))
.returning()
return row ? mapRow(row) : null
}
async deleteById(id: EntityId | string): Promise<<Name>Row | null> {
const idBig = parseEntityId(id)
const [row] = await this.db
.delete(<name>s)
.where(eq(<name>s.id, idBig))
.returning()
return row ? mapRow(row) : null
}
async count(): Promise<number> {
const [row] = await this.db
.select({ couTrust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | WARN |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (1)
apps/core/.env
Gates applied: no_behavioural_pass.
81b3f9a4c850full audit observations/trust-audit/skill/mx-space__create-module.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-14 | 81b3f9a4c850 | SAFE | B | 89 | first audit |
Questions
What does the Create Module skill do?
AI-powered CMS core for personal blogs and creator websites, with AI summaries, translation, moderation, and writing workflows.
Is Create Module safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Create Module access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (81b3f9a4c850), read on 2026-10-14. The repository is watched, and a new audit runs when it changes — this is the first audit.