You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SDK composition: generated library SDKs must import shared contracts, not embed them
Companion to #446 (durable versioned library publishing). #446 gives us the store — library@version → go get / pip / npm. This issue is the composition rule that makes multiple library SDKs co-installable in one consumer, which #446 does not address and which the solutions use-case hits immediately.
The problem
A solution consumes several module SDKs at once — e.g. accounts + a future billing + a shared platform/common. If each SDK is generated independently, each embeds its own copy of the shared protos. Then, in Go:
The two copies are distinct, non-interchangeable types (accountssdk.Money ≠ billingsdk.Money).
Both register the same proto file path in the global descriptor registry → hard panic at init: panic: proto: file "platform/common/v1/common.proto" is already registered.
Python has the equivalent descriptor-pool duplicate-symbol failure; TS duplicates types. So naive multi-library consumption is not just messy — it fails to link. Under #446's "one repo per library, go get" model this bites the first time two SDKs share a first-party proto.
Evidence today: codefly-dev/saas-sdk-go was generated as the whole saas-starter public surface under one prefix (accounts + saas/policy + saas/catalog + common …). Fine as one module's SDK; the moment a second module SDK also carries saas/policy or a shared common, go get-ing both panics.
The fix — composition = dependency resolution (fits #446 natively)
Module SDK codegen imports deps, does not regenerate them. In buf generate, the shared modules are declared deps and excluded from generation; the module SDK's descriptors reference the shared library's already-generated package path (managed-mode go_package / python root of the dependency, not a local prefix). This is exactly how googleapis / protovalidate are already handled — extend it to first-party shared contracts.
Consumers compose via the package manager.go get accounts-sdk billing-sdk → MVS resolves onecommon-sdk → types interchangeable, single registration. pip/npm likewise. No bespoke umbrella generator; the subset a solution needs is just the set of libraries it depends on.
What this asks of the library model / CLI
library.codefly.yaml (or the export recipe) needs to express inter-library dependencies (this SDK library depends on common-sdk@^2), so codegen can wire imports and the resolver can pin the closure coherently.
The codegen step (codefly generate proto / a future codefly generate sdk) needs a "generate local, import deps" mode with a stable mapping from a proto module → its published library's package coordinates.
Go + Python first (TS after), matching the solutions need.
P0: prove the pattern with saas-sdk-* — factor the shared sub-packages (policy, common) out of the accounts SDK into a shared library, regenerate accounts to import it, and show go get-ing accounts + a second stub SDK no longer panics.
Aligns with lodestar#53 item 4 (the solutions SDK wrapper) and the chosen model there: composable subset per solution, git-pinned buf workspace interim store.
SDK composition: generated library SDKs must import shared contracts, not embed them
Companion to #446 (durable versioned library publishing). #446 gives us the store —
library@version → go get / pip / npm. This issue is the composition rule that makes multiple library SDKs co-installable in one consumer, which #446 does not address and which the solutions use-case hits immediately.The problem
A solution consumes several module SDKs at once — e.g.
accounts+ a futurebilling+ a sharedplatform/common. If each SDK is generated independently, each embeds its own copy of the shared protos. Then, in Go:accountssdk.Money≠billingsdk.Money).panic: proto: file "platform/common/v1/common.proto" is already registered.Python has the equivalent descriptor-pool duplicate-symbol failure; TS duplicates types. So naive multi-library consumption is not just messy — it fails to link. Under #446's "one repo per library,
go get" model this bites the first time two SDKs share a first-party proto.Evidence today:
codefly-dev/saas-sdk-gowas generated as the whole saas-starter public surface under one prefix (accounts +saas/policy+saas/catalog+ common …). Fine as one module's SDK; the moment a second module SDK also carriessaas/policyor a shared common,go get-ing both panics.The fix — composition = dependency resolution (fits #446 natively)
platform/common,saas/policy, etc. become versionedLibraryresources published via Epic: durable versioned library publishing — storage abstraction for go get / pip / npm #446 (common-sdk-go,common-sdkwheel,@org/common-sdk).buf generate, the shared modules are declareddepsand excluded from generation; the module SDK's descriptors reference the shared library's already-generated package path (managed-modego_package/ python root of the dependency, not a local prefix). This is exactly howgoogleapis/protovalidateare already handled — extend it to first-party shared contracts.go get accounts-sdk billing-sdk→ MVS resolves onecommon-sdk→ types interchangeable, single registration.pip/npmlikewise. No bespoke umbrella generator; the subset a solution needs is just the set of libraries it depends on.What this asks of the library model / CLI
library.codefly.yaml(or the export recipe) needs to express inter-library dependencies (this SDK library depends oncommon-sdk@^2), so codegen can wire imports and the resolver can pin the closure coherently.codefly generate proto/ a futurecodefly generate sdk) needs a "generate local, import deps" mode with a stable mapping from a proto module → its published library's package coordinates.commonversion → all language exports tagged together) so the closure stays coherent across go/python/ts.Scope / phasing
saas-sdk-*— factor the shared sub-packages (policy, common) out of the accounts SDK into a shared library, regenerate accounts to import it, and showgo get-ing accounts + a second stub SDK no longer panics.Links