@volter/twin-googleoauth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +219 -0
  2. package/client/googleoauth-consent.css +207 -0
  3. package/client/googleoauth-consent.tsx +286 -0
  4. package/dist/client/googleoauth-consent.bundle.js +237 -0
  5. package/dist/client/googleoauth-consent.css +207 -0
  6. package/dist/client/googleoauth-consent.d.ts +88 -0
  7. package/dist/client/googleoauth-consent.js +94 -0
  8. package/dist/client/googleoauth-consent.tsx +286 -0
  9. package/dist/src/cli.d.ts +2 -0
  10. package/dist/src/cli.js +42 -0
  11. package/dist/src/googleoauth-autherror.d.ts +25 -0
  12. package/dist/src/googleoauth-autherror.js +144 -0
  13. package/dist/src/googleoauth-budget.d.ts +48 -0
  14. package/dist/src/googleoauth-budget.js +121 -0
  15. package/dist/src/googleoauth-capabilities.d.ts +3 -0
  16. package/dist/src/googleoauth-capabilities.js +1651 -0
  17. package/dist/src/googleoauth-conformance.d.ts +10 -0
  18. package/dist/src/googleoauth-conformance.js +426 -0
  19. package/dist/src/googleoauth-connector.d.ts +70 -0
  20. package/dist/src/googleoauth-connector.js +244 -0
  21. package/dist/src/googleoauth-consent-client.gen.d.ts +2 -0
  22. package/dist/src/googleoauth-consent-client.gen.js +10 -0
  23. package/dist/src/googleoauth-consent-ui.d.ts +25 -0
  24. package/dist/src/googleoauth-consent-ui.js +102 -0
  25. package/dist/src/googleoauth-jwt.d.ts +78 -0
  26. package/dist/src/googleoauth-jwt.js +183 -0
  27. package/dist/src/googleoauth-scopes.d.ts +36 -0
  28. package/dist/src/googleoauth-scopes.js +92 -0
  29. package/dist/src/googleoauth-server.d.ts +34 -0
  30. package/dist/src/googleoauth-server.js +89 -0
  31. package/dist/src/googleoauth-store.d.ts +78 -0
  32. package/dist/src/googleoauth-store.js +313 -0
  33. package/dist/src/googleoauth-twin.d.ts +53 -0
  34. package/dist/src/googleoauth-twin.js +1050 -0
  35. package/dist/src/index.d.ts +16 -0
  36. package/dist/src/index.js +102 -0
  37. package/package.json +75 -0
  38. package/src/cli.ts +41 -0
  39. package/src/googleoauth-autherror.ts +150 -0
  40. package/src/googleoauth-budget.ts +147 -0
  41. package/src/googleoauth-capabilities.ts +1775 -0
  42. package/src/googleoauth-conformance.ts +472 -0
  43. package/src/googleoauth-connector.ts +266 -0
  44. package/src/googleoauth-consent-client.gen.ts +10 -0
  45. package/src/googleoauth-consent-ui.ts +124 -0
  46. package/src/googleoauth-journey.uitest.ts +296 -0
  47. package/src/googleoauth-jwt.ts +207 -0
  48. package/src/googleoauth-scopes.ts +109 -0
  49. package/src/googleoauth-server.ts +101 -0
  50. package/src/googleoauth-store.ts +359 -0
  51. package/src/googleoauth-twin.ts +1207 -0
  52. package/src/index.ts +175 -0
package/src/index.ts ADDED
@@ -0,0 +1,175 @@
1
+ // @volter/twin-googleoauth — the Google OAuth 2.0 / OpenID Connect twin (one vendor, one package),
2
+ // built on the shared @volter/world-core kernel.
3
+ //
4
+ // The catalog's first BROWSER-FACING pack: it serves the vendor's own consent screen as HTML at
5
+ // accounts.google.com's real path, completes the full authorization-code round trip (consent → 302
6
+ // with code+state → redemption at the token endpoint → refresh), and mints REAL RS256 id_tokens
7
+ // verifiable against the JWKS it serves. Conformance tooling lives in @volter/world-tooling (a dev
8
+ // dependency) — not shipped in the runtime API.
9
+ export {
10
+ ACCOUNTS_ORIGIN,
11
+ APIS_ORIGIN,
12
+ discoveryDocument,
13
+ handleGoogleOAuthTwinRequest,
14
+ ISSUER,
15
+ OAUTH2_ORIGIN,
16
+ OIDC_ORIGIN,
17
+ } from './googleoauth-twin.ts';
18
+ export type { GoogleOAuthRequest, GoogleOAuthResponse } from './googleoauth-twin.ts';
19
+ export { createGoogleOAuthConsentServer, createGoogleOAuthTwinFetch, createGoogleOAuthTwinServer, type GoogleOAuthTwinFetchOptions } from './googleoauth-server.ts';
20
+ export {
21
+ DEFAULT_ACCOUNTS,
22
+ DEFAULT_CLIENT_ID,
23
+ DEFAULT_CLIENT_SECRET,
24
+ defaultRedirectUris,
25
+ RESOURCE_TYPES,
26
+ redirectUriAllowed,
27
+ } from './googleoauth-store.ts';
28
+ export {
29
+ atHash,
30
+ buildJwks,
31
+ buildLegacyPemCerts,
32
+ decodeJwt,
33
+ ensureKeypair,
34
+ pkceS256,
35
+ setKeypairGenerator,
36
+ signJwt,
37
+ verifyJwtWithJwks,
38
+ } from './googleoauth-jwt.ts';
39
+ export type { Jwk, Jwks } from './googleoauth-jwt.ts';
40
+ export {
41
+ describeScope,
42
+ describeScopes,
43
+ formatScopeParam,
44
+ isGranularlyDeclinable,
45
+ OIDC_SCOPES,
46
+ parseScopeParam,
47
+ SCOPE_CATALOG,
48
+ sortScopesForConsent,
49
+ } from './googleoauth-scopes.ts';
50
+ export type { ScopeInfo } from './googleoauth-scopes.ts';
51
+ export {
52
+ liveGoogleOAuthExecute,
53
+ mapTokenInfoClient,
54
+ mapTokenInfoGrant,
55
+ mapUserInfoAccount,
56
+ pullGoogleOAuthIdentity,
57
+ unpushableGoogleOAuthEntries,
58
+ syncGoogleOAuthFromReal,
59
+ } from './googleoauth-connector.ts';
60
+ export type { GoogleOAuthExecute, LiveGoogleOAuthOptions } from './googleoauth-connector.ts';
61
+ // The client-side rate budget — the fail-closed backstop `liveGoogleOAuthExecute` routes every live
62
+ // request through. The MECHANISM is the kernel's shared, vendor-agnostic `RateBudget`; what lives
63
+ // here is this vendor's DECLARATION (window/ceiling/per-endpoint weights) plus the vendor-bound
64
+ // bindings. Exported so an operator can inspect spend (`snapshot`) and so a caller can catch
65
+ // `GoogleOAuthBudgetError` by type; there is deliberately no export that disables the guard.
66
+ export {
67
+ GOOGLEOAUTH_BUDGET_CEILING,
68
+ GOOGLEOAUTH_BUDGET_MAX_RETRY_AFTER_S,
69
+ GOOGLEOAUTH_BUDGET_WINDOW_MS,
70
+ GOOGLEOAUTH_CALL_WEIGHTS,
71
+ GOOGLEOAUTH_RATE_BUDGET,
72
+ GoogleOAuthBudget,
73
+ GoogleOAuthBudgetError,
74
+ googleOAuthBudgetPath,
75
+ googleOAuthCallWeight,
76
+ } from './googleoauth-budget.ts';
77
+ export type {
78
+ GoogleOAuthBudgetErrorKind,
79
+ GoogleOAuthBudgetOptions,
80
+ GoogleOAuthBudgetReservation,
81
+ GoogleOAuthBudgetSnapshot,
82
+ } from './googleoauth-budget.ts';
83
+ export {
84
+ consentPageHtml,
85
+ CONSENT_SCRIPT_PATH,
86
+ CONSENT_STYLE_PATH,
87
+ errorPageHtml,
88
+ googleOAuthConsentState,
89
+ } from './googleoauth-consent-ui.ts';
90
+ export type { ConsentAccount, ConsentScopeRow, ConsentView } from './googleoauth-consent-ui.ts';
91
+
92
+ // Registry descriptor: the pack self-describes so tooling can discover it.
93
+ import { registerPack, type TwinPack } from '@volter/world-core';
94
+ import { GOOGLEOAUTH_RATE_BUDGET as RATE_BUDGET } from './googleoauth-budget.ts';
95
+ import { performGoogleOAuthAction, syncGoogleOAuthFromRemote } from './googleoauth-connector.ts';
96
+
97
+ export const pack: TwinPack = {
98
+ // PROTOCOL 2 (docs/contributing/architecture.md#protocol-2-the-pack-is-a-plugin): the pack is a plugin — its wire, its tree, and its half of the real
99
+ // state system. Moved 2026-09-08. NOTHING here can cross: Google publishes no API that creates an OAuth
100
+ // client, seeds a user or grants a scope — those are Cloud Console and myaccount.google.com actions a
101
+ // person takes in a browser — so `perform` settles every entry with that reason and only `refresh` reads.
102
+ protocol: '2',
103
+ refresh: { every: '30m', onDemand: { atMost: '60s' } },
104
+ stateSystem: { perform: performGoogleOAuthAction, refresh: syncGoogleOAuthFromRemote },
105
+ // the round trip registers an OAuth client through the twin's own door, because the vendor has no API for
106
+ // it at all — which is the same reason `perform` never crosses
107
+ roundTrip: { method: 'POST', path: '/_twin/clients', body: { client_id: 'round-trip.apps.googleusercontent.com', name: 'Round Trip', redirect_uris: ['https://round.trip.test/callback'] } },
108
+ parityOrigin: 'http://twin',
109
+ // shapeParity is NOT held, for a structural reason rather than a divergence: the refresh reads the ACCOUNT
110
+ // this credential names (its identity and granted scopes) — there is no listing of OAuth clients to
111
+ // observe back, because Google publishes none. Written and observed are different subjects by design.
112
+ vendor: 'googleoauth',
113
+ // The SAME object googleoauth-budget.ts declares at module load — one source of truth, so
114
+ // registering the pack and importing the connector can never arm two different ceilings.
115
+ rateBudget: RATE_BUDGET,
116
+ transport: 'rest',
117
+ archetype: 'crud',
118
+ bin: 'world-googleoauth',
119
+ resources: ['oauth_client', 'account', 'auth_request', 'authorization_code', 'access_token', 'refresh_token', 'grant'],
120
+ specSource:
121
+ 'accounts.google.com/.well-known/openid-configuration (the vendor\'s own OIDC discovery document) '
122
+ + '+ developers.google.com/identity/protocols/oauth2/{web-server,native-app,openid-connect,service-account}',
123
+ description:
124
+ 'Google OAuth 2.0 / OIDC twin — the real consent screen as HTML, the full authorization-code '
125
+ + 'round trip (PKCE S256, state, granular consent, refresh), real RS256 id_tokens and a real JWKS.',
126
+ // Adoption, all in the pack's one home (descriptor-first back-migration, adding-a-twin.md §3, 2026-08-31;
127
+ // `google-auth-library` and the bare `google`/`googleoauth`/`googleoidc` stems moved off the
128
+ // central maps unchanged).
129
+ //
130
+ // `google-auth-library` is the class every Google client builds its auth on (googleapis,
131
+ // @googleapis/*, @google-cloud/*), and it is the package an app adds when it does three-legged
132
+ // OAuth itself. `openid-client` is deliberately NOT claimed: it is a third-party generic OIDC
133
+ // library (panva), not a Google client, and claiming it would say any OIDC provider is this twin.
134
+ //
135
+ // GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI stem to `google` and are the
136
+ // OAuth-app credential shape — the exact vars the Cal.com blind-adoption run dropped nine of
137
+ // before _CLIENT_ID/_CLIENT_SECRET became strict suffixes (covers.ts's ENV_SUFFIX_STRICT). NB the
138
+ // `google-auth-library` package does NOT itself read these (it reads GOOGLE_APPLICATION_
139
+ // CREDENTIALS); apps set them and pass them to the constructor, which is exactly why the ENV
140
+ // signal and the SDK signal are separate and both worth having. The rest are the credential-var
141
+ // stems real apps use for sign-in-with-Google.
142
+ //
143
+ // NOTE: this pack's injector rule stays in the hand VENDOR_HOSTS table, and that is a ROUTING
144
+ // constraint, not an omission. It shares oauth2.googleapis.com and www.googleapis.com with the
145
+ // pack-less `googleauth` plumbing key, and it is declared BEFORE `googleauth` on purpose:
146
+ // `resolveTwin` returns the FIRST matching vendor in insertion order, so in a world where BOTH
147
+ // are configured the token endpoint goes to the pack (whose endpoint is a strict SUPERSET —
148
+ // authorization_code and refresh_token, which googleauth has no state for, PLUS the jwt-bearer
149
+ // service-account exchange, with a REAL RS256 id_token instead of gemini's `alg: none` stub).
150
+ // Descriptor-declared hosts are appended AFTER the whole hand table, so moving this entry alone
151
+ // would flip that precedence. It can move once `googleauth` has a home of its own.
152
+ adoption: {
153
+ // Google's official auth libraries - the Python counterparts of `google-auth-library`: token
154
+ // minting/refresh against oauth2.googleapis.com and the installed-app OAuth flow.
155
+ // `google-api-python-client` is deliberately UNCLAIMED: it is the generic multi-service Google
156
+ // API client (Drive, Sheets, YouTube, ...) whose calls go to whichever API the caller names,
157
+ // not to this pack's OAuth endpoints - claiming it here would map every Google-anything repo
158
+ // onto the OAuth twin.
159
+ pypi: ['google-auth', 'google-auth-oauthlib'],
160
+ sdks: ['google-auth-library', '@googleapis/oauth2'],
161
+ envStems: [
162
+ 'GOOGLE', 'GOOGLEOAUTH', 'GOOGLEOIDC',
163
+ 'AUTHGOOGLE', 'AUTHGOOGLEOAUTH2', 'BACKENDGOOGLE', 'GOOGLEIOS',
164
+ 'GOOGLELOGIN', 'GOOGLEWEB', 'NEXTPRIVATEGOOGLE', 'SSOGOOGLEOAUTH2',
165
+ // appsmith's Google OAuth app: APPSMITH_OAUTH2_GOOGLE_CLIENT_ID/_SECRET — the same
166
+ // app-prefixed shape as AUTHGOOGLEOAUTH2 / SSOGOOGLEOAUTH2 (ladder classification 2026-09-02).
167
+ 'APPSMITHOAUTH2GOOGLE',
168
+ ],
169
+ },
170
+ // A browser is REDIRECTED to accounts.google.com — there is no single API path prefix to proxy,
171
+ // so the loader host is the consent host and the prefix is the OAuth path root.
172
+ browserRouting: { apiPathPrefix: '/o/oauth2/', loaderHost: 'https://accounts.google.com' },
173
+ };
174
+ // registered at import: the kernel learns the pack's state system (protocol 2)
175
+ registerPack(pack);