Embedded schema type definitions are namespace-unqualified
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 35
- Forks
- 14
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 1
Description
Summary
In the schema string embedded in every Yardl file, type references are fully qualified (Namespace.Type) but type definitions carry only their unqualified name ("name":"Foo"). Because Yardl enforces name uniqueness only within a namespace, two different types from different namespaces can share an unqualified name in the same embedded schema. Any consumer that resolves the schema by definition name — e.g. a schema-only/dynamic reader, or a third-party tool — cannot disambiguate them and will misread the data.
Generated SDKs are unaffected (they use compile-time type knowledge and never resolve by name at runtime). This only affects consumers that interpret the embedded schema.
Root cause
- Uniqueness is checked on the fully-qualified name, so cross-namespace collisions are legal:
tooling/pkg/dsl/validation_type_resolution.go:32→fullName := fmt.Sprintf("%s.%s", namespace, meta.Name) - References are serialized qualified:
tooling/pkg/dsl/validation_type_resolution.go:157→simpleType.Name = meta.GetQualifiedName() - Definitions serialize only the unqualified name (
DefinitionMeta:Name json:"name",Namespace json:"-"—tooling/pkg/dsl/types.go:223-224).
Reproduction
Two namespaces each defining a different, non-alias record named Foo:
# imported/_package.yml: namespace: Imported
Foo: !record
fields: { a: int32 }
# base/_package.yml: namespace: Base, imports: [../imported]
Foo: !record
fields: { b: string }
P: !protocol
sequence:
localFoo: Foo
importedFoo: Imported.Foo
yardl generate succeeds, and the embedded schema contains two same-named, different-bodied definitions:
// references (qualified):
localFoo -> "Base.Foo"
importedFoo -> "Imported.Foo"
// definitions (unqualified — ambiguous):
{"name":"Foo","fields":[{"name":"b","type":"string"}]}
{"name":"Foo","fields":[{"name":"a","type":"int32"}]}
A reader that keys definitions by unqualified name resolves Imported.Foo to the wrong body and misreads the stream (in practice: reads the int32 as a string length → EOFError). The generated SDK reads the same bytes correctly.
Note: the existing TestModel schemas already contain unqualified-name collisions (e.g. Image — the real Image.Image generic vs. a TestModel.Image re-export alias). Those happen to be alias/real pairs resolving to the same structure, so they're benign today — but nothing guarantees that; the case above is a genuine, silent mismatch.
Proposed fix
Qualify definition names for imported types in the embedded schema (leave base-model types unqualified), matching the already-qualified references. Because within-namespace names are unique, every possible collision is cross-namespace, so qualifying the imported side makes the key sets provably disjoint (dot-free base names can never equal dotted imported names). Consumers then resolve via exact match, falling back to the unqualified name only for base-namespace references.
Alternative: fully qualify all definition names. Simpler for consumers (pure exact-match; no fallback), at the cost of changing every embedded schema string.
Notes
- Either option changes the embedded schema string and thus interacts with the same back-compat concern raised in #297 (readers do exact string-equality on the schema). A structural/canonical schema comparison would address both together.
- Assumes one namespace per package (true today). If a package could ever span multiple namespaces, "base = unqualified" breaks and full qualification would be required.
Acceptance criteria
- The embedded schema uniquely identifies every type definition even when unqualified names collide across imported namespaces.
- A schema-only reader can correctly resolve and read the reproduction model above.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in tooling/pkg/dsl/validation_type_resolution.go, especially the fully qualified reference serialization around lines 32 and 157, then inspect DefinitionMeta in tooling/pkg/dsl/types.go around lines 223-224. Reproduce the two-namespace Foo model and inspect its embedded schema. Done means every definition is uniquely resolvable and the schema-only reader correctly reads the reproduction model, while accounting for the schema compatibility concern in #297.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100