Found while landing #10676 / #10998 (the driver aligning to the spec introspection contract, maintainer ruling 2026-08-22 「同意所有」 item 9). That ruling names exactly three keys — primaryKey on columns, plus dialect and introspectedAt on the schema — and those are repaired. Two other keys of the same contract are still unconformed, and they are recorded here rather than absorbed into that PR, because neither is covered by the ruling.
1. IntrospectedTable.indexes is declared REQUIRED and is never emitted
packages/spec/src/contracts/schema-diff-service.ts:
exportinterfaceIntrospectedTable{name: string;columns: IntrospectedColumn[];indexes: IntrospectedIndex[];// required}SqlDriver.introspectSchema() builds { name, columns, foreignKeys, primaryKeys } — no indexes, on every dialect (one construction site, sql-driver.ts). So a consumer typed against the spec contract may read table.indexes without a guard and get undefined.
This is cheap to repair and deliberately not repaired in that PR: the capability already exists. SqlDriver.introspectIndexes(tableName, { onFailure }) returns PhysicalIndex[] ({ name, columns, unique, primary }), which is the spec's IntrospectedIndex ({ name, columns, unique }) plus one member. What is missing is the wiring plus two decisions that are not a dev's to take alone:
⚠️ In the meantime the type in driver-sql / objectqlOmits indexes from the spec table rather than emitting indexes: [], on purpose: an empty array tells a schema differ the table HAS no indexes, which is worse than an absent key.
2. IntrospectedColumn.defaultValue is declared string, and the producers emit other types
The spec declares defaultValue?: string. Measured on a live in-memory SQLite database, the driver's own output for t.string('id').primary():
{"name":"id","type":"varchar","nullable":true,"defaultValue":null,"primaryKey":true,"isUnique":true,"maxLength":"255"}defaultValue is null — it is whatever knex.columnInfo() reported. In-tree fixtures also carry non-strings (packages/objectql/src/util.test.ts has defaultValue: true for a boolean column). The IntrospectedColumn in driver-sql and objectql therefore keeps defaultValue?: unknown (spelled as an explicit Omit from the spec type, so the divergence is visible rather than accidental).
Repairing it means deciding which side is right: normalise the producer to a string expression (and drop null rather than emit it), or widen the spec declaration. Both are contract decisions.
Same measurement note: maxLength came back as the STRING "255" while the SQL-layer type declares number. Same class, same site, listed here so it is not re-discovered separately.
Not measured
SQLite only. Postgres and MySQL were read, not run — no server is reachable from the container this was measured in. Both keys are built at a single dialect-independent site, so the SHAPE cannot vary by dialect; per-dialect CONTENT is not claimed.
Filed unassigned as a finding from #10676 / #10998; not fixed there because the ruling that released those cards does not cover these keys.
Found while landing #10676 / #10998 (the driver aligning to the spec introspection contract, maintainer ruling 2026-08-22 「同意所有」 item 9). That ruling names exactly three keys —
primaryKeyon columns, plusdialectandintrospectedAton the schema — and those are repaired. Two other keys of the same contract are still unconformed, and they are recorded here rather than absorbed into that PR, because neither is covered by the ruling.1.
IntrospectedTable.indexesis declared REQUIRED and is never emittedpackages/spec/src/contracts/schema-diff-service.ts:SqlDriver.introspectSchema()builds{ name, columns, foreignKeys, primaryKeys }— noindexes, on every dialect (one construction site,sql-driver.ts). So a consumer typed against the spec contract may readtable.indexeswithout a guard and getundefined.This is cheap to repair and deliberately not repaired in that PR: the capability already exists.
SqlDriver.introspectIndexes(tableName, { onFailure })returnsPhysicalIndex[]({ name, columns, unique, primary }), which is the spec'sIntrospectedIndex({ name, columns, unique }) plus one member. What is missing is the wiring plus two decisions that are not a dev's to take alone:introspectSchema()call, including the federation path that introspects a whole remote warehouse;introspectIndexestakesonFailure: 'throw' | 'partial'for the reason driver-sql:introspectIndexesswallows every error and returns a partial index list, which the drift differ then reports as missing indexes #7332 documents. Which one an introspection snapshot wants is a real choice — a partial index list is what the drift differ misreads as missing indexes.driver-sql/objectqlOmitsindexesfrom the spec table rather than emittingindexes: [], on purpose: an empty array tells a schema differ the table HAS no indexes, which is worse than an absent key.2.
IntrospectedColumn.defaultValueis declaredstring, and the producers emit other typesThe spec declares
defaultValue?: string. Measured on a live in-memory SQLite database, the driver's own output fort.string('id').primary():{"name":"id","type":"varchar","nullable":true,"defaultValue":null,"primaryKey":true,"isUnique":true,"maxLength":"255"}defaultValueisnull— it is whateverknex.columnInfo()reported. In-tree fixtures also carry non-strings (packages/objectql/src/util.test.tshasdefaultValue: truefor a boolean column). TheIntrospectedColumnindriver-sqlandobjectqltherefore keepsdefaultValue?: unknown(spelled as an explicitOmitfrom the spec type, so the divergence is visible rather than accidental).Repairing it means deciding which side is right: normalise the producer to a string expression (and drop
nullrather than emit it), or widen the spec declaration. Both are contract decisions.Same measurement note:
maxLengthcame back as the STRING"255"while the SQL-layer type declaresnumber. Same class, same site, listed here so it is not re-discovered separately.Not measured
SQLite only. Postgres and MySQL were read, not run — no server is reachable from the container this was measured in. Both keys are built at a single dialect-independent site, so the SHAPE cannot vary by dialect; per-dialect CONTENT is not claimed.
Filed unassigned as a finding from #10676 / #10998; not fixed there because the ruling that released those cards does not cover these keys.