@oxyhq/core 12.7.0 → 12.8.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.
@@ -8,6 +8,7 @@ import { jwtDecode } from 'jwt-decode';
8
8
  import { loadNodeCrypto } from '@oxyhq/protocol';
9
9
  import { buildUrl } from '../utils/apiUtils.js';
10
10
  import { logger } from '../logger/index.js';
11
+ import { OXY_SERVICE_ENVIRONMENTS } from '../utils/oxyServiceEnvironment.js';
11
12
  /**
12
13
  * Expected JWT audience for tokens issued by the Oxy auth service.
13
14
  */
@@ -39,6 +40,10 @@ class ServiceTokenClaimError extends Error {
39
40
  this.name = 'ServiceTokenClaimError';
40
41
  }
41
42
  }
43
+ function isOxyServiceEnvironment(value) {
44
+ return (typeof value === 'string' &&
45
+ OXY_SERVICE_ENVIRONMENTS.includes(value));
46
+ }
42
47
  export function OxyServicesUtilityMixin(Base) {
43
48
  return class extends Base {
44
49
  // TypeScript's mixin pattern requires `(...args: any[])` here — the
@@ -335,7 +340,11 @@ export function OxyServicesUtilityMixin(Base) {
335
340
  // Validate required service token fields
336
341
  const appId = decoded.appId;
337
342
  const credentialId = decoded.credentialId;
338
- if (!appId || typeof credentialId !== 'string' || credentialId.length === 0) {
343
+ const environment = decoded.environment;
344
+ if (!appId ||
345
+ typeof credentialId !== 'string' ||
346
+ credentialId.length === 0 ||
347
+ !isOxyServiceEnvironment(environment)) {
339
348
  if (optional) {
340
349
  req.userId = null;
341
350
  req.user = null;
@@ -388,6 +397,7 @@ export function OxyServicesUtilityMixin(Base) {
388
397
  appName: decoded.appName || 'unknown',
389
398
  credentialId,
390
399
  scopes: Array.isArray(decoded.scopes) ? decoded.scopes : [],
400
+ environment,
391
401
  };
392
402
  if (debug) {
393
403
  logger.debug(`[oxy.auth] Service token OK app=${decoded.appName} delegateUser=${oxyUserId || '(none)'}`, {
@@ -1,3 +1,5 @@
1
+ import { OXY_SERVICE_ENVIRONMENTS } from '../utils/oxyServiceEnvironment.js';
2
+ export { OXY_SERVICE_ENVIRONMENTS };
1
3
  function normalizeId(value) {
2
4
  const normalized = value?.trim();
3
5
  return normalized && normalized.length > 0 ? normalized : null;
@@ -14,7 +14,7 @@
14
14
  * app.use(createOxyRateLimit(oxy, { store: redisStore }));
15
15
  * ```
16
16
  */
17
- export { createOptionalOxyAuth, createOxyAuthMiddleware, getOxyUserId, getRequiredOxyUserId, isOxyAuthenticated, requireOxyAuth, } from './auth.js';
17
+ export { createOptionalOxyAuth, createOxyAuthMiddleware, getOxyUserId, getRequiredOxyUserId, isOxyAuthenticated, requireOxyAuth, OXY_SERVICE_ENVIRONMENTS, } from './auth.js';
18
18
  export { createOxyRateLimit } from './rateLimit.js';
19
19
  // SSRF-safe upstream fetch + URL validation (Node-only).
20
20
  export { assertSafePublicUrl, isBlockedIp, safeFetch, SsrfRejection, UpstreamError, ALLOWED_PORTS, ALLOWED_PROTOCOLS, BLOCKED_HOSTNAMES, DEFAULT_USER_AGENT, MAX_REDIRECTS, MAX_URL_LENGTH, UPSTREAM_HEADERS_TIMEOUT_MS, } from './safeFetch.js';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Environment segregation for Oxy service-token JWTs (test/live isolation).
3
+ * Mirrors `ApplicationCredentialEnvironment` on the API's `ApplicationCredential`
4
+ * model (`packages/api/src/models/ApplicationCredential.ts`) as an INDEPENDENT
5
+ * literal union — `@oxyhq/core` has zero dependency on `@oxyhq/api`, so this is
6
+ * kept in sync by hand, not by import.
7
+ *
8
+ * Defined here (not in `server/auth.ts` or `mixins/OxyServices.utility.ts`
9
+ * directly) because BOTH of those files need it and neither may import from
10
+ * the other: `server/` types import `express` (Node-only, a peer dependency
11
+ * `mixins/` deliberately avoids so it stays safe to bundle into RN/browser
12
+ * consumers — see the "Local request/response/socket typing" comment in
13
+ * `OxyServices.utility.ts`). This file has zero imports, so both sides can
14
+ * depend on it without crossing that boundary.
15
+ */
16
+ export const OXY_SERVICE_ENVIRONMENTS = ['development', 'staging', 'production'];