Skip to content
Back to skills

Db Aspect Extraction

ASecurity

Extracts a repository's database schema (tables, columns, foreign keys, indexes) into a DatabaseSchemaPayload for /adopt --db. Use when adopting the database.schema aspect. Reads Drizzle, Prisma, TypeORM, SQLAlchemy, raw SQL migrations, or a committed pg_dump — never a live database.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 25, 2026
databasesgosqlnodeexpressdatabase

Works with

  • claude code
  • cli

Security analysis

A100/100

Scanned September 25, 2026

npx -y skills add provenmap/pmap-claude --skill db-aspect-extraction --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Db Aspect Extraction?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Db Aspect Extraction
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/provenmap-db-aspect-extraction/badge)](https://www.skillsdirectory.com/skills/provenmap-db-aspect-extraction)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: db-aspect-extraction
user-invokable: false
description: Extracts a repository's database schema (tables, columns, foreign keys, indexes) into a DatabaseSchemaPayload for /adopt --db. Use when adopting the database.schema aspect. Reads Drizzle, Prisma, TypeORM, SQLAlchemy, raw SQL migrations, or a committed pg_dump — never a live database.
license: MIT
compatibility: Claude Code plugin. Requires a synced spine (.provenmap/boards/<board>.json) so tables can link to node slugs.
metadata:
  author: ProvenMap
  version: 0.1.0
---

# Database Schema Extraction (database.schema aspect)

Extract the **declared** schema and shape it into a `DatabaseSchemaPayload`:
`{ tables: [ { …table fields, columns[], foreignKeys[], indexes[], ownerSlug, references[] } ] }`.

## Golden rules

1. **Read definitions, never execute.** No app boot, no DB connection, no running migrations. Parse the source of truth: ORM schema files, migration SQL, or a committed `pg_dump`.
2. **`slug` is the stable identity.** One kebab-case slug per table (e.g. `orders`, `user_sessions` → `user-sessions`), stable across re-extracts — the server reconciles by it. Never re-slug an existing table.
3. **Leave human-tier fields empty.** Do **not** fill `owners`, `deprecated`, `dataClassification`, `piiRationale`, `description`, `usageNotes`, `textual`, `migrationHistory`, `ownershipNotes`. Those are the human's to annotate; the server strips them from ingest anyway (D4), so guessing PII only creates noise. Emit `null`/`[]`/`false` defaults.

## Sources, by ORM

| Source | Where the schema lives | Dialect / ORM |
| --- | --- | --- |
| **Drizzle** | `*.schema.ts` (`pgTable`, `mysqlTable`) | `postgres`/`mysql`, `drizzle` |
| **Prisma** | `schema.prisma` `model` blocks | per `datasource`, `prisma` |
| **TypeORM** | `@Entity` classes | per data-source, `typeorm` |
| **SQLAlchemy** | `Base`/`Table` models | per engine, `sqlalchemy` |
| **Raw migrations** | `CREATE TABLE` in `migrations/*.sql` | parse the DDL, `raw-sql` |
| **pg_dump** | committed `schema.sql` | `postgres`, `raw-sql` |

## Per-table fields

- `slug`, `name`, `schemaName` (default `public`), `dialect`, `orm`.
- `primaryKey`: ordered PK column names, or `null` if the table has none.
- `columns[]`: for each column — `ordinalPosition`, `name`, `type` (raw dialect spelling, verbatim), `logicalType` (the queryable semantic type: `string` | `integer` | `bigint` | `uuid` | `timestamp` | `boolean` | `json` | `enum` | `decimal` | …), `nullable`, `isPrimaryKey`, `isUnique`, `defaultValue`, `enumSlug` (for enum columns), `isComputed` + `generatedExpression` (for generated columns). Leave the human-tier column fields null.
- `foreignKeys[]`: `columns`, `referencesTableSlug` (the **slug** of the target table if it is in this schema), `referencesTableRaw` (the raw name if the target is outside the extract — this powers the "FK to a table we don't model" insight), `referencesColumns`, `onDelete`, `onUpdate`.
- `indexes[]`: `name`, `columns`, `unique`, `method` (`btree`/`gin`/…), `where` (partial-index predicate), `expression` (expression index body).

## Owner + references — linking to the spine (the important part)

Read `.provenmap/boards/<board-slug>.json` for the node `slug`s the spine already has. Every slug you emit must be one of them.

- **`ownerSlug`** — the node that *owns* the table: the repository / data-access module where the schema is defined (e.g. the `orders-repository` node for `orders`). If you can't confidently name one, omit it (`null`) — the server keeps `target_raw` and the D5 pass heals it later.
- **`references[]`** — every node that *uses* the table, one entry per usage: `{ nodeSlug, relation, evidence[] }`.
  - `relation`: `reads` | `writes` | `references`.
  - Find usages by grepping for the ORM's query calls (`db.select(...).from(orders)`, `prisma.orders.findMany`, `orderRepository.save`, raw `SELECT/INSERT ... orders`) and mapping the enclosing service/module to its node slug.
  - `evidence[]`: `{ file, line, snippet }` for each call site — this is what a human clicks through to verify the link.
  - A reference to a node the spine doesn't have yet is fine — emit the slug anyway; it lands unresolved (`node_raw`) and auto-resolves after the next `/sync`.

Prune `references` to real, evidenced usages. A table with no owner and no references still adopts fine (it just shows as unlinked until you enrich the spine).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…