Skip to content

Schema READMEs include foreign-schema enums; ruby-rails has no enums but lists 26 #303

Description

@WhatIfWeDigDeeper

Problem

Every per-schema README in docs/schema/*/README.md lists the union of every other stack's Postgres enum types in its ## Enums section, not just the enums defined by that schema.

Example: docs/schema/ruby-rails/README.md ## Enums shows 26 enum rows across 8 sibling schemas (express_prisma.*, graphql_yoga.*, java_spring.*, python_fastapi.*, react_koa.*, react_nestjs.*, svelte_hono.*, vue_nuxt.*) — none of which belong to the ruby_rails schema. Worse, ruby-rails defines zero Postgres enum types of its own (it uses VARCHAR(50) columns with model-level validates :inclusion checks in rails-api/app/models/job_application.rb:54-56). So the entire ## Enums table on that page is foreign noise that could mislead a reader into thinking values like accepted offer are DB-enforced enums for rails when they're actually string-validated at the Rails model layer.

The same noise appears in every other schema README too — they all show every enum from every schema.

Cause

scripts/generate-schema-docs.sh:69 invokes:

tbls doc "${DB_URL}" "${DOC_DIR}/${dir}" \
  --include "${schema}.*" \
  --er-format mermaid \
  --force

tbls's --include flag filters tables, not enum types. tbls enumerates pg_type across the whole connected database and emits every enum it finds into the README's ## Enums section regardless of schema. Since this is a single shared app_tracker DB with one schema per stack, every stack's enums are visible to every per-schema doc run.

Proposed fix

Two paths, pick one:

Option A — post-process (simpler, contained to one script)

Add a step after the existing Mermaid column-swap in scripts/generate-schema-docs.sh:

For each ${DOC_DIR}/${dir}/README.md:

  • Drop rows in the ## Enums table whose Name column does not start with ${schema}.
  • Drop the ## Enums heading and the empty table entirely if no rows remain after filtering.

A perl -i -0777 -pe one-liner per README, scoped to the section between ## Enums and the next ## heading, is enough.

Option B — per-schema .tbls.yml config (cleaner, more YAML)

Generate a temporary .tbls.yml per schema with dict.enums.exclude patterns matching every other schema's prefix, pass it to tbls doc via --config. More principled but adds 11 generated config files (or a single templated one with substitution).

Recommend A for the first pass — quicker to land, no new YAML to maintain, and it survives tbls behavior changes since the post-process is independent of the tool's internal filters.

Acceptance criteria

  • Each docs/schema/<stack>/README.md ## Enums section lists only enums from that stack's schema.
  • docs/schema/ruby-rails/README.md no longer has an ## Enums section (rails-api defines no Postgres enums).
  • All 11 schema READMEs regenerated and committed in the same PR so the diff is reviewable as the visible cleanup.
  • scripts/generate-schema-docs.sh continues to be safe to re-run.

Context

Surfaced during PR #300 (rails-api implementation) when reviewing the generated docs/schema/ruby-rails/README.md. The rails stack is a particularly clear illustration because it has no Postgres enums of its own, but the bug exists on every per-schema README in the repo.

Companion to #301 (CI workflow split) and #302 (cross-stack contract test promotion) — all three are monorepo-wide cleanups that the rails-api PR exposed but doesn't own.


Addendum (2026-05-03) — also covers cross-schema table bleed

A second tbls --include filter limit surfaced during PR #300 follow-up review (Copilot inline comment on docs/schema/react-nestjs/README.md):

scripts/generate-schema-docs.sh:69 passes --include "${schema}.*" to tbls. tbls treats this as a regex (not a literal-dot glob), so the . matches any single character. For schemas whose name is a prefix of another schema's name (currently only react_nestjs vs react_nestjs_history), the include pattern leaks tables from the sibling schema:

  • docs/schema/react-nestjs/README.md lists react_nestjs_history.application_history, react_nestjs_history.knex_migrations, and react_nestjs_history.knex_migrations_lock in its ## Tables section.
  • docs/schema/react-nestjs/react_nestjs_history.*.md files are duplicates of the ones in docs/schema/react-nestjs-history/.
  • The Mermaid ## Relations ER diagram on the same README also includes the foreign-schema entities.
  • docs/schema/react-nestjs/schema.json mirrors the leak.

This is the same family as the enum bleed above (tbls --include filter limits) and should be fixed in the same PR. Recommended approach is the Option A post-process already proposed: extend the per-README cleanup to also drop foreign-schema rows from ## Tables, drop foreign-schema entities from the Mermaid diagram, drop foreign-schema entries from schema.json, and delete duplicated ${other_schema}.*.md files. Acceptance criteria are extended:

  • Each docs/schema/<stack>/README.md ## Tables section lists only tables from that stack's schema.
  • Each docs/schema/<stack>/ directory contains only ${schema}.*.md files (no ${other_schema}.*.md duplicates).
  • Each docs/schema/<stack>/schema.json contains only its own schema's tables.
  • Each docs/schema/<stack>/README.md Mermaid ## Relations diagram contains only its own schema's entities.

Surfaced again during PR #300 follow-up review (Copilot, comment 3178063839).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions