@eva_solutions/auth-sdk 0.0.0-stage → 3.0.0-dev-20261107051125
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.
- package/CHANGELOG.md +290 -0
- package/LICENSE +21 -0
- package/README.md +481 -2
- package/dist/admin/index.cjs +4 -0
- package/dist/admin/index.d.cts +2 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/admin/index.js +1 -0
- package/dist/admin-DjvuvuI8.js +408 -0
- package/dist/admin-DjvuvuI8.js.map +1 -0
- package/dist/admin-Q6lbWqLM.cjs +419 -0
- package/dist/admin-Q6lbWqLM.cjs.map +1 -0
- package/dist/api-path-2Ulruz7R.cjs +34 -0
- package/dist/api-path-2Ulruz7R.cjs.map +1 -0
- package/dist/api-path-B-vSkL2H.js +29 -0
- package/dist/api-path-B-vSkL2H.js.map +1 -0
- package/dist/auth-19r-Q6X2.js +84 -0
- package/dist/auth-19r-Q6X2.js.map +1 -0
- package/dist/auth-DX1N5JA4.cjs +131 -0
- package/dist/auth-DX1N5JA4.cjs.map +1 -0
- package/dist/auth-handlers-B3iJaPln.js +343 -0
- package/dist/auth-handlers-B3iJaPln.js.map +1 -0
- package/dist/auth-handlers-BTbXKJms.d.ts +15 -0
- package/dist/auth-handlers-BTbXKJms.d.ts.map +1 -0
- package/dist/auth-handlers-CDzGFDTu.cjs +404 -0
- package/dist/auth-handlers-CDzGFDTu.cjs.map +1 -0
- package/dist/auth-handlers-DRUUTEtW.d.cts +15 -0
- package/dist/auth-handlers-DRUUTEtW.d.cts.map +1 -0
- package/dist/catalog-CHPqldcj.cjs +172 -0
- package/dist/catalog-CHPqldcj.cjs.map +1 -0
- package/dist/catalog-CIqpzgsM.d.cts +75 -0
- package/dist/catalog-CIqpzgsM.d.cts.map +1 -0
- package/dist/catalog-CIqpzgsM.d.ts +75 -0
- package/dist/catalog-CIqpzgsM.d.ts.map +1 -0
- package/dist/catalog-DqPhtCKZ.js +95 -0
- package/dist/catalog-DqPhtCKZ.js.map +1 -0
- package/dist/config-D6Tr7ev6.d.cts +95 -0
- package/dist/config-D6Tr7ev6.d.cts.map +1 -0
- package/dist/config-rl4_-VAq.d.ts +95 -0
- package/dist/config-rl4_-VAq.d.ts.map +1 -0
- package/dist/constants-BE1_9Tod.cjs +52 -0
- package/dist/constants-BE1_9Tod.cjs.map +1 -0
- package/dist/constants-BY7QZokc.js +29 -0
- package/dist/constants-BY7QZokc.js.map +1 -0
- package/dist/constants-CcbhOaAP.cjs +153 -0
- package/dist/constants-CcbhOaAP.cjs.map +1 -0
- package/dist/constants-rNuD5qJn.js +94 -0
- package/dist/constants-rNuD5qJn.js.map +1 -0
- package/dist/contracts/index.cjs +1006 -0
- package/dist/contracts/index.cjs.map +1 -0
- package/dist/contracts/index.d.cts +488 -0
- package/dist/contracts/index.d.cts.map +1 -0
- package/dist/contracts/index.d.ts +488 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +817 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/cookies-DCIcr7uy.cjs +94 -0
- package/dist/cookies-DCIcr7uy.cjs.map +1 -0
- package/dist/cookies-DKEC7AWv.js +71 -0
- package/dist/cookies-DKEC7AWv.js.map +1 -0
- package/dist/delegated-token-CVNbMNfy.js +426 -0
- package/dist/delegated-token-CVNbMNfy.js.map +1 -0
- package/dist/delegated-token-DHSK4rHI.cjs +461 -0
- package/dist/delegated-token-DHSK4rHI.cjs.map +1 -0
- package/dist/error-helpers-BenWu-_u.d.ts +105 -0
- package/dist/error-helpers-BenWu-_u.d.ts.map +1 -0
- package/dist/error-helpers-KBHUbkOM.d.cts +105 -0
- package/dist/error-helpers-KBHUbkOM.d.cts.map +1 -0
- package/dist/error-helpers-XCh4ZJ-g.cjs +282 -0
- package/dist/error-helpers-XCh4ZJ-g.cjs.map +1 -0
- package/dist/error-helpers-lnwgNOw9.js +145 -0
- package/dist/error-helpers-lnwgNOw9.js.map +1 -0
- package/dist/error-messages-CGpW1fsg.d.cts +48 -0
- package/dist/error-messages-CGpW1fsg.d.cts.map +1 -0
- package/dist/error-messages-CGpW1fsg.d.ts +48 -0
- package/dist/error-messages-CGpW1fsg.d.ts.map +1 -0
- package/dist/event-codes-BBJHon-I.cjs +48 -0
- package/dist/event-codes-BBJHon-I.cjs.map +1 -0
- package/dist/event-codes-BgcJWsov.d.cts +42 -0
- package/dist/event-codes-BgcJWsov.d.cts.map +1 -0
- package/dist/event-codes-BgcJWsov.d.ts +42 -0
- package/dist/event-codes-BgcJWsov.d.ts.map +1 -0
- package/dist/event-codes-DR5_VlaR.js +43 -0
- package/dist/event-codes-DR5_VlaR.js.map +1 -0
- package/dist/generic/index.cjs +91 -0
- package/dist/generic/index.cjs.map +1 -0
- package/dist/generic/index.d.cts +27 -0
- package/dist/generic/index.d.cts.map +1 -0
- package/dist/generic/index.d.ts +27 -0
- package/dist/generic/index.d.ts.map +1 -0
- package/dist/generic/index.js +80 -0
- package/dist/generic/index.js.map +1 -0
- package/dist/hono/index.cjs +309 -0
- package/dist/hono/index.cjs.map +1 -0
- package/dist/hono/index.d.cts +272 -0
- package/dist/hono/index.d.cts.map +1 -0
- package/dist/hono/index.d.ts +272 -0
- package/dist/hono/index.d.ts.map +1 -0
- package/dist/hono/index.js +290 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/hono-openapi/index.cjs +326 -0
- package/dist/hono-openapi/index.cjs.map +1 -0
- package/dist/hono-openapi/index.d.cts +14 -0
- package/dist/hono-openapi/index.d.cts.map +1 -0
- package/dist/hono-openapi/index.d.ts +14 -0
- package/dist/hono-openapi/index.d.ts.map +1 -0
- package/dist/hono-openapi/index.js +307 -0
- package/dist/hono-openapi/index.js.map +1 -0
- package/dist/http-client-BVF3iktR.cjs +211 -0
- package/dist/http-client-BVF3iktR.cjs.map +1 -0
- package/dist/http-client-Da0-OMfc.js +206 -0
- package/dist/http-client-Da0-OMfc.js.map +1 -0
- package/dist/index-BYzDaMR9.d.ts +312 -0
- package/dist/index-BYzDaMR9.d.ts.map +1 -0
- package/dist/index-CNNMCrdl.d.ts +66 -0
- package/dist/index-CNNMCrdl.d.ts.map +1 -0
- package/dist/index-DBZoLU4E.d.ts +240 -0
- package/dist/index-DBZoLU4E.d.ts.map +1 -0
- package/dist/index-DcvQWByo.d.cts +66 -0
- package/dist/index-DcvQWByo.d.cts.map +1 -0
- package/dist/index-Dold-Ycb.d.cts +1711 -0
- package/dist/index-Dold-Ycb.d.cts.map +1 -0
- package/dist/index-Dold-Ycb.d.ts +1711 -0
- package/dist/index-Dold-Ycb.d.ts.map +1 -0
- package/dist/index-jAO62-OD.d.cts +240 -0
- package/dist/index-jAO62-OD.d.cts.map +1 -0
- package/dist/index-o7nXcl7z.d.cts +312 -0
- package/dist/index-o7nXcl7z.d.cts.map +1 -0
- package/dist/index.cjs +89 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +114 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt-BBNqk0TV.cjs +155 -0
- package/dist/jwt-BBNqk0TV.cjs.map +1 -0
- package/dist/jwt-DhqgH94B.js +150 -0
- package/dist/jwt-DhqgH94B.js.map +1 -0
- package/dist/key-resolver-CESqj4-P.cjs +45 -0
- package/dist/key-resolver-CESqj4-P.cjs.map +1 -0
- package/dist/key-resolver-D56I2Zpz.js +34 -0
- package/dist/key-resolver-D56I2Zpz.js.map +1 -0
- package/dist/parse-error-response-6qOQS5y9.cjs +316 -0
- package/dist/parse-error-response-6qOQS5y9.cjs.map +1 -0
- package/dist/parse-error-response-BM9-kjs0.js +239 -0
- package/dist/parse-error-response-BM9-kjs0.js.map +1 -0
- package/dist/path-segment-C25i6aaH.cjs +29 -0
- package/dist/path-segment-C25i6aaH.cjs.map +1 -0
- package/dist/path-segment-CyqnaFrP.js +24 -0
- package/dist/path-segment-CyqnaFrP.js.map +1 -0
- package/dist/react/index.cjs +336 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +151 -0
- package/dist/react/index.d.cts.map +1 -0
- package/dist/react/index.d.ts +151 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +300 -0
- package/dist/react/index.js.map +1 -0
- package/dist/refresh-dedup-CKaHHe7m.js +14 -0
- package/dist/refresh-dedup-CKaHHe7m.js.map +1 -0
- package/dist/refresh-dedup-CLdACQXR.cjs +19 -0
- package/dist/refresh-dedup-CLdACQXR.cjs.map +1 -0
- package/dist/rolldown-runtime-CmQyd0Gu.cjs +27 -0
- package/dist/routes-DpAzgY1V.cjs +424 -0
- package/dist/routes-DpAzgY1V.cjs.map +1 -0
- package/dist/routes-F1g5aVqP.js +347 -0
- package/dist/routes-F1g5aVqP.js.map +1 -0
- package/dist/s2s/index.cjs +24 -0
- package/dist/s2s/index.d.cts +5 -0
- package/dist/s2s/index.d.ts +5 -0
- package/dist/s2s/index.js +5 -0
- package/dist/s2s-6wbotr78.cjs +926 -0
- package/dist/s2s-6wbotr78.cjs.map +1 -0
- package/dist/s2s-B_0SIQzn.js +897 -0
- package/dist/s2s-B_0SIQzn.js.map +1 -0
- package/dist/sign-C7y6xdvT.cjs +324 -0
- package/dist/sign-C7y6xdvT.cjs.map +1 -0
- package/dist/sign-HFtcYwa-.js +259 -0
- package/dist/sign-HFtcYwa-.js.map +1 -0
- package/dist/tokens-C1nzkn21.cjs +232 -0
- package/dist/tokens-C1nzkn21.cjs.map +1 -0
- package/dist/tokens-C3Z40qd7.js +107 -0
- package/dist/tokens-C3Z40qd7.js.map +1 -0
- package/dist/types-B5sf7kKE.d.cts +52 -0
- package/dist/types-B5sf7kKE.d.cts.map +1 -0
- package/dist/types-CLOIHzRu.d.ts +96 -0
- package/dist/types-CLOIHzRu.d.ts.map +1 -0
- package/dist/types-CQTZdZIF.d.ts +52 -0
- package/dist/types-CQTZdZIF.d.ts.map +1 -0
- package/dist/types-DGeQ8j4k.d.cts +538 -0
- package/dist/types-DGeQ8j4k.d.cts.map +1 -0
- package/dist/types-DIUWza9-.d.ts +538 -0
- package/dist/types-DIUWza9-.d.ts.map +1 -0
- package/dist/types-qh6ANBCV.d.cts +96 -0
- package/dist/types-qh6ANBCV.d.cts.map +1 -0
- package/dist/webhooks/index.cjs +8 -0
- package/dist/webhooks/index.d.cts +5 -0
- package/dist/webhooks/index.d.ts +5 -0
- package/dist/webhooks/index.js +4 -0
- package/dist/webhooks-B5sAWC9W.js +74 -0
- package/dist/webhooks-B5sAWC9W.js.map +1 -0
- package/dist/webhooks-Cx11psg1.cjs +79 -0
- package/dist/webhooks-Cx11psg1.cjs.map +1 -0
- package/package.json +192 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s2s-6wbotr78.cjs","names":["signS2SHeaders","isDelegableAudience","isDelegableScope","TOKEN_EXCHANGE_GRANT_TYPE","ACCESS_TOKEN_TYPE","isServiceAudience","isScopeOfAudience","apiPath","INTERNAL_TOKEN_ROUTES","INTERNAL_TOKEN_EXCHANGE_ROUTES","encodePathSegment","SUBJECT_TOKEN_INVALID_CODE","parseErrorResponse","apiPath","INTERNAL_USER_ROUTES","WEBHOOK_ROUTES","INTERNAL_EMPRESA_ROUTES","INTERNAL_GRUPO_ROUTES","DIRECTORIO_ROUTES","SUBJECT_TOKEN_HEADER","INTERNAL_AUTORIZACION_ROUTES","AUTORIZACION_CACHE_TTL_MS"],"sources":["../src/s2s/token-provider.ts","../src/s2s/client.ts","../src/s2s/error-codes.ts"],"sourcesContent":["/**\n * Proveedor de tokens de servicio (client credentials) para un servicio que llama a otro.\n *\n * Pide el token a `POST /api/v1/internal/token` autenticándose con la firma HMAC del service client\n * (la única ruta servicio -> servicio que la conserva), lo guarda en memoria y lo entrega a cada\n * llamada como `Authorization: Bearer`. El caché vive en la instancia: crea UN proveedor por\n * (audiencia, scope) y compártelo.\n */\n\nimport {\n ACCESS_TOKEN_TYPE,\n INTERNAL_TOKEN_EXCHANGE_ROUTES,\n INTERNAL_TOKEN_ROUTES,\n TOKEN_EXCHANGE_GRANT_TYPE,\n isDelegableAudience,\n isDelegableScope,\n isScopeOfAudience,\n isServiceAudience,\n} from '@eva_solutions/auth-contracts'\nimport { apiPath } from '../api-path'\nimport { validateHttpsUrl } from '../config'\nimport type { Result } from '../types'\nimport { signS2SHeaders } from './sign'\n\n/** Cuánto antes del vencimiento se renueva el token, en milisegundos. */\nexport const SERVICE_TOKEN_RENEW_MARGIN_MS = 30_000\n\nconst REQUEST_TIMEOUT_MS = 10_000\n\n// Margen para que el plazo de quien se une no venza antes que el aborto del que inició el pedido.\nconst JOIN_GRACE_MS = 1_000\n\nconst encoder = new TextEncoder()\n\nexport type ServiceTokenProviderConfig = {\n /**\n * URL base del Auth Service (sin `/api/v1`). Se requiere https (o http con host loopback para\n * tests); admite path (`https://host/auth`).\n */\n authUrl: string\n /** Slug del service client (`clientId`) que firma el pedido. */\n clientId: string\n /** Clave del service client en hex (64 chars). Nunca viaja: solo firma el pedido. */\n secretHex: string\n /** Servicio destino del token (`'auth-api'`, `'whatsapp-api'`). */\n audience: string\n /** Permisos pedidos separados por espacio. Si falta, se piden todos los concedidos. */\n scope?: string\n}\n\n/**\n * What the clients that call a service need from a provider: a token and a way to drop a rejected\n * one. `createServiceTokenProvider` returns more ({@link ServiceTokenProvider}); a hand-made source\n * (tests, another credential flow) only needs these two.\n */\nexport type ServiceTokenSource = {\n /**\n * Devuelve un token vigente: el guardado mientras falten más de 30 s para su vencimiento, o uno\n * nuevo. Los pedidos simultáneos comparten una sola llamada al Auth Service.\n * @throws {ServiceTokenRequestError} si el Auth Service rechaza el pedido; `Error` de red si no responde.\n */\n getToken(): Promise<string>\n /**\n * Descarta el token guardado para que la próxima `getToken()` pida uno nuevo. Úsalo cuando el\n * servicio destino responde 401 con un token que creías vigente, pasando ESE token:\n * solo se descarta si sigue siendo el guardado. Así, N respuestas 401 simultáneas del mismo\n * token provocan UN pedido nuevo (la primera descarta; las demás ven que ya no es el guardado\n * y comparten el pedido en curso o el token renovado). Nunca descarta un pedido en curso.\n * Sin argumento descarta el token guardado, sea cual sea.\n */\n invalidate(rejectedToken?: string): void\n}\n\n/** Input of {@link ServiceTokenProvider.exchangeToken}. */\nexport type ExchangeTokenInput = {\n /**\n * Token to exchange: the access token of the user (`aud` = product of this actor) or a delegated\n * token (`aud` = audience of this actor, for a re-exchange). Pass one your service has ALREADY\n * verified (`verifyAccessToken`, `verifyDelegatedToken` or the middleware): the SDK does not.\n */\n subjectToken: string\n /** Destination service of the delegated token: one audience with a delegation edge from this client. Never `auth-api`. */\n audience: string\n /** Permissions asked for, separated by space. If absent, everything delegable on that edge. */\n scope?: string\n}\n\n/** A delegated token (`typ: dlg-at+jwt`) and the permissions it carries. */\nexport type DelegatedTokenGrant = {\n accessToken: string\n /** Permissions issued, separated by space (they can be fewer than asked for). */\n scope: string\n}\n\n/**\n * Provider of service tokens for ONE (audience, scope), plus the token exchange of the same client.\n */\nexport type ServiceTokenProvider = ServiceTokenSource & {\n /**\n * Exchanges a subject token for a delegated one (RFC 8693) so this service can call another one\n * on behalf of the user. Authenticates with its own service token (`aud: auth-api`, permission\n * `tokens:exchange`), which it obtains and renews by itself whatever the audience of this\n * provider is.\n *\n * Caches the delegated token in this isolate until 30 s before its `exp` (it lives 120 s). The\n * key is the audience, the scope and a fingerprint of the WHOLE subject token: a token with other\n * claims (another session, user or company), or the same re-exchanged from another token of the\n * chain (other `jti`), never reuses an entry. Errors are not cached.\n *\n * Returns a Result: `invalid_grant` (session closed, user or company out, product not contracted,\n * depth or cycle) is a normal answer, not an exception. The failures of Auth keep their RFC code\n * in `error.code` (`invalid_grant`, `invalid_target`, `invalid_scope`, `invalid_client`, ...).\n */\n exchangeToken(input: ExchangeTokenInput): Promise<Result<DelegatedTokenGrant>>\n}\n\n/** El Auth Service rechazó el pedido de token. `code` es el `error` de RFC 6749 (`invalid_client`, …). */\nexport class ServiceTokenRequestError extends Error {\n readonly code: string\n readonly status: number\n /** Segundos de espera que pidió Auth con `Retry-After` (429 / 503), si los mandó. */\n readonly retryAfterSeconds?: number\n\n constructor(\n code: string,\n status: number,\n description?: string,\n retryAfterSeconds?: number,\n ) {\n super(description ?? code)\n this.name = 'ServiceTokenRequestError'\n this.code = code\n this.status = status\n if (retryAfterSeconds !== undefined) {\n this.retryAfterSeconds = retryAfterSeconds\n }\n }\n}\n\ntype CachedToken = { token: string; renewAtMs: number }\n\nasync function requestToken(\n config: ServiceTokenProviderConfig,\n url: URL,\n body: string,\n): Promise<CachedToken> {\n // El vencimiento se mide con el reloj local desde ANTES de pedir y con `expires_in` (relativo),\n // nunca comparando `exp` con el reloj local: un desfase de relojes no puede acortar ni alargar el token.\n const requestedAtMs = Date.now()\n const headers = await signS2SHeaders({\n method: 'POST',\n path: url.pathname,\n rawQuery: '',\n bodyBytes: encoder.encode(body),\n clientId: config.clientId,\n secretHex: config.secretHex,\n })\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...headers },\n body,\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n })\n const json = (await res.json().catch(() => null)) as Record<\n string,\n unknown\n > | null\n\n if (!res.ok) {\n // El límite de pedidos por client responde 429; el contrato no le da un `error` propio, así que\n // sin cuerpo RFC se trata como `temporarily_unavailable` (reintentable tras `Retry-After`).\n const code =\n typeof json?.error === 'string'\n ? json.error\n : res.status === 429\n ? 'temporarily_unavailable'\n : 'server_error'\n const retryAfterHeader = res.headers?.get('retry-after')?.trim()\n // Sin header (o no numérico) no hay espera pedida: `Number('')` sería 0, \"reintenta ya\".\n const retryAfter =\n retryAfterHeader !== undefined && /^\\d+$/.test(retryAfterHeader)\n ? Number(retryAfterHeader)\n : undefined\n const description =\n typeof json?.error_description === 'string'\n ? json.error_description\n : undefined\n throw new ServiceTokenRequestError(\n code,\n res.status,\n description,\n retryAfter,\n )\n }\n const token = json?.access_token\n const expiresIn = json?.expires_in\n if (\n typeof token !== 'string' ||\n token === '' ||\n typeof expiresIn !== 'number' ||\n !(expiresIn > 0)\n ) {\n throw new ServiceTokenRequestError(\n 'server_error',\n res.status,\n 'Respuesta de token inválida',\n )\n }\n return {\n token,\n renewAtMs: requestedAtMs + expiresIn * 1000 - SERVICE_TOKEN_RENEW_MARGIN_MS,\n }\n}\n\n/** Entries the exchange cache keeps per provider before it drops expired ones and then the oldest. */\nconst EXCHANGE_CACHE_MAX_ENTRIES = 500\n\ntype CachedGrant = { grant: DelegatedTokenGrant; renewAtMs: number }\n\nconst malformed = (message: string): Result<never> => ({\n ok: false,\n error: { kind: 'sdk', reason: 'malformed', message, status: 0 },\n})\n\n/** SHA-256 of the subject token as hex: the cache never keys on claims nobody verified here. */\nasync function fingerprint(value: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', encoder.encode(value))\n return Array.from(new Uint8Array(digest), (b) =>\n b.toString(16).padStart(2, '0'),\n ).join('')\n}\n\n/** Validates the exchange input locally (a bad audience or scope is a sure `invalid_target` / `invalid_scope`). */\nfunction validateExchangeInput(\n input: ExchangeTokenInput,\n): Result<never> | null {\n if (typeof input.subjectToken !== 'string' || input.subjectToken === '') {\n return malformed('exchangeToken: subjectToken requerido')\n }\n if (!isDelegableAudience(input.audience)) {\n return malformed(\n `exchangeToken: \"${String(input.audience)}\" no es una audiencia delegable del catálogo (auth-api nunca lo es)`,\n )\n }\n for (const scope of input.scope?.split(' ').filter(Boolean) ?? []) {\n if (!isDelegableScope(input.audience, scope)) {\n return malformed(\n `exchangeToken: \"${scope}\" no es un permiso delegable de la audiencia \"${input.audience}\"`,\n )\n }\n }\n return null\n}\n\nfunction postExchange(\n url: URL,\n bearer: string,\n input: ExchangeTokenInput,\n): Promise<Response> {\n return fetch(url, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${bearer}`,\n },\n body: JSON.stringify({\n grant_type: TOKEN_EXCHANGE_GRANT_TYPE,\n subject_token: input.subjectToken,\n subject_token_type: ACCESS_TOKEN_TYPE,\n audience: input.audience,\n ...(input.scope !== undefined && { scope: input.scope }),\n }),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n })\n}\n\n/**\n * Crea un proveedor de tokens de servicio.\n *\n * Deduplica los pedidos simultáneos dentro del mismo proceso (isolate): N llamadas concurrentes a\n * `getToken()` con el caché vacío o vencido hacen UN pedido al Auth Service. Un pedido fallido no\n * se guarda: la siguiente llamada reintenta.\n *\n * Valida su configuración al crearse (audiencia del catálogo, permisos de esa audiencia, clave hex).\n *\n * @example\n * ```ts\n * const provider = createServiceTokenProvider({\n * authUrl: env.AUTH_URL,\n * clientId: env.AUTH_CLIENT_ID,\n * secretHex: env.AUTH_CLIENT_SECRET_HEX,\n * audience: 'auth-api',\n * })\n * const s2s = createS2SClient({ baseUrl: env.AUTH_URL, tokenProvider: provider })\n * ```\n */\nexport function createServiceTokenProvider(\n config: ServiceTokenProviderConfig,\n): ServiceTokenProvider {\n validateHttpsUrl(config.authUrl, 'ServiceTokenProviderConfig.authUrl')\n if (!isServiceAudience(config.audience)) {\n throw new TypeError(\n `[eva-auth-sdk] createServiceTokenProvider: audience \"${config.audience}\" no es una audiencia de servicio del catálogo`,\n )\n }\n for (const scope of config.scope?.split(' ').filter(Boolean) ?? []) {\n if (!isScopeOfAudience(config.audience, scope)) {\n throw new TypeError(\n `[eva-auth-sdk] createServiceTokenProvider: \"${scope}\" no es un permiso de la audiencia \"${config.audience}\"`,\n )\n }\n }\n if (!/^(?:[0-9a-fA-F]{2})+$/.test(config.secretHex)) {\n throw new TypeError(\n '[eva-auth-sdk] createServiceTokenProvider: secretHex inválido (formato hex requerido)',\n )\n }\n const url = new URL(\n `${config.authUrl.replace(/\\/$/, '')}${apiPath(INTERNAL_TOKEN_ROUTES.issue)}`,\n )\n const body = JSON.stringify({\n audience: config.audience,\n ...(config.scope !== undefined && { scope: config.scope }),\n })\n\n let cached: CachedToken | undefined\n let inFlight: Promise<string> | undefined\n\n // Token exchange: authenticates with a service token of its own (`aud: auth-api`, permission\n // `tokens:exchange`), whatever the audience of this provider is. Created on first use.\n const exchangeUrl = new URL(\n `${config.authUrl.replace(/\\/$/, '')}${apiPath(INTERNAL_TOKEN_EXCHANGE_ROUTES.exchange)}`,\n )\n let exchangeBearer: ServiceTokenSource | undefined\n const exchangeCache = new Map<string, CachedGrant>()\n\n const rememberGrant = (key: string, entry: CachedGrant): void => {\n if (exchangeCache.size >= EXCHANGE_CACHE_MAX_ENTRIES) {\n const now = Date.now()\n for (const [k, v] of exchangeCache) {\n if (now >= v.renewAtMs) exchangeCache.delete(k)\n }\n if (exchangeCache.size >= EXCHANGE_CACHE_MAX_ENTRIES) {\n const oldest = exchangeCache.keys().next().value\n if (oldest !== undefined) exchangeCache.delete(oldest)\n }\n }\n exchangeCache.set(key, entry)\n }\n\n // Pedidos en curso por llave: dos llamadas simultáneas iguales hacen UN pedido (como `getToken`).\n const exchangeInFlight = new Map<\n string,\n Promise<Result<DelegatedTokenGrant>>\n >()\n\n const requestExchange = async (\n input: ExchangeTokenInput,\n key: string,\n ): Promise<Result<DelegatedTokenGrant>> => {\n try {\n exchangeBearer ??= createServiceTokenProvider({\n authUrl: config.authUrl,\n clientId: config.clientId,\n secretHex: config.secretHex,\n audience: 'auth-api',\n scope: 'tokens:exchange',\n })\n // As in the S2S client: a 401 means the Bearer was not good (revoked, client disabled);\n // drop it and try ONCE more with a fresh one.\n const requestedAtMs = Date.now()\n let bearer = await exchangeBearer.getToken()\n let res = await postExchange(exchangeUrl, bearer, input)\n if (res.status === 401) {\n exchangeBearer.invalidate(bearer)\n bearer = await exchangeBearer.getToken()\n res = await postExchange(exchangeUrl, bearer, input)\n }\n const json = (await res.json().catch(() => null)) as Record<\n string,\n unknown\n > | null\n\n if (!res.ok) {\n const code =\n typeof json?.error === 'string'\n ? json.error\n : res.status === 429\n ? 'temporarily_unavailable'\n : 'server_error'\n return {\n ok: false,\n error: {\n kind: 'api',\n code,\n message:\n typeof json?.error_description === 'string'\n ? json.error_description\n : code,\n status: res.status,\n },\n }\n }\n const accessToken = json?.access_token\n const expiresIn = json?.expires_in\n const scope = json?.scope\n if (\n typeof accessToken !== 'string' ||\n accessToken === '' ||\n typeof expiresIn !== 'number' ||\n !(expiresIn > 0) ||\n typeof scope !== 'string' ||\n json?.issued_token_type !== ACCESS_TOKEN_TYPE ||\n json?.token_type !== 'Bearer'\n ) {\n return {\n ok: false,\n error: {\n kind: 'api',\n code: 'server_error',\n message: 'Respuesta de token exchange inválida',\n status: res.status,\n },\n }\n }\n const grant: DelegatedTokenGrant = { accessToken, scope }\n rememberGrant(key, {\n grant,\n renewAtMs:\n requestedAtMs + expiresIn * 1000 - SERVICE_TOKEN_RENEW_MARGIN_MS,\n })\n return { ok: true, data: grant }\n } catch (err) {\n // Auth refused the Bearer request itself (bad signature, disabled client, no grant).\n if (err instanceof ServiceTokenRequestError) {\n return {\n ok: false,\n error: {\n kind: 'api',\n code: err.code,\n message: err.message,\n status: err.status,\n },\n }\n }\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'network',\n message: err instanceof Error ? err.message : 'Network error',\n status: 0,\n },\n }\n }\n }\n\n const exchangeToken = async (\n input: ExchangeTokenInput,\n ): Promise<Result<DelegatedTokenGrant>> => {\n const invalid = validateExchangeInput(input)\n if (invalid !== null) return invalid\n\n const scopeKey = (input.scope ?? '')\n .split(' ')\n .filter(Boolean)\n .sort()\n .join(' ')\n const key = `${await fingerprint(input.subjectToken)}|${input.audience}|${scopeKey}`\n const hit = exchangeCache.get(key)\n if (hit !== undefined) {\n if (Date.now() < hit.renewAtMs) return { ok: true, data: hit.grant }\n exchangeCache.delete(key)\n }\n const pending = exchangeInFlight.get(key)\n if (pending !== undefined) {\n // Como en `getToken`: si la request que inició el pedido terminó sin esperarlo, Workers lo\n // cancela y su promesa NUNCA se resuelve (`.finally` tampoco corre). Quien se une espera\n // como máximo lo que dura un pedido más el margen; luego suelta la entrada (si sigue siendo\n // esa) y hace el suyo.\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n if (exchangeInFlight.get(key) === pending)\n exchangeInFlight.delete(key)\n exchangeToken(input).then(resolve, reject)\n }, REQUEST_TIMEOUT_MS + JOIN_GRACE_MS)\n pending.then(\n (result) => {\n clearTimeout(timer)\n resolve(result)\n },\n (err: unknown) => {\n clearTimeout(timer)\n reject(err)\n },\n )\n })\n }\n const started = requestExchange(input, key).finally(() => {\n if (exchangeInFlight.get(key) === started) exchangeInFlight.delete(key)\n })\n exchangeInFlight.set(key, started)\n return started\n }\n\n // Un pedido en curso lo comparten las requests del mismo isolate. En Cloudflare Workers, si la\n // request que lo inició termina sin esperarlo (por ejemplo `provider.getToken()` sin `await` ni\n // `waitUntil`), el runtime cancela su subrequest y esa promesa NUNCA se resuelve: quien se\n // unió quedaría colgado. Por eso los que se unen esperan como máximo lo que dura un pedido\n // (`REQUEST_TIMEOUT_MS` más un margen de 1 s); pasado ese plazo lo dan por huérfano y hacen el suyo.\n // (Probado en workerd: ver docs/api.md, sección `createServiceTokenProvider`.)\n const joinWithDeadline = (\n pending: Promise<string>,\n retry: () => Promise<string>,\n ): Promise<string> =>\n new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n if (inFlight === pending) inFlight = undefined\n retry().then(resolve, reject)\n }, REQUEST_TIMEOUT_MS + JOIN_GRACE_MS)\n pending.then(\n (token) => {\n clearTimeout(timer)\n resolve(token)\n },\n (err: unknown) => {\n clearTimeout(timer)\n reject(err)\n },\n )\n })\n\n const provider: ServiceTokenProvider = {\n getToken() {\n if (cached !== undefined && Date.now() < cached.renewAtMs) {\n return Promise.resolve(cached.token)\n }\n if (inFlight !== undefined) {\n return joinWithDeadline(inFlight, () => provider.getToken())\n }\n const pending: Promise<string> = requestToken(config, url, body)\n .then((fresh) => {\n cached = fresh\n return fresh.token\n })\n .finally(() => {\n if (inFlight === pending) inFlight = undefined\n })\n inFlight = pending\n return pending\n },\n invalidate(rejectedToken) {\n if (rejectedToken === undefined || cached?.token === rejectedToken) {\n cached = undefined\n }\n },\n exchangeToken,\n }\n return provider\n}\n","/**\n * Cliente S2S (service-to-service) para llamar a la API interna del Auth Service desde servicios\n * backend. Autentica cada llamada con `Authorization: Bearer <token de servicio>` (audiencia\n * `auth-api`) que entrega un `ServiceTokenProvider`; ante un 401 invalida el token y reintenta UNA vez.\n *\n * REQ-S2S-01, REQ-S2S-04, REQ-INT-01, REQ-INT-02 LOCKED.\n *\n * Endpoints disponibles:\n * GET /internal/users/:id\n * POST /internal/users/batch\n * POST /internal/webhooks/subscriptions\n * GET /internal/webhooks/subscriptions\n * GET /internal/webhooks/subscriptions/:id\n * PATCH /internal/webhooks/subscriptions/:id\n * DELETE /internal/webhooks/subscriptions/:id\n * POST /internal/webhooks/subscriptions/:id/rotate-secret\n * GET /internal/webhooks/deliveries\n * POST /internal/empresas\n * GET /internal/empresas/:id\n * POST /internal/empresas/:id/miembros\n * DELETE /internal/empresas/:id/miembros/:userId\n * POST /internal/empresas/:id/sucursales\n * (fase 2) PATCH /internal/empresas/:id, GET /internal/empresas, POST .../baja|reactivar,\n * PATCH .../miembros/:userId, PATCH|DELETE .../sucursales/:sucursalId, contratación\n * (.../productos), grupos (/internal/grupos), directorio (/directorio) y autorizaciones.\n *\n * Los paths salen de `INTERNAL_USER_ROUTES`, `WEBHOOK_ROUTES` e `INTERNAL_EMPRESA_ROUTES`\n * (contrato compartido) vía `apiPath`.\n */\n\nimport {\n DIRECTORIO_ROUTES,\n INTERNAL_AUTORIZACION_ROUTES,\n INTERNAL_EMPRESA_ROUTES,\n INTERNAL_GRUPO_ROUTES,\n INTERNAL_USER_ROUTES,\n SUBJECT_TOKEN_HEADER,\n SUBJECT_TOKEN_INVALID_CODE,\n USERS_BATCH_MAX_IDS,\n WEBHOOK_ROUTES,\n} from '@eva_solutions/auth-contracts'\nimport { apiPath } from '../api-path'\nimport { validateHttpsUrl } from '../config'\nimport { parseErrorResponse } from '../parse-error-response'\nimport { encodePathSegment } from '../path-segment'\nimport type { Result } from '../types'\nimport { AUTORIZACION_CACHE_TTL_MS } from './constants'\nimport type {\n S2SClientConfig,\n S2SGetUserResult,\n S2SBatchUsersInput,\n S2SBatchUsersResult,\n CreateWebhookSubscriptionInput,\n UpdateWebhookSubscriptionInput,\n ListWebhookDeliveriesQuery,\n AddEmpresaMemberInput,\n AddGrupoEmpresaInput,\n AutorizacionResult,\n CheckAutorizacionInput,\n CheckAutorizacionResult,\n ContratacionResult,\n ContratadoResult,\n CreateAutorizacionInput,\n CreateEmpresaInput,\n CreateGrupoInput,\n CreateSucursalInput,\n DeactivateSucursalInput,\n DeleteAutorizacionInput,\n DirectorioResult,\n EmpresaEstadoResult,\n EmpresaMemberResult,\n EmpresaResult,\n GetEmpresaResult,\n GrupoResult,\n ListAutorizacionesInput,\n ListAutorizacionesResult,\n ListEmpresasInput,\n ListEmpresasResult,\n RemoveEmpresaMemberInput,\n RemoveGrupoEmpresaInput,\n RenameGrupoInput,\n SearchDirectorioInput,\n SetContratacionInput,\n SubjectTokenInput,\n SucursalResult,\n UpdateEmpresaInput,\n UpdateEmpresaMemberInput,\n UpdateSucursalInput,\n} from './types'\nimport { ServiceTokenRequestError } from './token-provider'\nimport type {\n WebhookSubscription,\n WebhookSubscriptionWithSecret,\n WebhookDelivery,\n RotateWebhookSecretResult,\n} from '../webhooks/types'\n\n/**\n * Tipo del cliente S2S retornado por `createS2SClient`.\n */\nexport type S2SClient = {\n getUser(userId: string): Promise<Result<S2SGetUserResult>>\n batchUsers(input: S2SBatchUsersInput): Promise<Result<S2SBatchUsersResult>>\n createWebhookSubscription(\n input: CreateWebhookSubscriptionInput,\n ): Promise<Result<WebhookSubscriptionWithSecret>>\n listWebhookSubscriptions(): Promise<\n Result<{ subscriptions: WebhookSubscription[] }>\n >\n getWebhookSubscription(id: string): Promise<Result<WebhookSubscription>>\n updateWebhookSubscription(\n id: string,\n input: UpdateWebhookSubscriptionInput,\n ): Promise<Result<WebhookSubscription>>\n deleteWebhookSubscription(id: string): Promise<Result<void>>\n rotateWebhookSubscriptionSecret(\n id: string,\n ): Promise<Result<RotateWebhookSecretResult>>\n listWebhookDeliveries(\n query?: ListWebhookDeliveriesQuery,\n ): Promise<Result<{ deliveries: WebhookDelivery[] }>>\n // ----- Empresas (token de servicio + `subjectToken` de la persona donde actúa una persona) -----\n\n /**\n * Crea una empresa (`empresas:escribir`, el actor necesita `producto`). La persona del\n * `subjectToken` queda como titular y el producto del actor en `prueba`. 409 si el RUC, la razón\n * social o el slug ya existen; 429 si la persona superó el límite de altas.\n */\n createEmpresa(input: CreateEmpresaInput): Promise<Result<EmpresaResult>>\n /** Edita datos maestros, perfil y visibilidad en el directorio (administrador o titular; `empresas:escribir`). */\n updateEmpresa(\n empresaId: string,\n input: UpdateEmpresaInput,\n ): Promise<Result<EmpresaResult>>\n /** Empresas que contrataron el producto del actor, paginadas con `cursor` (`empresas:leer`). */\n listEmpresas(query?: ListEmpresasInput): Promise<Result<ListEmpresasResult>>\n /**\n * Una empresa (`empresas:leer`): vista completa (`vista: 'completa'`) si el actor tiene producto y\n * la empresa lo contrató; recortada (`vista: 'recortada'`, sin contacto ni miembros) si el actor\n * no tiene producto (servicio compartido). 404 si no existe o no la contrató.\n */\n getEmpresa(empresaId: string): Promise<Result<GetEmpresaResult>>\n /** Da de baja una empresa (solo facturación, permiso `empresas:baja`; no lleva persona). */\n bajaEmpresa(empresaId: string): Promise<Result<EmpresaEstadoResult>>\n /** Reactiva una empresa de baja (solo facturación, permiso `empresas:baja`). */\n reactivarEmpresa(empresaId: string): Promise<Result<EmpresaEstadoResult>>\n /** Agrega un miembro como `miembro`; si ya lo es, 409 `conflict` (administrador o titular; `empresas:escribir`). */\n addEmpresaMember(\n empresaId: string,\n input: AddEmpresaMemberInput,\n ): Promise<Result<EmpresaMemberResult>>\n /** Cambia el rol de un miembro (solo titular; `empresas:escribir`). */\n setEmpresaMemberRole(\n empresaId: string,\n userId: string,\n input: UpdateEmpresaMemberInput,\n ): Promise<Result<EmpresaMemberResult>>\n /**\n * Quita un miembro (`empresas:escribir`); si no lo es, 404 `not_found`. Con `userId` igual a la\n * persona del token es salir por cuenta propia (cualquier rol, salvo el último titular).\n */\n removeEmpresaMember(\n empresaId: string,\n userId: string,\n input: RemoveEmpresaMemberInput,\n ): Promise<Result<void>>\n /** Crea una sucursal de la empresa (administrador o titular; `empresas:escribir`). */\n createSucursal(\n empresaId: string,\n input: CreateSucursalInput,\n ): Promise<Result<SucursalResult>>\n /** Edita una sucursal (administrador o titular; `empresas:escribir`). */\n updateSucursal(\n empresaId: string,\n sucursalId: string,\n input: UpdateSucursalInput,\n ): Promise<Result<SucursalResult>>\n /** Baja lógica de una sucursal, `activa = false` (administrador o titular; `empresas:escribir`). */\n deactivateSucursal(\n empresaId: string,\n sucursalId: string,\n input: DeactivateSucursalInput,\n ): Promise<Result<void>>\n\n // ----- Contratación de productos -----\n\n /**\n * Pide la contratación del PROPIO producto del actor para una empresa existente\n * (`pendiente_pago`; `contrataciones:pedir`). La persona del `subjectToken` debe ser titular:\n * 404 igual si la empresa no existe o no es titular. Solo si no hay fila o está `cancelado`.\n */\n requestContratacion(\n empresaId: string,\n input: SubjectTokenInput,\n ): Promise<Result<ContratacionResult>>\n /** Cancela la contratación del propio producto (`cancelado`, desde cualquier estado; solo titular). */\n cancelContratacion(\n empresaId: string,\n input: SubjectTokenInput,\n ): Promise<Result<void>>\n /**\n * ¿La empresa tiene contratado ese producto? (`contrataciones:leer`). Para servicios compartidos\n * que atienden llamadas de servicio donde no hay token delegado.\n */\n getContratacion(\n empresaId: string,\n producto: string,\n ): Promise<Result<ContratadoResult>>\n /** Facturación: escribe el estado y el vencimiento de cualquier fila (`contrataciones:escribir`, actor sin producto). */\n setContratacion(\n empresaId: string,\n producto: string,\n input: SetContratacionInput,\n ): Promise<Result<ContratacionResult>>\n\n // ----- Grupos de empresas (solo titular; `empresas:escribir`) -----\n\n /** Crea un grupo con una empresa de la persona. */\n createGrupo(input: CreateGrupoInput): Promise<Result<GrupoResult>>\n /** Renombra el grupo (titular de alguna de sus empresas). */\n renameGrupo(\n grupoId: string,\n input: RenameGrupoInput,\n ): Promise<Result<GrupoResult>>\n /** Agrega una empresa de la que la persona es titular. */\n addGrupoEmpresa(\n grupoId: string,\n input: AddGrupoEmpresaInput,\n ): Promise<Result<GrupoResult>>\n /** Quita una empresa del grupo; un grupo que queda vacío se borra solo. */\n removeGrupoEmpresa(\n grupoId: string,\n empresaId: string,\n input: RemoveGrupoEmpresaInput,\n ): Promise<Result<void>>\n\n // ----- Directorio -----\n\n /** Busca en el directorio de empresas visibles (`directorio:leer`). Solo campos de perfil público; 50 por página. */\n searchDirectorio(\n query?: SearchDirectorioInput,\n ): Promise<Result<DirectorioResult>>\n\n // ----- Autorizaciones entre empresas -----\n\n /** Concede un permiso del catálogo entre empresas a otra empresa (administrador o titular de la otorgante; `autorizaciones:escribir`). 409 si ya está vigente. */\n createAutorizacion(\n otorganteId: string,\n input: CreateAutorizacionInput,\n ): Promise<Result<AutorizacionResult>>\n /** Revoca (otorgante) o renuncia a (beneficiaria) una autorización; administrador o titular (`autorizaciones:escribir`). */\n deleteAutorizacion(\n empresaId: string,\n autorizacionId: string,\n input: DeleteAutorizacionInput,\n ): Promise<Result<void>>\n /** Autorizaciones vigentes de la empresa, `otorgadas` o `recibidas` (administrador o titular; `autorizaciones:leer`). La persona viaja en el header `x-eva-subject-token`. */\n listAutorizaciones(\n empresaId: string,\n input: ListAutorizacionesInput,\n ): Promise<Result<ListAutorizacionesResult>>\n /**\n * ¿La otorgante autorizó ese permiso a la beneficiaria? (`autorizaciones:leer`, solo actores cuya\n * audiencia es dueña del permiso; puede tener además `producto`). Vale solo si las dos empresas están activas.\n *\n * Guarda el resultado 30 s (`AUTORIZACION_CACHE_TTL_MS`) por cliente: una revocación o una baja\n * tardan como máximo eso en notarse. Los errores no se guardan.\n */\n checkAutorizacion(\n input: CheckAutorizacionInput,\n ): Promise<Result<CheckAutorizacionResult>>\n}\n\n// ---------------------------------------------------------------------------\n// Helper interno\n// ---------------------------------------------------------------------------\n\n/**\n * Construye el query string a partir de un objeto de parámetros.\n * Omite valores undefined.\n */\nfunction buildQueryString(\n params: Record<string, string | number | undefined>,\n): string {\n const parts: string[] = []\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n parts.push(\n `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`,\n )\n }\n }\n return parts.join('&')\n}\n\nfunction invalidIdResult(method: string): Result<never> {\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'malformed',\n message: `${method}: id inválido (no puede ser vacío, \".\" ni \"..\")`,\n status: 0,\n },\n }\n}\n\n/**\n * Codifica cada id como UN segmento del path (`encodePathSegment`). Devuelve los segmentos listos\n * para `apiPath` o, si alguno es vacío, `.` o `..`, el `Result` de error (sin hacer la request).\n */\nfunction encodeSegments<K extends string>(\n method: string,\n values: Record<K, string>,\n): Record<K, string> | Result<never> {\n const out = {} as Record<K, string>\n for (const key of Object.keys(values) as K[]) {\n const segment = encodePathSegment(values[key])\n if (segment === null) return invalidIdResult(method)\n out[key] = segment\n }\n return out\n}\n\n/** ¿El cuerpo de error es el fallo del token de la persona (`subject_token_invalid`)? */\nconst isSubjectTokenFailure = (body: unknown): boolean =>\n (body as { error?: { code?: unknown } } | null)?.error?.code ===\n SUBJECT_TOKEN_INVALID_CODE\n\nconst isInvalid = (value: object): value is Result<never> => 'ok' in value\n\n/** Entradas que guarda el caché de `checkAutorizacion` antes de soltar las vencidas y luego la más vieja. */\nconst AUTORIZACION_CACHE_MAX_ENTRIES = 1000\n\n/**\n * Realiza un fetch autenticado con el token de servicio del proveedor. Un 401 invalida el token y\n * reintenta una sola vez con uno nuevo. Retorna `Result<T>` con la propiedad `data` del body.\n */\nasync function s2sFetch<T>({\n config,\n method,\n pathname,\n rawQuery = '',\n body,\n headers: extraHeaders,\n}: {\n config: S2SClientConfig\n method: string\n pathname: string\n rawQuery?: string\n body?: unknown\n /** Headers extra de ESTA llamada (p. ej. la persona en un GET que no tiene body). */\n headers?: Record<string, string>\n}): Promise<Result<T>> {\n try {\n const bodyText = body !== undefined ? JSON.stringify(body) : undefined\n const url = rawQuery\n ? `${config.baseUrl}${pathname}?${rawQuery}`\n : `${config.baseUrl}${pathname}`\n\n let usedToken = ''\n const send = async (): Promise<Response> => {\n const token = await config.tokenProvider.getToken()\n usedToken = token\n return fetch(url, {\n method,\n headers: {\n 'content-type': 'application/json',\n ...extraHeaders,\n authorization: `Bearer ${token}`,\n },\n body: bodyText,\n signal: AbortSignal.timeout(10_000),\n })\n }\n\n let res = await send()\n if (res.status === 401) {\n // Solo un 401 del Bearer de servicio descarta el token de servicio. Si Auth dice que el que\n // falló es el token de la PERSONA, el de servicio está bien: no se invalida ni se reintenta.\n const body: unknown = await res.json().catch(() => null)\n if (isSubjectTokenFailure(body)) {\n return { ok: false, error: parseErrorResponse(res.status, body) }\n }\n // El token pudo vencer o revocarse antes de lo que creía el proveedor: se descarta y se\n // reintenta UNA vez. Un segundo 401 es definitivo.\n // Se pasa el token rechazado: con N 401 simultáneos solo el primero descarta; el resto\n // comparte el token renovado en vez de provocar un pedido por cada uno.\n config.tokenProvider.invalidate(usedToken)\n res = await send()\n }\n\n if (!res.ok) {\n const responseBody = await res.json().catch(() => null)\n return { ok: false, error: parseErrorResponse(res.status, responseBody) }\n }\n\n // 204 No Content — Result<void>\n if (res.status === 204) {\n return { ok: true, data: undefined as T }\n }\n\n const json = (await res.json()) as { data: T }\n return { ok: true, data: json.data }\n } catch (err) {\n // El Auth Service rechazó el pedido de token (firma inválida, client deshabilitado, sin\n // concesión): es un error de API con su `error` RFC 6749 como code.\n if (err instanceof ServiceTokenRequestError) {\n return {\n ok: false,\n error: {\n kind: 'api',\n code: err.code,\n message: err.message,\n status: err.status,\n },\n }\n }\n const message = err instanceof Error ? err.message : 'Network error'\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'network',\n message,\n status: 0,\n },\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Crea un cliente S2S autenticado para comunicarse con la API interna del Auth Service.\n *\n * @example\n * ```ts\n * const tokenProvider = createServiceTokenProvider({\n * authUrl: 'https://auth.miapp.com',\n * clientId: 'mi-servicio',\n * secretHex: env.AUTH_CLIENT_SECRET_HEX,\n * audience: 'auth-api',\n * })\n * const s2s = createS2SClient({ baseUrl: 'https://auth.miapp.com', tokenProvider })\n * const result = await s2s.getUser(userId)\n * if (!result.ok) return handleError(result.error)\n * return result.data // perfil del usuario\n * ```\n */\nexport function createS2SClient(config: S2SClientConfig): S2SClient {\n validateHttpsUrl(config.baseUrl, 'S2SClientConfig.baseUrl')\n // Caché de `checkAutorizacion`: vive en el cliente (un cliente por isolate, como el proveedor).\n const autorizacionCache = new Map<\n string,\n { autorizado: boolean; expiresAtMs: number }\n >()\n return {\n async getUser(userId: string): Promise<Result<S2SGetUserResult>> {\n const segment = encodePathSegment(userId)\n if (segment === null) return invalidIdResult('getUser')\n return s2sFetch<S2SGetUserResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_USER_ROUTES.get, { id: segment }),\n })\n },\n\n /**\n * Consulta múltiples usuarios por ID en una sola llamada.\n *\n * @param input - Input con la lista de IDs a consultar.\n * @param input.ids - Máximo `USERS_BATCH_MAX_IDS` (100, constante del contrato compartido)\n * IDs por llamada. El schema del request no lleva ese tope: lo aplica este cliente.\n * Si se superan, retorna error sin hacer fetch al API.\n */\n async batchUsers(\n input: S2SBatchUsersInput,\n ): Promise<Result<S2SBatchUsersResult>> {\n if (input.ids.length > USERS_BATCH_MAX_IDS) {\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'malformed',\n message: `batchUsers acepta máximo ${USERS_BATCH_MAX_IDS} IDs por llamada (recibidos: ${input.ids.length})`,\n status: 0,\n },\n }\n }\n return s2sFetch<S2SBatchUsersResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_USER_ROUTES.batch),\n body: input,\n })\n },\n\n async createWebhookSubscription(\n input: CreateWebhookSubscriptionInput,\n ): Promise<Result<WebhookSubscriptionWithSecret>> {\n return s2sFetch<WebhookSubscriptionWithSecret>({\n config,\n method: 'POST',\n pathname: apiPath(WEBHOOK_ROUTES.createSubscription),\n body: input,\n })\n },\n\n async listWebhookSubscriptions(): Promise<\n Result<{ subscriptions: WebhookSubscription[] }>\n > {\n return s2sFetch<{ subscriptions: WebhookSubscription[] }>({\n config,\n method: 'GET',\n pathname: apiPath(WEBHOOK_ROUTES.listSubscriptions),\n })\n },\n\n async getWebhookSubscription(\n id: string,\n ): Promise<Result<WebhookSubscription>> {\n const segment = encodePathSegment(id)\n if (segment === null) return invalidIdResult('getWebhookSubscription')\n return s2sFetch<WebhookSubscription>({\n config,\n method: 'GET',\n pathname: apiPath(WEBHOOK_ROUTES.getSubscription, { id: segment }),\n })\n },\n\n async updateWebhookSubscription(\n id: string,\n input: UpdateWebhookSubscriptionInput,\n ): Promise<Result<WebhookSubscription>> {\n const segment = encodePathSegment(id)\n if (segment === null) return invalidIdResult('updateWebhookSubscription')\n return s2sFetch<WebhookSubscription>({\n config,\n method: 'PATCH',\n pathname: apiPath(WEBHOOK_ROUTES.updateSubscription, { id: segment }),\n body: input,\n })\n },\n\n async deleteWebhookSubscription(id: string): Promise<Result<void>> {\n const segment = encodePathSegment(id)\n if (segment === null) return invalidIdResult('deleteWebhookSubscription')\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(WEBHOOK_ROUTES.deleteSubscription, { id: segment }),\n })\n },\n\n async rotateWebhookSubscriptionSecret(\n id: string,\n ): Promise<Result<RotateWebhookSecretResult>> {\n const segment = encodePathSegment(id)\n if (segment === null)\n return invalidIdResult('rotateWebhookSubscriptionSecret')\n return s2sFetch<RotateWebhookSecretResult>({\n config,\n method: 'POST',\n pathname: apiPath(WEBHOOK_ROUTES.rotateSubscriptionSecret, {\n id: segment,\n }),\n })\n },\n\n async listWebhookDeliveries(\n query?: ListWebhookDeliveriesQuery,\n ): Promise<Result<{ deliveries: WebhookDelivery[] }>> {\n if (\n query?.limit !== undefined &&\n (query.limit < 1 || query.limit > 100)\n ) {\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'malformed',\n message: `listWebhookDeliveries: limit debe estar entre 1 y 100 (recibido: ${query.limit})`,\n status: 0,\n },\n }\n }\n if (query?.offset !== undefined && query.offset < 0) {\n return {\n ok: false,\n error: {\n kind: 'sdk',\n reason: 'malformed',\n message: `listWebhookDeliveries: offset no puede ser negativo (recibido: ${query.offset})`,\n status: 0,\n },\n }\n }\n const rawQuery = query\n ? buildQueryString(query as Record<string, string | number | undefined>)\n : ''\n return s2sFetch<{ deliveries: WebhookDelivery[] }>({\n config,\n method: 'GET',\n pathname: apiPath(WEBHOOK_ROUTES.listDeliveries),\n rawQuery,\n })\n },\n\n async createEmpresa(\n input: CreateEmpresaInput,\n ): Promise<Result<EmpresaResult>> {\n return s2sFetch<EmpresaResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.create),\n body: input,\n })\n },\n\n async updateEmpresa(\n empresaId: string,\n input: UpdateEmpresaInput,\n ): Promise<Result<EmpresaResult>> {\n const seg = encodeSegments('updateEmpresa', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<EmpresaResult>({\n config,\n method: 'PATCH',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.update, seg),\n body: input,\n })\n },\n\n async listEmpresas(\n query?: ListEmpresasInput,\n ): Promise<Result<ListEmpresasResult>> {\n return s2sFetch<ListEmpresasResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.list),\n rawQuery: query ? buildQueryString({ ...query }) : '',\n })\n },\n\n async getEmpresa(empresaId: string): Promise<Result<GetEmpresaResult>> {\n const seg = encodeSegments('getEmpresa', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<GetEmpresaResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.get, seg),\n })\n },\n\n async bajaEmpresa(empresaId: string): Promise<Result<EmpresaEstadoResult>> {\n const seg = encodeSegments('bajaEmpresa', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<EmpresaEstadoResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.baja, seg),\n })\n },\n\n async reactivarEmpresa(\n empresaId: string,\n ): Promise<Result<EmpresaEstadoResult>> {\n const seg = encodeSegments('reactivarEmpresa', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<EmpresaEstadoResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.reactivar, seg),\n })\n },\n\n async addEmpresaMember(\n empresaId: string,\n input: AddEmpresaMemberInput,\n ): Promise<Result<EmpresaMemberResult>> {\n const seg = encodeSegments('addEmpresaMember', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<EmpresaMemberResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.addMember, seg),\n body: input,\n })\n },\n\n async setEmpresaMemberRole(\n empresaId: string,\n userId: string,\n input: UpdateEmpresaMemberInput,\n ): Promise<Result<EmpresaMemberResult>> {\n const seg = encodeSegments('setEmpresaMemberRole', {\n id: empresaId,\n userId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<EmpresaMemberResult>({\n config,\n method: 'PATCH',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.updateMember, seg),\n body: input,\n })\n },\n\n async removeEmpresaMember(\n empresaId: string,\n userId: string,\n input: RemoveEmpresaMemberInput,\n ): Promise<Result<void>> {\n const seg = encodeSegments('removeEmpresaMember', {\n id: empresaId,\n userId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.removeMember, seg),\n body: input,\n })\n },\n\n async createSucursal(\n empresaId: string,\n input: CreateSucursalInput,\n ): Promise<Result<SucursalResult>> {\n const seg = encodeSegments('createSucursal', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<SucursalResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.createBranch, seg),\n body: input,\n })\n },\n\n async updateSucursal(\n empresaId: string,\n sucursalId: string,\n input: UpdateSucursalInput,\n ): Promise<Result<SucursalResult>> {\n const seg = encodeSegments('updateSucursal', {\n id: empresaId,\n sucursalId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<SucursalResult>({\n config,\n method: 'PATCH',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.updateBranch, seg),\n body: input,\n })\n },\n\n async deactivateSucursal(\n empresaId: string,\n sucursalId: string,\n input: DeactivateSucursalInput,\n ): Promise<Result<void>> {\n const seg = encodeSegments('deactivateSucursal', {\n id: empresaId,\n sucursalId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.deactivateBranch, seg),\n body: input,\n })\n },\n\n async requestContratacion(\n empresaId: string,\n input: SubjectTokenInput,\n ): Promise<Result<ContratacionResult>> {\n const seg = encodeSegments('requestContratacion', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<ContratacionResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.requestContratacion, seg),\n body: input,\n })\n },\n\n async cancelContratacion(\n empresaId: string,\n input: SubjectTokenInput,\n ): Promise<Result<void>> {\n const seg = encodeSegments('cancelContratacion', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.cancelContratacion, seg),\n body: input,\n })\n },\n\n async getContratacion(\n empresaId: string,\n producto: string,\n ): Promise<Result<ContratadoResult>> {\n const seg = encodeSegments('getContratacion', { id: empresaId, producto })\n if (isInvalid(seg)) return seg\n return s2sFetch<ContratadoResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.getContratacion, seg),\n })\n },\n\n async setContratacion(\n empresaId: string,\n producto: string,\n input: SetContratacionInput,\n ): Promise<Result<ContratacionResult>> {\n const seg = encodeSegments('setContratacion', { id: empresaId, producto })\n if (isInvalid(seg)) return seg\n return s2sFetch<ContratacionResult>({\n config,\n method: 'PUT',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.setContratacion, seg),\n body: input,\n })\n },\n\n async createGrupo(input: CreateGrupoInput): Promise<Result<GrupoResult>> {\n return s2sFetch<GrupoResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_GRUPO_ROUTES.create),\n body: input,\n })\n },\n\n async renameGrupo(\n grupoId: string,\n input: RenameGrupoInput,\n ): Promise<Result<GrupoResult>> {\n const seg = encodeSegments('renameGrupo', { id: grupoId })\n if (isInvalid(seg)) return seg\n return s2sFetch<GrupoResult>({\n config,\n method: 'PATCH',\n pathname: apiPath(INTERNAL_GRUPO_ROUTES.rename, seg),\n body: input,\n })\n },\n\n async addGrupoEmpresa(\n grupoId: string,\n input: AddGrupoEmpresaInput,\n ): Promise<Result<GrupoResult>> {\n const seg = encodeSegments('addGrupoEmpresa', { id: grupoId })\n if (isInvalid(seg)) return seg\n return s2sFetch<GrupoResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_GRUPO_ROUTES.addEmpresa, seg),\n body: input,\n })\n },\n\n async removeGrupoEmpresa(\n grupoId: string,\n empresaId: string,\n input: RemoveGrupoEmpresaInput,\n ): Promise<Result<void>> {\n const seg = encodeSegments('removeGrupoEmpresa', {\n id: grupoId,\n empresaId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(INTERNAL_GRUPO_ROUTES.removeEmpresa, seg),\n body: input,\n })\n },\n\n async searchDirectorio(\n query?: SearchDirectorioInput,\n ): Promise<Result<DirectorioResult>> {\n return s2sFetch<DirectorioResult>({\n config,\n method: 'GET',\n pathname: apiPath(DIRECTORIO_ROUTES.search),\n rawQuery: query ? buildQueryString({ ...query }) : '',\n })\n },\n\n async createAutorizacion(\n otorganteId: string,\n input: CreateAutorizacionInput,\n ): Promise<Result<AutorizacionResult>> {\n const seg = encodeSegments('createAutorizacion', { id: otorganteId })\n if (isInvalid(seg)) return seg\n return s2sFetch<AutorizacionResult>({\n config,\n method: 'POST',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.createAutorizacion, seg),\n body: input,\n })\n },\n\n async deleteAutorizacion(\n empresaId: string,\n autorizacionId: string,\n input: DeleteAutorizacionInput,\n ): Promise<Result<void>> {\n const seg = encodeSegments('deleteAutorizacion', {\n id: empresaId,\n autorizacionId,\n })\n if (isInvalid(seg)) return seg\n return s2sFetch<void>({\n config,\n method: 'DELETE',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.deleteAutorizacion, seg),\n body: input,\n })\n },\n\n async listAutorizaciones(\n empresaId: string,\n input: ListAutorizacionesInput,\n ): Promise<Result<ListAutorizacionesResult>> {\n const seg = encodeSegments('listAutorizaciones', { id: empresaId })\n if (isInvalid(seg)) return seg\n return s2sFetch<ListAutorizacionesResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_EMPRESA_ROUTES.listAutorizaciones, seg),\n rawQuery: buildQueryString({ direccion: input.direccion }),\n headers: { [SUBJECT_TOKEN_HEADER]: input.subjectToken },\n })\n },\n\n async checkAutorizacion(\n input: CheckAutorizacionInput,\n ): Promise<Result<CheckAutorizacionResult>> {\n const key = `${input.otorgante}|${input.beneficiaria}|${input.permiso}`\n const hit = autorizacionCache.get(key)\n if (hit !== undefined) {\n if (Date.now() < hit.expiresAtMs) {\n return { ok: true, data: { autorizado: hit.autorizado } }\n }\n autorizacionCache.delete(key)\n }\n const result = await s2sFetch<CheckAutorizacionResult>({\n config,\n method: 'GET',\n pathname: apiPath(INTERNAL_AUTORIZACION_ROUTES.verificar),\n rawQuery: buildQueryString({\n otorgante: input.otorgante,\n beneficiaria: input.beneficiaria,\n permiso: input.permiso,\n }),\n })\n if (result.ok) {\n if (autorizacionCache.size >= AUTORIZACION_CACHE_MAX_ENTRIES) {\n const now = Date.now()\n for (const [k, v] of autorizacionCache) {\n if (now >= v.expiresAtMs) autorizacionCache.delete(k)\n }\n if (autorizacionCache.size >= AUTORIZACION_CACHE_MAX_ENTRIES) {\n const oldest = autorizacionCache.keys().next().value\n if (oldest !== undefined) autorizacionCache.delete(oldest)\n }\n }\n autorizacionCache.set(key, {\n autorizado: result.data.autorizado,\n expiresAtMs: Date.now() + AUTORIZACION_CACHE_TTL_MS,\n })\n }\n return result\n },\n }\n}\n","/**\n * Códigos de error específicos del módulo S2S.\n *\n * Complementan a `ERROR_CODES` (core) para los errores propios de los endpoints\n * `/api/v1/internal/*` que consume `createS2SClient`: usuarios y subscriptions de webhooks.\n *\n * @example\n * ```ts\n * import { S2S_ERROR_CODES } from '@eva_solutions/auth-sdk/s2s'\n *\n * const r = await s2s.rotateWebhookSubscriptionSecret(id)\n * if (!r.ok && r.error.kind === 'api' && r.error.code === S2S_ERROR_CODES.webhook_secret_rotation_conflict) {\n * // otra rotación concurrente ganó; esta llamada no recibió clave. Reintenta.\n * }\n * ```\n */\nexport const S2S_ERROR_CODES = {\n /** `GET /internal/users/{id}`: el usuario no existe o está soft-deleted (404). */\n user_not_found: 'user_not_found',\n /** Ya existe una subscription del mismo service client con la misma URL y los mismos eventCodes (409). */\n webhook_subscription_duplicate: 'webhook_subscription_duplicate',\n /** La subscription no existe o pertenece a otro service client (404). */\n webhook_subscription_not_found: 'webhook_subscription_not_found',\n /**\n * `rotate-secret` perdió contra otra rotación concurrente de la misma subscription (409).\n * El perdedor no recibe clave; es reintentable.\n */\n webhook_secret_rotation_conflict: 'webhook_secret_rotation_conflict',\n /** URL de webhook inválida: reglas estáticas, IP privada o host sin direcciones (400). */\n webhook_url_invalid: 'webhook_url_invalid',\n /** `eventCodes` vacío al crear o actualizar (400). */\n webhook_event_codes_empty: 'webhook_event_codes_empty',\n} as const\n\n/** Unión de literales de los error codes específicos del módulo S2S. */\nexport type S2SErrorCode =\n (typeof S2S_ERROR_CODES)[keyof typeof S2S_ERROR_CODES]\n"],"mappings":"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"}
|