Found by QA run #10663 driving integration-system.external-schema-introspection at framework 79ebb37.
Symptom
POST /api/v1/datasources/showcase_external/object-draft {"table":"customers"} → 200, but definition.fields.id is {"type":"text"} with no primaryKey: true anywhere in the draft or the rendered source — even though the remote table declares primary key (id) (PRAGMA table_info pk=1 on id). A user who follows the review-before-commit flow commits a federated object with no primary key — the addressing/upsert key for the federated table is dropped by the very codegen meant to produce it.
Root cause
A contract-spelling collision at the introspection seam:
SqlDriver.introspectSchema sets col.isPrimary = true (packages/drivers/driver-sql/src/sql-driver.ts:9698) and populates table.primaryKeys.ExternalDatasourceService.generateObjectDraft reads col.primaryKey (packages/services/service-datasource/src/external-datasource-service.ts).- The two
IntrospectedColumn contracts disagree: packages/objectql/src/util.ts:20 declares isPrimary?: boolean (what the driver returns); packages/spec/src/contracts/schema-diff-service.ts:59 declares primaryKey: boolean (what the service reads).
The driver's result is handed straight to the service (plugin.ts:67-74), so on every SQL driver (sqlite/postgres/mysql) the PK is silently lost. Confirmed in the shipped dist; reproduced twice on both fixture tables; also reachable via os datasource introspect.
Why the pin misses it
external-datasource-service.test.ts hand-writes its fake schema with primaryKey: true (the spec-contract spelling), so no test ever feeds it a real driver's isPrimary output.
Suggested fix
Read both spellings at the seam (col.primaryKey ?? col.isPrimary, or better fall back to table.primaryKeys?.includes(col.name)), and add a pin that drives generateObjectDraft off a realSqlDriver.introspectSchema() result rather than a hand-written fake.
QA-source: #10663 · integration-system.external-schema-introspection · clause 2 (object-draft reviewable/compilable, PK from introspected PK)
Found by QA run #10663 driving
integration-system.external-schema-introspectionat framework79ebb37.Symptom
POST /api/v1/datasources/showcase_external/object-draft {"table":"customers"}→ 200, butdefinition.fields.idis{"type":"text"}with noprimaryKey: trueanywhere in the draft or the rendered source — even though the remote table declaresprimary key (id)(PRAGMA table_infopk=1 onid). A user who follows the review-before-commit flow commits a federated object with no primary key — the addressing/upsert key for the federated table is dropped by the very codegen meant to produce it.Root cause
A contract-spelling collision at the introspection seam:
SqlDriver.introspectSchemasetscol.isPrimary = true(packages/drivers/driver-sql/src/sql-driver.ts:9698) and populatestable.primaryKeys.ExternalDatasourceService.generateObjectDraftreadscol.primaryKey(packages/services/service-datasource/src/external-datasource-service.ts).IntrospectedColumncontracts disagree:packages/objectql/src/util.ts:20declaresisPrimary?: boolean(what the driver returns);packages/spec/src/contracts/schema-diff-service.ts:59declaresprimaryKey: boolean(what the service reads).The driver's result is handed straight to the service (
plugin.ts:67-74), so on every SQL driver (sqlite/postgres/mysql) the PK is silently lost. Confirmed in the shippeddist; reproduced twice on both fixture tables; also reachable viaos datasource introspect.Why the pin misses it
external-datasource-service.test.tshand-writes its fake schema withprimaryKey: true(the spec-contract spelling), so no test ever feeds it a real driver'sisPrimaryoutput.Suggested fix
Read both spellings at the seam (
col.primaryKey ?? col.isPrimary, or better fall back totable.primaryKeys?.includes(col.name)), and add a pin that drivesgenerateObjectDraftoff a realSqlDriver.introspectSchema()result rather than a hand-written fake.QA-source: #10663 · integration-system.external-schema-introspection · clause 2 (object-draft reviewable/compilable, PK from introspected PK)