Roadmap: #188
Respect the [auth] roadmap first and the AGENTS.md file of every repository touched.
Previous roadmap step
[auth 7] (#195) provides adapter-neutral account/profile UI over the universal brokered OAuth baseline. This issue adds optional native provider transports as UX capabilities without forking the Auth domain, profile model or generated account UI.
Repository impact
Likely:
ankhorage/contracts
ankhorage/supabase-auth
ankhorage/studio
ankhorage/expo-runtime
ankhorage/orchestrator and/or dedicated native-auth module repositories
ankhorage/ankh for capability/readiness validation
Do not install provider-native packages into every generated app. Dependencies and Config Plugins must be planned only when a native transport is enabled for an enabled platform.
Goal
Add capability-driven native Google and Apple sign-in transports while keeping brokered browser OAuth available as the universal fallback/default.
Native transport changes only how a provider assertion is acquired. The configured Auth backend still owns creation of the normalized Ankhorage session.
Architecture
UI
-> signInWithProvider('google' | 'apple')
Auth runtime coordinator
-> choose configured transport for current platform
Provider transport
-> brokeredRedirect
-> nativeIdToken / nativeAssertion
Auth backend adapter
-> exchange/verify assertion
-> normalized AuthSession
The generated profile/account UI from [auth 7] must remain unchanged.
Neutral contract direction
Finalize a provider-neutral assertion/input contract, conceptually:
type ExternalIdentityAssertion =
| {
kind: 'oidc-id-token';
provider: AuthOAuthProviderId;
token: string;
nonce?: string;
authorizationCode?: string;
}
| {
kind: 'provider-credential';
provider: AuthOAuthProviderId;
credential: unknown;
};
Do not expose an untyped unknown credential publicly unless a safer discriminated contract cannot represent required providers. Provider-specific payloads may remain inside transport packages and be converted to a canonical backend-consumable assertion.
The Auth backend adapter should advertise supported assertion kinds/providers rather than every adapter pretending to support native tokens.
Google requirements
For native Google transport, support target-aware public client configuration:
Web Client ID
public ID + trusted Web Client Secret
Web Client ID remains first/primary backend audience where required
iOS Client ID
public
associated with stable bundle identifier
Android Client ID
public
associated with stable application ID and signing fingerprints
There are no trusted iOS/Android client secrets to store in generated apps/Vault.
The exact native package/API must be selected after current Expo SDK and provider guidance review. Prefer maintained native integrations and generated Config Plugin ownership. Do not freeze the implementation to a package from an example answer.
Apple requirements
Support native Sign in with Apple on enabled iOS targets and any other platform where the selected architecture/provider supports it intentionally.
Model the required Apple identifiers/keys/secret references with correct trusted/public separation. Do not treat Apple configuration as identical to Google fields.
Handle Apple-specific first-login name/email availability correctly: values returned only once must be persisted according to the profile initialization policy from [auth 6].
Platform-aware configuration
Extend [auth 4]'s requirement model so Studio requests native settings only when:
- the platform is enabled;
- the provider is enabled;
- the native transport is selected;
- the selected Auth backend can consume the assertion.
Example:
Web-only Google brokered redirect
-> Web Client ID + Secret
Web + iOS, Google native on iOS
-> Web Client ID + Secret + iOS Client ID
Web + iOS + Android, Google native on Native
-> Web Client ID + Secret + iOS Client ID + Android Client ID/fingerprint readiness
Runtime/dependency planning
- provider-native dependencies are conditional;
- generated imports are static and planned at generation/build time;
- no unreliable Metro runtime dynamic-import workaround;
- Config Plugins, URL schemes, entitlements/capabilities and native files remain owned by reusable runtime/orchestrator modules;
- Web bundles must not require native modules;
- browser fallback remains available when configured and valid.
Supabase implementation
Implement assertion exchange behind @ankhorage/supabase-auth, for example through the supported Supabase ID-token/assertion methods, without leaking Supabase calls into generated screens.
- validate advertised provider/assertion support;
- normalize the resulting session through the existing canonical session path;
- preserve profile verification/initialization lifecycle;
- map provider/backend failures to neutral Auth error contracts;
- do not store provider ID tokens longer than required for exchange.
Likely files
Contracts, non-exhaustive:
src/auth.ts
src/auth-oauth.test.ts
src/auth-flow-contract.test.ts
Supabase Auth:
src/createSupabaseAuthAdapter.ts
src/oauth.ts
src/types.ts
src/session.ts
src/*native* or assertion modules/tests
Studio/Expo Runtime/Orchestrator:
src/host/orchestrator/templates.ts
src/host/layout/templates/auth/*
src/ui/admin/pages/AuthAdminPage.tsx
planning/config-plugin modules
Exact provider package/module boundaries must be decided during implementation planning.
Phases
Phase 1 — assertion and transport capability contracts
Define neutral assertion inputs, backend capabilities, transport selection and result/error semantics.
Phase 2 — conditional native runtime modules
Implement reusable Google/Apple native transport modules, dependencies and Config Plugins only for enabled targets.
Phase 3 — Supabase assertion exchange
Consume native assertions behind @ankhorage/supabase-auth and return canonical sessions/profile lifecycle.
Phase 4 — Studio configuration and Doctor validation
Expose platform/provider/transport-specific requirements, callbacks, fingerprints and build readiness.
Phase 5 — real-device validation
Validate development/preview builds on iOS and Android with documented credential setup and deterministic non-secret CI coverage.
Tests
Cover at minimum:
- transport selection by platform/provider/configuration;
- unsupported native transport/backend combination rejected during planning/Doctor;
- conditional dependency/config-plugin generation;
- Web-only app receives no native provider dependency;
- Google iOS/Android client IDs treated as public config, not secrets;
- Web Client Secret remains trusted;
- native assertion exchange returns canonical AuthSession;
- nonce/code/provider error mapping;
- Apple first-login profile values persist without being expected on later logins;
- brokered browser fallback still works for providers/platforms without native transport;
- fake second Auth backend can advertise/consume the neutral assertion contract without Supabase types.
Acceptance criteria
- Native Google and Apple are optional transport capabilities, not a separate Auth architecture.
- UI/profile/account contracts remain provider/platform neutral.
- Native dependencies/configuration are generated only when enabled.
- Google Web/iOS/Android client configuration is modeled with correct public/secret boundaries.
- Apple configuration and one-time profile data semantics are modeled correctly.
- Supabase consumes assertions behind its adapter and returns canonical sessions.
- Unsupported combinations fail at planning/Doctor time with actionable diagnostics.
- Brokered browser OAuth remains available and unaffected.
- Real native builds are validated without relying on Expo Go assumptions.
- Behavior-focused tests, package releases/changesets and full validation pass.
Roadmap: #188
Respect the
[auth]roadmap first and theAGENTS.mdfile of every repository touched.Previous roadmap step
[auth 7](#195) provides adapter-neutral account/profile UI over the universal brokered OAuth baseline. This issue adds optional native provider transports as UX capabilities without forking the Auth domain, profile model or generated account UI.Repository impact
Likely:
ankhorage/contractsankhorage/supabase-authankhorage/studioankhorage/expo-runtimeankhorage/orchestratorand/or dedicated native-auth module repositoriesankhorage/ankhfor capability/readiness validationDo not install provider-native packages into every generated app. Dependencies and Config Plugins must be planned only when a native transport is enabled for an enabled platform.
Goal
Add capability-driven native Google and Apple sign-in transports while keeping brokered browser OAuth available as the universal fallback/default.
Native transport changes only how a provider assertion is acquired. The configured Auth backend still owns creation of the normalized Ankhorage session.
Architecture
The generated profile/account UI from
[auth 7]must remain unchanged.Neutral contract direction
Finalize a provider-neutral assertion/input contract, conceptually:
Do not expose an untyped
unknowncredential publicly unless a safer discriminated contract cannot represent required providers. Provider-specific payloads may remain inside transport packages and be converted to a canonical backend-consumable assertion.The Auth backend adapter should advertise supported assertion kinds/providers rather than every adapter pretending to support native tokens.
Google requirements
For native Google transport, support target-aware public client configuration:
There are no trusted iOS/Android client secrets to store in generated apps/Vault.
The exact native package/API must be selected after current Expo SDK and provider guidance review. Prefer maintained native integrations and generated Config Plugin ownership. Do not freeze the implementation to a package from an example answer.
Apple requirements
Support native Sign in with Apple on enabled iOS targets and any other platform where the selected architecture/provider supports it intentionally.
Model the required Apple identifiers/keys/secret references with correct trusted/public separation. Do not treat Apple configuration as identical to Google fields.
Handle Apple-specific first-login name/email availability correctly: values returned only once must be persisted according to the profile initialization policy from
[auth 6].Platform-aware configuration
Extend
[auth 4]'s requirement model so Studio requests native settings only when:Example:
Runtime/dependency planning
Supabase implementation
Implement assertion exchange behind
@ankhorage/supabase-auth, for example through the supported Supabase ID-token/assertion methods, without leaking Supabase calls into generated screens.Likely files
Contracts, non-exhaustive:
Supabase Auth:
Studio/Expo Runtime/Orchestrator:
Exact provider package/module boundaries must be decided during implementation planning.
Phases
Phase 1 — assertion and transport capability contracts
Define neutral assertion inputs, backend capabilities, transport selection and result/error semantics.
Phase 2 — conditional native runtime modules
Implement reusable Google/Apple native transport modules, dependencies and Config Plugins only for enabled targets.
Phase 3 — Supabase assertion exchange
Consume native assertions behind
@ankhorage/supabase-authand return canonical sessions/profile lifecycle.Phase 4 — Studio configuration and Doctor validation
Expose platform/provider/transport-specific requirements, callbacks, fingerprints and build readiness.
Phase 5 — real-device validation
Validate development/preview builds on iOS and Android with documented credential setup and deterministic non-secret CI coverage.
Tests
Cover at minimum:
Acceptance criteria