Repository navigation
feat(swift): type OIDCClient by the spec's provider names - #902
Open
thisisabhash wants to merge 7 commits into
Open
thisisabhash wants to merge 7 commits into
thisisabhash wants to merge 7 commits into
Conversation
Without written type args, an oidc/client result now carries the provider
names the type checker infers, as a string enum. AuthOIDC.createApi() types
getClient() as OIDCClient<ProviderName<P>>, which resolves to the configured
names, so the spec gets e.g. [{ "type": "string", "enum": ["google", "github"] }].
Names that resolve to plain string or any emit nothing.
Inference stays limited to oidc/client: an inferred realtime message type can be
any or a primitive that native generators can't decode, and a declared binding's
arity check would reject inferred args. Written type args are unchanged.
The spec now fills an oidc/client's x-blocks-type-args with the app's provider names. Neither generator uses them yet, and turning them into an unused enum breaks codegen: Kotlin throws on a name such as login.gov, and Dart emits constants such as default or okta:corp that don't compile. Both now drop the type args, so the generated OidcClient result is unchanged.
A direct or optional oidc/client result whose first type arg is a string enum generates a CaseIterable, Sendable Provider enum in the operation's enum (e.g. OidcAuthApi.GetClient.Provider) and a signIn(provider:relayTo:launcher:) overload on BlocksRuntime.OIDCClient that forwards its raw value, so signIn(provider: .google, ...) checks the name at compile time. getClient() still returns OIDCClient and the String overload stays. The enum is named ResultProvider, with a swift: warning, when the method's own types already use Provider. Case names are camelCased, made legal and backticked when they're keywords. A nested oidc/client keeps decoding as JSONValue with no enum. Fixture 37-oidc-provider-enum covers all three platforms.
Resolve conflicts with #807, which moved the transferable helpers into TransferableEmission.swift and routes emitted declarations through emitDeclaration: the provider enum now goes through it too. Keep both README feature bullets and AGENTS.md test rows.
🦋 Changeset detectedLatest commit: 37dbd10 The changes in this PR will be included in the next version bump. This PR includes changesets to release 26 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
thisisabhash
had a problem deploying
to
publish
October 20, 2026 18:02 — with
GitHub Actions
Failure
thisisabhash
had a problem deploying
to
publish
October 20, 2026 18:02 — with
GitHub Actions
Failure
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 17:24 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 17:24 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 17:24 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 18:14 — with
GitHub Actions
Inactive
Picks up #926's e2e-slot action and E2E job-selection test, which the PR's workflows (run from the merge ref) need in the checked-out head.
…ntry point main's Kotlin Blocks entry point (#704) changed generated namespace and Servers files, so fixture 37's Kotlin goldens are regenerated. The typed and untyped OIDC clients still generate the same Kotlin.
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
thisisabhash
temporarily deployed
to
agent-bench
October 22, 2026 19:03 — with
GitHub Actions
Inactive
This branch had an error being deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OIDCClient.signIn(provider:relayTo:launcher:)on Swift takes a rawString, so a typo in a provider name compiles and only fails at runtime withOIDCError.unknownProvider. The TS client already types this:AuthOIDC.createApi()declaresgetClient()asOIDCClient<ProviderName<P>>, which TypeScript resolves toOIDCClient<'google' | 'github'>. The spec drops those names, becausedetectTransferableemitsx-blocks-type-argsonly for a written<...>, and a namespace built in another module, such ascreateApi()'s, never has one.Issue #, if available: none.
Changes
Spec generator (
@aws-blocks/core). Without written type args, anoidc/clientnow also emits the provider names the type checker infers, as a string enum:{ "x-blocks-transferable": "oidc/client", "x-blocks-type-args": [{ "type": "string", "enum": ["google", "github"] }] }It emits them only when they resolve to string literals. Provider names that resolve to plain
string,anyor an unresolved type parameter emit nothing.generate-spec.tsis unchanged: an untitled enum stays inline and isn't moved intocomponents.schemas.The inference is limited to
oidc/clienton purpose. An earlier version applied it to every transferable, and review showed what that breaks:anybecomes{}. That crashes Kotlin codegen, and Swift turns it into an empty struct that drops every payload.genericArity: 0fail arity validation.Written type args behave exactly as on
main.Swift runtime and codegen (
aws-blocks-swift).OIDCClientis now generic over the providers it signs in with, the wayRealtimeChannel<T>is over its message type:public actor OIDCClient<Provider: OIDCProviderName>.Provideris phantom: it only typessignIn(provider:relayTo:launcher:), which sendsprovider.providerName.fromJSONand everything else are unchanged.OIDCProviderNameis a new protocol withvar providerName: String. AString-backed enum gets it fromrawValue, andStringconforms, so an untyped spec's client isOIDCClient<String>and still signs in with a string.oidc/clientresult whose first type arg is a string enum generatespublic enum Provider: String, CaseIterable, Codable, BlocksRuntime.OIDCProviderNamein the operation's enum, andgetClient()returns and hydratesOIDCClient<GetClient.Provider>. Without the type arg it returnsOIDCClient<String>.oidc/clientstill decodes asJSONValueand gets no enum, inline or in a model.How the names are made safe:
ResultProvider, with aswift:warning, when the operation's own types declare or referenceProvider: a parameter type, a root union's variant struct, or a model one of them names. AProvidermodel elsewhere in the spec doesn't rename it.login.govbecomescase loginGov = "login.gov", and duplicates get numbered.Breaking (Swift): a bare
OIDCClientin a type position no longer compiles. WriteOIDCClient<String>, orOIDCClient<…GetClient.Provider>for a typed spec, including for its static members (OIDCClient<String>.generateVerifier()). Swift has no default type parameters, so there's no non-breaking spelling of the generic.Kotlin and Dart codegen. Both now ignore an
oidc/client's type args, so their output is unchanged frommain. Without this guard, the new provider names would break them:IllegalArgumentException: Can't escape identifier 'Login.gov'for a provider namedlogin.gov.defaultandokta:corp, which don't compile.Their typed
signInis follow-up work.What to review closely:
inferredProviderNamesinpackages/core/src/scripts/extract-ts-types.ts.OIDCClient/OIDCProviderNameinBlocksRuntime/OIDC/OIDCClient.swift.oidcProviderArgsandreferencedTypeNamesinCodegenModelBuilder.swift.SwiftCodeGenerator+OIDCProviders.swift, and theoidc/clientbranches inTransferableEmission.swiftandSwiftCodeGenerator.swift.Behavior and limitations reviewers should know:
as constarray keep their literals, as intest-apps/comprehensive. An inline[stubIdp({ name: 'google', onAuthorize: (req) => ... })]widens toStubProvider<string>, sotest-apps/native-bindings(the native E2E app) stays untyped and getsOIDCClient<String>.Fixture
37-oidc-provider-enumcovers all three platforms, includingmy-ssoandlogin.gov. It's numbered after #854's 28–36 so the two don't collide.Validation
swift test --filter "BlocksCodegenTests|BlocksRuntimeTests|BlocksGeneratedCodeTests|BlocksGeneratedMainActorTests": 341 pass on top ofmainwith feat(swift): emit typed transferable results for declared native bindings #807 merged. This includes:Stringclients, nested and in-model clients, optional results, case-name escaping, theResultProviderfallback and its warning, aProvidermodel elsewhere in the spec not renaming the enum, and the rename terminating for a name with no PascalCase part;OIDCClient<Auth.GetClient.Provider>fromgetClient()and signing in against a recordingURLProtocol, with the right/authorize-params/my-ssopath;OIDCUserandBrowserLaunchertypes in the generated module;Tests/BlocksE2ETests) compile against code generated fromtest-apps/native-bindings' spec.packages/core: the extractor,generate-spec, native-catalog and spec validation tests pass (117). New tests cover:AuthOIDC.createApi()pattern (typed, plainstring,any);oidc/clientgate is removed; I checked with a mutation;:codegen:checkpasses (130 tests), and so does the Dartblocks_codegensuite (185 tests), on Dart 3.11 withdart formatclean.main. The only difference iscomprehensive'soidcAuthApi.getClient, which gains["google", "corporate"]. The Swift output for that method compiles in Swift 6 with warnings as errors.oidc/client, the Swift generator's output is byte-identical tomain's, and no existing golden changed. An untypedoidc/clientnow returnsOIDCClient<String>.Checklist
docs/native-clients/schema-generation-guide-for-devs.md,docs/native-clients/codegen-design.md,native/swift/README.md,native/swift/AGENTS.md@aws-blocks/coreand@aws-blocks/blocks,aws-blocks-swift,aws-blocks-kotlinblocks_codegenchangelogBy submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.