Data Architecture & Persistence Layer
Analyze the project to document database configuration, entity models, data ownership boundaries, repository interfaces, and caching strategies. Generate a Mermaid ER diagram showing entity relationships. Save to .github/modernize/assessment/engines/facts/data-architecture.md.
Input Parameters
workspace-path (optional): Path to the project to analyze (defaults to current directory)
⚠ Mermaid Safety Constraints — read BEFORE you write the ```mermaid block
Mermaid erDiagram has a stricter grammar than flowchart. One bad attribute line or one stray { crashes the whole diagram with Syntax error in text. Stay strictly inside this subset:
Chart kind. erDiagram only.
Attribute grammar — exact shape. Every attribute line inside an entity body MUST match:
<type> <name> [<key>] ["<description>"]
<type> / <name>: single tokens, plain text (letters, digits, underscore). No spaces, no backticks, no @#$%&.
<key>: optional. Exactly one of PK, FK, UK — never two, never combined. Compound tokens like PK_FK, PKFK, PK/FK crash the parser.
<description>: optional, must be a double-quoted string on one line. Free text, but obey rule 4.
Relationships. <EntityA> <leftCard>--<rightCard> <EntityB> : "label". Each side independently picks || (exactly one), |o/o| (zero or one), }o/o{ (zero or many), or }|/|{ (one or many). The open side of o/}/{ faces inward toward --. Always quote the label.
Banned characters inside any quoted description or relationship label:
| Banned |
Why it breaks |
Replacement |
\n (literal two chars) |
escape removed |
drop, or shorten |
{ } |
opens an entity block |
use <...> for placeholders, e.g. "Redis key /basket/<BuyerId>" |
" (a second double-quote) |
closes description early |
' (single quote) |
` (backtick) |
not part of grammar |
drop |
— – (em/en dash) |
parser may treat as edge |
- (ASCII hyphen) |
smart quotes " " ' ' |
not ASCII |
regular " and ' |
@ # $ % & |
unsafe in names/descriptions |
rephrase or drop |
Composite PK that is also FK. Mark every column as PK only and note the FK role inside the quoted description. The FK relationship is already shown by the cardinality arrow — duplicating it as a second key marker crashes the parser.
Canonical attribute examples (copy these shapes)
int Id PK
string Name
int OwnerId FK
int InstructorId PK "also FK to Person (shared PK)"
int CourseId PK "composite PK; FK to Course"
int StudentId PK "composite PK; FK to Person"
string Email UK "unique"
decimal Budget "money column"
bytes RowVersion "concurrency token"
Mandatory self-attestation
Immediately before writing the ```mermaid opening fence, emit this exact one-line HTML comment in the markdown (it does not render — it is for your own visible attestation):
<!-- mermaid-checked: every attribute is `<type> <name> [<key>] ["<description>"]` with at most one of PK/FK/UK, no \n in descriptions, no {} in descriptions, every relationship label is double-quoted -->
If you cannot truthfully emit that comment, fix the diagram first.
Scope Boundaries — Avoid Redundancy with Other Skills
This skill is part of a set of four complementary assessment skills. To avoid content duplication across their output documents, observe these scope rules:
- Introduction: Write a 1-2 sentence intro focused on the data layer (number of entities, database types, ORM). Do NOT restate the application's overall architecture type, web framework, or API surface — those are covered by other skills.
- Configuration property keys/values (e.g.,
spring.jpa.hibernate.ddl-auto, spring.sql.init.*) are owned by the configuration-inventory skill. In the Database Configuration table, describe the behavior (e.g., "Hibernate does not manage schema; SQL scripts are authoritative") but do NOT list raw property key-value pairs. Reference configuration-inventory.md for the full property inventory.
- API endpoints and HTTP methods are owned by the
api-service-contracts skill. Do NOT list controller endpoints or HTTP paths. Repository methods are in scope for this skill; controller routes are not.
- Business workflow steps and validation rules are owned by the
business-workflows skill. Do NOT describe multi-step business processes or enumerate validation constraints. When documenting entity relationships (cascade, fetch), focus on the persistence/ORM implications, not the business process flow.
- Deployment configurations (Docker Compose, K8s, profiles) are owned by the
configuration-inventory skill. Mention database profiles only in the Database Configuration table to identify which DB is used per profile — do NOT describe Docker Compose services, K8s manifests, or deployment targets in detail.
Execution Steps
Step 1: Generate Database Configuration Section
Extract database configuration from project files, per profile/environment, and produce the complete ## Database Configuration section:
- Database types: HSQLDB, MySQL, PostgreSQL, MongoDB, SQL Server, Oracle, SQLite, CosmosDB, DynamoDB
- Per-profile configuration: identify which database is used in each profile (e.g., HSQLDB for
default/dev in-memory testing, MySQL for production/mysql profile)
- Database drivers per profile (e.g.,
mysql-connector-java for production, hsqldb for development)
- Connection configuration: connection strings, JDBC URLs, pooling settings (HikariCP, connection pool size)
- Migration tools: Flyway, Liquibase, EF Migrations, Alembic, Prisma Migrate, Knex migrations
- Schema management: DDL auto-generation settings (
spring.jpa.hibernate.ddl-auto), schema versioning, initial schema scripts
- Seed data:
data.sql, import.sql, seed migration files, or programmatic data seeding
Step 2: Generate Data Ownership per Service Section
Determine table/entity ownership across modules/services and produce the complete ## Data Ownership per Service section. Scope is strictly the per-service ownership table — high-level data boundary discussion belongs in Step 6.
For each module/service, identify:
- Which tables/entities it owns (bounded context analysis)
- ORM framework used (e.g., Hibernate, EF Core, MyBatis, Mongoose)
- Caching layer used by this service (if any)
- Brief notes (e.g., outbox table, schema-per-service)
Do NOT include shared-vs-isolated data store summary, cross-service data access patterns, or read/write/CQRS observations here — those belong in the ## Data Ownership Boundaries section (Step 6).
Step 3: Generate Entity Model Section
Scan source code for data access patterns and ORM entities, then produce the complete ## Entity Model section:
Analysis:
- Java: JPA/Hibernate entities (
@Entity, @Table), Spring Data repositories (JpaRepository, CrudRepository), MyBatis mappers, JDBC templates
- .NET: EF Core
DbContext, EF Core entities, Dapper, ADO.NET
- JavaScript/TypeScript: Mongoose models/schemas, Sequelize models, TypeORM entities, Prisma schema, Knex migrations
Identify:
- Entity/model classes with their fields, types, and constraints — note the source file path for each entity
- Transaction management annotations/configuration (
@Transactional, TransactionScope, etc.)
- Bidirectional vs unidirectional relationship mappings (e.g.,
owner.addPet(pet) establishing parent-child links)
Diagram — Mermaid erDiagram:
- Show primary entities with key fields (PK, FK)
- Use standard cardinality notation:
||--o{ (one-to-many), ||--|| (one-to-one), }o--o{ (many-to-many)
- Group related entities logically
- Include relationship labels
- Annotate which service owns each entity group (use comments or subgraph labels)
Reference example (this block satisfies every Safety Constraint — match its shape):
erDiagram
Owner ||--o{ Pet : "has"
Pet ||--o{ Visit : "has"
Pet }o--|| PetType : "is of"
Vet }o--o{ Specialty : "has"
Owner {
int id PK
string firstName
string lastName
string address
string city
string telephone
}
Pet {
int id PK
string name
date birthDate
int ownerId FK
int typeId FK
}
PetType {
int id PK
string name
}
Visit {
int id PK
int petId FK
date visitDate
string description
}
Vet {
int id PK
string firstName
string lastName
}
Specialty {
int id PK
string name
}
Step 4: Generate Key Repository Methods Section
For each service/module, document the key repository interfaces and produce the complete ## Key Repository Methods section:
- Repository interface name, entity type, and source file path
- Standard CRUD methods inherited from base interface
- Custom query methods with their signatures and purposes — especially:
- Bulk/batch queries (e.g.,
findByPetIdIn(Collection<Integer>)) used for cross-service aggregation
- Custom finders with derived query methods
- Named queries or
@Query-annotated methods
- Raw SQL or stored procedure calls
- Query method parameters and return types
Step 5: Generate Caching Strategy Section
Identify caching layers and configuration and produce the complete ## Caching Strategy section:
- Cache providers: EhCache, Redis, Caffeine, Spring Cache (
@Cacheable, @CacheEvict), MemoryCache, IDistributedCache
- Cache configuration: TTL, eviction policies, cache regions/names
- Cache-aside, read-through, write-through, write-behind patterns
- Session caching, query result caching, second-level cache (Hibernate)
- Rationale for caching decisions (e.g., "veterinarian data is read frequently but changes rarely")
- JSR-107 (JCache) /
cache-api usage and provider binding
Step 6: Generate Data Ownership Boundaries Section
Document data-store topology and cross-service access semantics, plus data classification, then produce the complete ## Data Ownership Boundaries section (including the ### Data Classification & Sensitivity subsection):
Boundaries:
- Shared vs isolated data stores (shared database, database-per-service, logical separation within shared DB)
- Cross-service data access patterns: how one service queries another service's data (direct DB access vs REST API calls vs batch/bulk query methods such as
findByPetIdIn(...) that enable gateway-level aggregation)
- Read/write patterns and CQRS observations across services
Data Classification & Sensitivity (### Data Classification & Sensitivity subsection):
- Identify whether stored data contains sensitive categories — PII (names, addresses, phone numbers, emails), PHI (health records), PCI (payment card data)
- For each sensitive category found, note whether encryption-at-rest, data masking, or field-level access controls are in place
- If absent, state this explicitly (e.g., "Owner entity stores PII (firstName, lastName, address, telephone); no encryption-at-rest or masking configured")
Step 7: Save Output
Save to .github/modernize/assessment/engines/facts/data-architecture.md with this exact structure:
# Data Architecture & Persistence Layer
A brief introduction (1-2 sentences) summarizing the data layer.
## Database Configuration
[Table: Service/Module | DB Type | Profile | Driver | Connection | Migration Tool]
## Data Ownership per Service
[Table: Service | Tables Owned | ORM Framework | Caching | Notes]
## Entity Model
< Mermaid erDiagram here >
## Key Repository Methods
[Table: Service | Repository | Notable Methods | Purpose]
## Caching Strategy
[Table or description of caching layers, providers, TTL, patterns, and rationale]
## Data Ownership Boundaries
[Description of shared vs isolated data stores, cross-service data access patterns, and aggregation enablers]
### Data Classification & Sensitivity
[Table: Entity | Sensitive Fields | Classification (PII/PHI/PCI/None) | Controls in Place]
[If no sensitive data found: "No PII, PHI, or PCI data detected in entity model."]
Scaling Rules
- If the project has more than 30 entities, aggregate minor entities and show only the core domain model (15-20 key entities)
- Keep the ER diagram under 40 entities to ensure readability and GitHub rendering compatibility
- For multi-module projects, focus on inter-module entity relationships and data boundaries
- Collapse join tables into relationship annotations rather than showing them as separate entities
- In the repository methods table, focus on non-CRUD custom methods; omit standard inherited methods
Common failure patterns observed in past runs
Each row below is something the model actually produced that crashed the diagram. Use the ✅ form.
| ❌ Past mistake |
✅ Safe form |
Why the ❌ crashed |
int OwnerId PK_FK |
int OwnerId PK "FK to Owner" |
Compound key marker is not in grammar |
int OwnerId PK FK |
int OwnerId PK "also FK to Owner" |
Two key markers on one line |
string Key PK "Redis key /basket/{BuyerId}" |
string Key PK "Redis key /basket/<BuyerId>" |
{ opens an entity block even inside quotes |
string Roles "comma-separated\nROLE_USER, ROLE_ADMIN" |
string Roles "comma-separated; ROLE_USER, ROLE_ADMIN" |
Literal \n |
string user-name |
string userName |
- not allowed in attribute name |
| `Owner |
|
--o{ Pet : has` |
Error Handling
- Unsupported project type: Output a single line:
> ERROR: Unsupported project type. This skill supports Java, .NET, JavaScript, and TypeScript projects only.
- No data access layer found: Output:
> ERROR: No recognized data access patterns or entities found at workspace-path. Verify the path is correct.
- Insufficient info: Generate a best-effort diagram from available data. Add a note:
> Note: Some entities or relationships could not be fully identified.
Success Criteria
- Database configuration table lists all discovered databases with type, profile, driver, and migration tools
- Data ownership table maps each service to its owned tables, ORM, and caching layer
- Mermaid ER diagram renders correctly showing entity relationships with cardinality and key fields
- Repository methods table documents custom query methods with purposes, especially cross-service aggregation enablers
- Caching strategy section describes cache providers, patterns, and rationale
- Data ownership boundaries describe shared vs isolated stores and cross-service data access patterns
- Data Classification & Sensitivity table identifies PII/PHI/PCI fields and documents presence or absence of controls
- The ```mermaid block is preceded by the
<!-- mermaid-checked: ... --> attestation comment
- File saved to
.github/modernize/assessment/engines/facts/data-architecture.md
1---2name: data-architecture3description: Generate data architecture and persistence layer documentation with data model diagram4---56# Data Architecture & Persistence Layer78Analyze the project to document database configuration, entity models, data ownership boundaries, repository interfaces, and caching strategies. Generate a Mermaid ER diagram showing entity relationships. Save to `.github/modernize/assessment/engines/facts/data-architecture.md`.910## Input Parameters1112- `workspace-path` (optional): Path to the project to analyze (defaults to current directory)1314## ⚠ Mermaid Safety Constraints — read BEFORE you write the ```mermaid block1516Mermaid `erDiagram` has a stricter grammar than flowchart. One bad attribute line or one stray `{` crashes the **whole** diagram with `Syntax error in text`. Stay strictly inside this subset:17181. **Chart kind.** `erDiagram` only.192. **Attribute grammar — exact shape.** Every attribute line inside an entity body MUST match:2021 ```22 <type> <name> [<key>] ["<description>"]23 ```2425 - `<type>` / `<name>`: single tokens, plain text (letters, digits, underscore). No spaces, no backticks, no `@#$%&`.26 - `<key>`: optional. **Exactly one of** `PK`, `FK`, `UK` — never two, never combined. Compound tokens like `PK_FK`, `PKFK`, `PK/FK` crash the parser.27 - `<description>`: optional, must be a double-quoted string on one line. Free text, but obey rule 4.283. **Relationships.** `<EntityA> <leftCard>--<rightCard> <EntityB> : "label"`. Each side independently picks `||` (exactly one), `|o`/`o|` (zero or one), `}o`/`o{` (zero or many), or `}|`/`|{` (one or many). The open side of `o`/`}`/`{` faces inward toward `--`. Always quote the label.294. **Banned characters inside any quoted description or relationship label:**3031 | Banned | Why it breaks | Replacement |32 |---|---|---|33 | `\n` (literal two chars) | escape removed | drop, or shorten |34 | `{` `}` | opens an entity block | use `<...>` for placeholders, e.g. `"Redis key /basket/<BuyerId>"` |35 | `"` (a second double-quote) | closes description early | `'` (single quote) |36 | `` ` `` (backtick) | not part of grammar | drop |37 | `—` `–` (em/en dash) | parser may treat as edge | `-` (ASCII hyphen) |38 | smart quotes `"` `"` `'` `'` | not ASCII | regular `"` and `'` |39 | `@` `#` `$` `%` `&` | unsafe in names/descriptions | rephrase or drop |40415. **Composite PK that is also FK.** Mark every column as `PK` only and note the FK role inside the quoted description. The FK relationship is already shown by the cardinality arrow — duplicating it as a second key marker crashes the parser.4243### Canonical attribute examples (copy these shapes)4445```46int Id PK47string Name48int OwnerId FK49int InstructorId PK "also FK to Person (shared PK)"50int CourseId PK "composite PK; FK to Course"51int StudentId PK "composite PK; FK to Person"52string Email UK "unique"53decimal Budget "money column"54bytes RowVersion "concurrency token"55```5657### Mandatory self-attestation5859Immediately before writing the ` ```mermaid ` opening fence, emit this exact one-line HTML comment in the markdown (it does not render — it is for your own visible attestation):6061```62<!-- mermaid-checked: every attribute is `<type> <name> [<key>] ["<description>"]` with at most one of PK/FK/UK, no \n in descriptions, no {} in descriptions, every relationship label is double-quoted -->63```6465If you cannot truthfully emit that comment, fix the diagram first.6667---6869## Scope Boundaries — Avoid Redundancy with Other Skills7071This skill is part of a set of four complementary assessment skills. To avoid content duplication across their output documents, observe these scope rules:7273- **Introduction**: Write a 1-2 sentence intro focused on the data layer (number of entities, database types, ORM). Do NOT restate the application's overall architecture type, web framework, or API surface — those are covered by other skills.74- **Configuration property keys/values** (e.g., `spring.jpa.hibernate.ddl-auto`, `spring.sql.init.*`) are owned by the `configuration-inventory` skill. In the Database Configuration table, describe the *behavior* (e.g., "Hibernate does not manage schema; SQL scripts are authoritative") but do NOT list raw property key-value pairs. Reference `configuration-inventory.md` for the full property inventory.75- **API endpoints and HTTP methods** are owned by the `api-service-contracts` skill. Do NOT list controller endpoints or HTTP paths. Repository methods are in scope for this skill; controller routes are not.76- **Business workflow steps and validation rules** are owned by the `business-workflows` skill. Do NOT describe multi-step business processes or enumerate validation constraints. When documenting entity relationships (cascade, fetch), focus on the persistence/ORM implications, not the business process flow.77- **Deployment configurations** (Docker Compose, K8s, profiles) are owned by the `configuration-inventory` skill. Mention database profiles only in the Database Configuration table to identify which DB is used per profile — do NOT describe Docker Compose services, K8s manifests, or deployment targets in detail.7879## Execution Steps8081### Step 1: Generate Database Configuration Section8283Extract database configuration from project files, **per profile/environment**, and produce the complete `## Database Configuration` section:8485- Database types: HSQLDB, MySQL, PostgreSQL, MongoDB, SQL Server, Oracle, SQLite, CosmosDB, DynamoDB86- **Per-profile configuration**: identify which database is used in each profile (e.g., HSQLDB for `default`/dev in-memory testing, MySQL for `production`/`mysql` profile)87- Database drivers per profile (e.g., `mysql-connector-java` for production, `hsqldb` for development)88- Connection configuration: connection strings, JDBC URLs, pooling settings (HikariCP, connection pool size)89- Migration tools: Flyway, Liquibase, EF Migrations, Alembic, Prisma Migrate, Knex migrations90- Schema management: DDL auto-generation settings (`spring.jpa.hibernate.ddl-auto`), schema versioning, initial schema scripts91- Seed data: `data.sql`, `import.sql`, seed migration files, or programmatic data seeding9293### Step 2: Generate Data Ownership per Service Section9495Determine table/entity ownership across modules/services and produce the complete `## Data Ownership per Service` section. Scope is strictly the per-service ownership table — high-level data boundary discussion belongs in Step 6.9697For each module/service, identify:9899- Which tables/entities it owns (bounded context analysis)100- ORM framework used (e.g., Hibernate, EF Core, MyBatis, Mongoose)101- Caching layer used by this service (if any)102- Brief notes (e.g., outbox table, schema-per-service)103104> Do NOT include shared-vs-isolated data store summary, cross-service data access patterns, or read/write/CQRS observations here — those belong in the `## Data Ownership Boundaries` section (Step 6).105106### Step 3: Generate Entity Model Section107108Scan source code for data access patterns and ORM entities, then produce the complete `## Entity Model` section:109110**Analysis:**111- Java: JPA/Hibernate entities (`@Entity`, `@Table`), Spring Data repositories (`JpaRepository`, `CrudRepository`), MyBatis mappers, JDBC templates112- .NET: EF Core `DbContext`, EF Core entities, Dapper, ADO.NET113- JavaScript/TypeScript: Mongoose models/schemas, Sequelize models, TypeORM entities, Prisma schema, Knex migrations114115Identify:116- Entity/model classes with their fields, types, and constraints — note the source file path for each entity117- Transaction management annotations/configuration (`@Transactional`, `TransactionScope`, etc.)118- Bidirectional vs unidirectional relationship mappings (e.g., `owner.addPet(pet)` establishing parent-child links)119120**Diagram — Mermaid `erDiagram`:**121- Show primary entities with key fields (PK, FK)122- Use standard cardinality notation: `||--o{` (one-to-many), `||--||` (one-to-one), `}o--o{` (many-to-many)123- Group related entities logically124- Include relationship labels125- Annotate which service owns each entity group (use comments or subgraph labels)126127Reference example (this block satisfies every Safety Constraint — match its shape):128129<!-- mermaid-checked: every attribute is `<type> <name> [<key>] ["<description>"]` with at most one of PK/FK/UK, no \n in descriptions, no {} in descriptions, every relationship label is double-quoted -->130~~~mermaid131erDiagram132 Owner ||--o{ Pet : "has"133 Pet ||--o{ Visit : "has"134 Pet }o--|| PetType : "is of"135 Vet }o--o{ Specialty : "has"136 Owner {137 int id PK138 string firstName139 string lastName140 string address141 string city142 string telephone143 }144 Pet {145 int id PK146 string name147 date birthDate148 int ownerId FK149 int typeId FK150 }151 PetType {152 int id PK153 string name154 }155 Visit {156 int id PK157 int petId FK158 date visitDate159 string description160 }161 Vet {162 int id PK163 string firstName164 string lastName165 }166 Specialty {167 int id PK168 string name169 }170~~~171172### Step 4: Generate Key Repository Methods Section173174For each service/module, document the key repository interfaces and produce the complete `## Key Repository Methods` section:175176- Repository interface name, entity type, and source file path177- Standard CRUD methods inherited from base interface178- Custom query methods with their signatures and purposes — especially:179 - Bulk/batch queries (e.g., `findByPetIdIn(Collection<Integer>)`) used for cross-service aggregation180 - Custom finders with derived query methods181 - Named queries or `@Query`-annotated methods182 - Raw SQL or stored procedure calls183- Query method parameters and return types184185### Step 5: Generate Caching Strategy Section186187Identify caching layers and configuration and produce the complete `## Caching Strategy` section:188189- Cache providers: EhCache, Redis, Caffeine, Spring Cache (`@Cacheable`, `@CacheEvict`), MemoryCache, IDistributedCache190- Cache configuration: TTL, eviction policies, cache regions/names191- Cache-aside, read-through, write-through, write-behind patterns192- Session caching, query result caching, second-level cache (Hibernate)193- Rationale for caching decisions (e.g., "veterinarian data is read frequently but changes rarely")194- JSR-107 (JCache) / `cache-api` usage and provider binding195196### Step 6: Generate Data Ownership Boundaries Section197198Document data-store topology and cross-service access semantics, plus data classification, then produce the complete `## Data Ownership Boundaries` section (including the `### Data Classification & Sensitivity` subsection):199200**Boundaries:**201- Shared vs isolated data stores (shared database, database-per-service, logical separation within shared DB)202- Cross-service data access patterns: how one service queries another service's data (direct DB access vs REST API calls vs batch/bulk query methods such as `findByPetIdIn(...)` that enable gateway-level aggregation)203- Read/write patterns and CQRS observations across services204205**Data Classification & Sensitivity (`### Data Classification & Sensitivity` subsection):**206- Identify whether stored data contains sensitive categories — PII (names, addresses, phone numbers, emails), PHI (health records), PCI (payment card data)207- For each sensitive category found, note whether encryption-at-rest, data masking, or field-level access controls are in place208- If absent, state this explicitly (e.g., "Owner entity stores PII (firstName, lastName, address, telephone); no encryption-at-rest or masking configured")209210### Step 7: Save Output211212Save to `.github/modernize/assessment/engines/facts/data-architecture.md` with this exact structure:213214```215# Data Architecture & Persistence Layer216217A brief introduction (1-2 sentences) summarizing the data layer.218219## Database Configuration220221[Table: Service/Module | DB Type | Profile | Driver | Connection | Migration Tool]222223## Data Ownership per Service224225[Table: Service | Tables Owned | ORM Framework | Caching | Notes]226227## Entity Model228229< Mermaid erDiagram here >230231## Key Repository Methods232233[Table: Service | Repository | Notable Methods | Purpose]234235## Caching Strategy236237[Table or description of caching layers, providers, TTL, patterns, and rationale]238239## Data Ownership Boundaries240241[Description of shared vs isolated data stores, cross-service data access patterns, and aggregation enablers]242243### Data Classification & Sensitivity244245[Table: Entity | Sensitive Fields | Classification (PII/PHI/PCI/None) | Controls in Place]246[If no sensitive data found: "No PII, PHI, or PCI data detected in entity model."]247```248249## Scaling Rules250251- If the project has **more than 30 entities**, aggregate minor entities and show only the core domain model (15-20 key entities)252- Keep the ER diagram under **40 entities** to ensure readability and GitHub rendering compatibility253- For multi-module projects, focus on inter-module entity relationships and data boundaries254- Collapse join tables into relationship annotations rather than showing them as separate entities255- In the repository methods table, focus on non-CRUD custom methods; omit standard inherited methods256257## Common failure patterns observed in past runs258259Each row below is something the model actually produced that crashed the diagram. Use the ✅ form.260261| ❌ Past mistake | ✅ Safe form | Why the ❌ crashed |262|---|---|---|263| `int OwnerId PK_FK` | `int OwnerId PK "FK to Owner"` | Compound key marker is not in grammar |264| `int OwnerId PK FK` | `int OwnerId PK "also FK to Owner"` | Two key markers on one line |265| `string Key PK "Redis key /basket/{BuyerId}"` | `string Key PK "Redis key /basket/<BuyerId>"` | `{` opens an entity block even inside quotes |266| `string Roles "comma-separated\nROLE_USER, ROLE_ADMIN"` | `string Roles "comma-separated; ROLE_USER, ROLE_ADMIN"` | Literal `\n` |267| `string user-name` | `string userName` | `-` not allowed in attribute name |268| `Owner ||--o{ Pet : has` | `Owner ||--o{ Pet : "has"` | Relationship label must be quoted |269270## Error Handling271272- **Unsupported project type**: Output a single line: `> ERROR: Unsupported project type. This skill supports Java, .NET, JavaScript, and TypeScript projects only.`273- **No data access layer found**: Output: `> ERROR: No recognized data access patterns or entities found at workspace-path. Verify the path is correct.`274- **Insufficient info**: Generate a best-effort diagram from available data. Add a note: `> Note: Some entities or relationships could not be fully identified.`275276## Success Criteria277278- Database configuration table lists all discovered databases with type, profile, driver, and migration tools279- Data ownership table maps each service to its owned tables, ORM, and caching layer280- Mermaid ER diagram renders correctly showing entity relationships with cardinality and key fields281- Repository methods table documents custom query methods with purposes, especially cross-service aggregation enablers282- Caching strategy section describes cache providers, patterns, and rationale283- Data ownership boundaries describe shared vs isolated stores and cross-service data access patterns284- Data Classification & Sensitivity table identifies PII/PHI/PCI fields and documents presence or absence of controls285- The ```mermaid block is preceded by the `<!-- mermaid-checked: ... -->` attestation comment286- File saved to `.github/modernize/assessment/engines/facts/data-architecture.md`