aurora-schema
Aurora YAML schema analysis and editing. Validates field names, descriptions, types, and module semantics following DDD best practices. Trigger: When analyzing or editing *.aurora.yaml files, improving field naming, adding descriptions, or validating schema semantics.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
When to Use
Use this skill when:
- Analyzing
*.aurora.yamlfiles for quality and consistency - Editing YAML schemas (creating, updating, or deleting fields)
- Validating field naming conventions and descriptions
- Ensuring module descriptions explain purpose and context
- Reviewing data type appropriateness
- Checking cross-module consistency
Always combine with:
-
aurora-cliskill when regenerating after YAML changes -
aurora-project-structureskill for locating YAML files -
conventional-commitsskill when committing schema changes
Critical Patterns
Module Description (REQUIRED)
Every *.aurora.yaml must have a description property before
aggregateProperties:.
# ✅ CORRECT
version: 0.0.1
boundedContextName: iam
moduleName: permission
description: >
Module containing the permissions associated with each bounded context, to be
used to manage access to each API.
aggregateProperties:
- name: id
# ❌ INCORRECT - Missing description
version: 0.0.1
boundedContextName: iam
moduleName: permission
aggregateProperties:
- name: id
Description should explain:
- What the module contains (main entity)
- What it's used for (purpose)
- How it relates to other modules in the bounded context
Field Naming Conventions
| Pattern | Use For | Examples |
|---|---|---|
camelCase |
All field names | firstName, orderDate, totalAmount |
is*, has*, can* |
Boolean flags | isActive, hasChildren, canEdit |
*At |
Timestamps | createdAt, updatedAt, publishedAt |
*Date |
Date-only fields | birthDate, startDate, endDate |
*Id |
Foreign keys | authorId, categoryId, parentId |
sort |
Display/UI ordering | sort (NOT displayOrder, order, position) |
Anti-patterns:
# ❌ BAD
- name: stat # → status
- name: dt # → createdAt
- name: qty # → quantity
- name: active # → isActive (boolean prefix)
- name: author # → authorId (if it's a foreign key)
type: id
- name: displayOrder # → sort (standard name for ordering)
- name: order # → sort (ambiguous, conflicts with order entity)
- name: position # → sort (use sort for UI ordering)
# ✅ GOOD
- name: status
- name: createdAt
- name: quantity
- name: isActive
- name: authorId
type: id
- name: sort # Standard field for UI display ordering
type: smallint
unsigned: true
Field Descriptions (MANDATORY)
Every field MUST have a description that explains WHY, not WHAT:
# ❌ BAD - States the obvious
- name: price
type: decimal
description: The price of the book
# ✅ GOOD - Explains context and usage
- name: price
type: decimal
decimals: [10, 2]
description: >
Retail price in the store's base currency (configured in settings). Does not
include taxes or discounts. Used as base for price calculations.
Include:
- Business context and constraints
- Default values and behavior
- Validation rules
- Examples for complex formats
- name: isbn
type: varchar
maxLength: 17
index: unique
description: >
International Standard Book Number in ISBN-13 format. Must be unique across
all books. Validated against checksum algorithm. Example: 978-3-16-148410-0
Type Selection Guide
| Use Case | Type | Configuration | Notes |
|---|---|---|---|
| UUID identifiers | id |
NO length property |
CRITICAL: Never add length to id type |
| Short text | varchar |
maxLength: N |
Names, titles, codes |
| Long text | text |
- | Descriptions, content |
| Fixed-length text | char |
length: N |
Country codes, currency |
| Passwords | password |
- | Auto-hashed by Aurora |
| Integer counters | int |
- | Standard integers |
| Large numbers | bigint |
- | > 2 billion |
| Small numbers | smallint |
- | 0-255 range |
| Money/decimals | decimal |
decimals: [precision, scale] |
Never use float for money |
| Approximate | float |
- | Scientific only |
| Date + time | timestamp |
- | Most common |
| Date only | date |
- | Birthdays, deadlines |
| True/false | boolean |
- | Use is*/has*/can* prefix |
| Fixed options | enum |
enumOptions: [...] |
Document each option |
| Structured data | json, jsonb |
- | Use jsonb for PostgreSQL |
| Navigation property | relationship |
relationship: {...} |
One-to-many, many-to-many inverse side |
Varchar Length Standards (Byte-Optimized)
IMPORTANT: When defining varchar fields, ALWAYS use one of these standard lengths.
These lengths are optimized for PostgreSQL byte storage efficiency:
| Length | Use Case Examples | Notes |
|---|---|---|
| 1 | Single character flags, gender (M/F) | Minimum length |
| 4 | Country codes (US, ES), file extensions | ISO codes |
| 8 | Short codes, abbreviations | Currency codes with margin |
| 16 | Short identifiers, codes | 2^4 bytes |
| 36 | UUIDs in string format | Standard UUID length (8-4-4-4-12) |
| 64 | Short names, usernames, slugs | 2^6 bytes |
| 128 | Names, titles, email addresses | 2^7 bytes |
| 255 | Standard text fields | 2^8 - 1 (single byte length indicator) |
| 382 | Medium text, short descriptions | 1.5 × 255 (optimized for UTF-8) |
| 510 | Longer descriptions, addresses | 2 × 255 |
| 1022 | Long text that needs indexing | ~4 × 255 (max recommended for indexes) |
| 2046 | URLs, very long text with length limit | Max practical URL length (~2048 limit) |
Why these specific lengths?
- Byte alignment: PostgreSQL stores varchar with a length prefix. These values optimize storage blocks.
- Index compatibility: Lengths ≤ 2046 can be indexed efficiently in PostgreSQL.
- UTF-8 consideration: Lengths account for multi-byte characters (up to 4 bytes per char).
- URL compatibility: 2046 is just under the 2048 practical limit for URLs (IE/Edge limit, SEO sitemaps).
Selection guide:
# ❌ Bad - arbitrary lengths
- name: username
type: varchar
maxLength: 50
- name: description
type: varchar
maxLength: 500
# ✅ Good - byte-optimized lengths
- name: username
type: varchar
maxLength: 64
description: >
User's display name. Max 64 characters.
- name: description
type: varchar
maxLength: 510
description: >
Brief description of the item. Max 510 characters.
Quick reference for common fields:
| Field Type | Recommended Length |
|---|---|
| UUID as string | 36 |
| Username | 64 |
| 128 | |
| Name/Title | 128 |
| Phone | 64 |
| Short description | 255 |
| Address line | 255 |
| Medium description | 510 |
| Long description | 1022 |
| URL/Link | 2046 |
| Slug | 2046 |
ID Fields (CRITICAL RULE)
Fields of type id MUST NOT have a length property.
# ✅ CORRECT
- name: id
type: id
primaryKey: true
description: >
Unique identifier for the record. UUID v4 format, generated automatically on
creation.
# ❌ INCORRECT - Remove length property
- name: id
type: id
length: 36 # ← DELETE THIS
primaryKey: true
Relationship Fields (CRITICAL RULE)
| Side | Has FK? | Use |
|---|---|---|
| Child/Many (invoice-line) | YES | type: id + relationship block inside |
| Parent/One (invoice) | NO | type: relationship (navigation only) |
| Many-to-many | NO | type: relationship + pivot config |
⚠️ NEVER define both invoiceId (type: id) AND invoice (type: relationship)
in the SAME module.
# ✅ child.aurora.yaml - ONLY the FK field
- name: parentId
type: id
relationship:
type: many-to-one
field: parent
aggregateName: MyParent
modulePath: my-context/parent
# ✅ parent.aurora.yaml - ONLY the navigation property
- name: children
type: relationship
relationship:
type: one-to-many
aggregateName: MyChild
modulePath: my-context/child
key: parentId
Error when duplicated:
TypeError: config.propertyTypesEquivalenceSequelizeTypes[property.type] is not a function
Cross-Module Consistency
Use the same field names across ALL modules for common concepts:
# Standard across all modules:
- name: id # Not: ID, _id, uuid, identifier
- name: createdAt # Not: created, createdDate, createTime
- name: updatedAt # Not: updated, modifiedAt, updateTime
- name: deletedAt # Not: deleted, removedAt, deletionDate
- name: isActive # Not: active, enabled, status
Analysis Workflow
1. Locate YAML Files
# Find all Aurora YAMLs
fd -e yaml -e yml aurora
# Find specific module
fd "book.aurora.yaml"
2. Read and Analyze
Check for:
- Module has
descriptionbeforeaggregateProperties - All fields have meaningful descriptions
- Field names follow conventions (camelCase, boolean prefixes)
- No
idtype fields havelengthproperty - Descriptions explain WHY, not WHAT
- Enum values are documented
- Types are appropriate for use case
- Consistency with similar modules
- No duplicate relationship definitions (FK + type:relationship in same module)
3. Generate Report
## Analysis of [module].aurora.yaml
### Summary
- Total fields: X
- Fields without description: Y
- Naming improvements needed: Z
- Module has description: Yes/No
### Module Description ❌ (if missing)
**Suggested:**
```yaml
description: >
[Purpose and role within bounded context]
```
Fields Without Description ❌
| Field | Type | Suggested Description |
|---|---|---|
| ... | ... | ... |
Naming Improvements ⚠️
| Current | Suggested | Reason |
|---|---|---|
| dt | createdAt | Ambiguous abbreviation |
| active | isActive | Boolean convention |
Type Issues ⚠️
| Field | Issue | Fix |
|---|---|---|
| id | Has length: 36 |
Remove length property |
---
## Editing Workflow
### Creating Fields
```yaml
- name: publishedAt
type: timestamp
nullable: true
description: >
Timestamp when the book was published. NULL indicates unpublished.
Automatically set when status changes to PUBLISHED.
Checklist:
- Name follows camelCase convention
- Boolean names have is*/has*/can* prefix
- Type is appropriate for use case
- Description explains context and usage
- No
lengthproperty onidtype fields - Consistent with similar fields in other modules
Editing Fields
Only modify requested attributes:
# Before
- name: status
type: varchar
# After (changing to enum)
- name: status
type: enum
enumOptions: [DRAFT, PUBLISHED, ARCHIVED]
description: >
Current publication status. DRAFT: Not ready. PUBLISHED: Available to
readers. ARCHIVED: Preserved but no longer available.
Deleting Fields
Always check dependencies first:
# Search for field references
rg "fieldName" cliter/ -g "*.aurora.yaml"
If field is referenced in relationships:
- Alert the user
- Confirm deletion
- Document affected modules
Common Patterns
Status Fields with Enum
- name: status
type: enum
enumOptions: [PENDING, APPROVED, REJECTED, CANCELLED]
defaultValue: PENDING
description: >
Workflow status. PENDING: Awaiting review. APPROVED: Accepted and active.
REJECTED: Denied (see rejectionReason). CANCELLED: Withdrawn by user.
Soft Delete Pattern
- name: deletedAt
type: timestamp
nullable: true
description: >
Soft delete timestamp. NULL means active record. When set, record is
excluded from normal queries. Enables audit trail and recovery.
Money Fields
- name: amount
type: decimal
decimals: [12, 2]
description: >
Monetary amount in smallest currency unit with 2 decimal places. Currency
determined by currencyCode field.
- name: currencyCode
type: char
length: 3
description: >
ISO 4217 currency code (USD, EUR, GBP). Must be valid and supported.
Sort Order Fields
- name: sort
type: smallint
unsigned: true
nullable: true
description: >
Sort order for displaying records in user interfaces. Lower numbers appear
first. NULL indicates no specific order preference (alphabetical fallback).
Used to prioritize items in selection lists and forms.
Note: Always use sort instead of displayOrder, order, position, or
sortOrder.
URL-Friendly Slugs
- name: slug
type: varchar
maxLength: 2046
index: unique
description: >
URL-friendly identifier. Lowercase, hyphenated. Auto-generated from name if
not provided. Example: "my-awesome-product". Max 2046 chars for URL
compatibility.
Commands
# Find all Aurora YAMLs
fd -e yaml aurora
# Search for fields without descriptions
rg -A1 "^ - name:" cliter/ -g "*.aurora.yaml" | rg -v "description:"
# Find id fields with length (incorrect)
rg -A2 "type: id" cliter/ -g "*.aurora.yaml" | rg "length:"
# Check for missing module descriptions
rg -L "^description:" cliter/ -g "*.aurora.yaml"
# Search for field usage across modules
rg "fieldName" cliter/ -g "*.aurora.yaml"
# Find potential duplicate relationships (type: relationship on many-to-one side)
rg -B5 "type: relationship" cliter/ -g "*.aurora.yaml" | rg -A1 "type: many-to-one"
# Validate YAML syntax
yamllint cliter/**/*.aurora.yaml
Decision Trees
Should I Edit or Just Analyze?
User explicitly requested edit? ────YES───> Edit mode
│
NO
│
Is this an analysis request? ────YES───> Analysis mode
│
NO
│
Ask user for clarification
What Type Should This Field Be?
Is it a UUID identifier? ────YES───> type: id (NO length!)
│
NO
│
Is it true/false? ────YES───> type: boolean (use is*/has*/can* prefix)
│
NO
│
Is it money? ────YES───> type: decimal with decimals: [12, 2]
│
NO
│
Fixed set of options? ────YES───> type: enum with enumOptions
│
NO
│
Date and time? ────YES───> type: timestamp
│
NO
│
Short text (< 255 chars)? ────YES───> type: varchar with maxLength
│
NO
│
Long text? ────YES───> type: text
│
NO
│
Review use case and choose appropriate type
Anti-Patterns to Avoid
| ❌ Don't | ✅ Do |
|---|---|
| Skip module description | Always add description before aggregateProperties |
| Use abbreviations (dt, qty, amt) | Use full words (createdAt, quantity, amount) |
| Name booleans without prefix (active) | Use semantic prefix (isActive, hasPermission) |
Add length to id type fields |
Never specify length for id type |
| Write "The price" as description | Explain context: "Retail price in base currency..." |
| Mix naming styles across modules | Use consistent names (createdAt everywhere) |
Use float for money |
Always use decimal with proper scale |
| Leave enum values undocumented | Explain what each enum option means |
| Duplicate relationship definitions | FK side uses type: id, inverse uses type: relationship |
Add type: relationship on many-to-one side |
Only use on parent/one-to-many side |
Change Log Template
When making modifications:
## Schema Changes - 2026-01-17
### tesla/model.aurora.yaml
#### Created
- `isActive` (boolean) - Flag to indicate if model is currently available
#### Modified
- `status`: Changed type from `varchar` to `enum` with options [ACTIVE,
INACTIVE, DISCONTINUED]
- Module: Added `description` property explaining module purpose
#### Deleted
- `legacyCode` (varchar) - Removed after confirming no dependencies
#### Fixed
- `id`: Removed `length: 36` property (not needed for id type)
Resources
-
Aurora Docs: Check
aurora-cliskill for regeneration commands -
Project Structure: Use
aurora-project-structureskill to locate YAMLs -
YAML Syntax: Run
yamllintto validate syntax -
Cross-References: Search with
rgto find field usage
Related Skills
| Skill | When to Use Together |
|---|---|
aurora-cli |
After editing YAML, regenerate with aurora load back module |
aurora-project-structure |
To locate YAML files in correct directories |
conventional-commits |
When committing schema changes |
typescript |
When reviewing generated TypeScript from YAML |
aurora-cqrs |
Understanding how YAML generates commands/queries |
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!