@oxyhq/core 18.0.0 → 19.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 (62) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/i18n/locales/en-US.json +49 -5
  3. package/dist/cjs/i18n/locales/es-ES.json +49 -5
  4. package/dist/cjs/i18n/locales/locales/en-US.json +49 -5
  5. package/dist/cjs/i18n/locales/locales/es-ES.json +49 -5
  6. package/dist/cjs/index.js +17 -6
  7. package/dist/cjs/mixins/OxyServices.accounts.js +69 -31
  8. package/dist/cjs/mixins/OxyServices.followGraph.js +204 -0
  9. package/dist/cjs/mixins/OxyServices.user.js +17 -20
  10. package/dist/cjs/mixins/index.js +4 -0
  11. package/dist/cjs/server/index.js +8 -2
  12. package/dist/cjs/server/userInvalidation.js +6 -28
  13. package/dist/cjs/session/accountProjection.js +45 -9
  14. package/dist/cjs/utils/accountCacheSweep.js +80 -0
  15. package/dist/cjs/utils/identityCacheSweep.js +97 -0
  16. package/dist/esm/.tsbuildinfo +1 -1
  17. package/dist/esm/i18n/locales/en-US.json +49 -5
  18. package/dist/esm/i18n/locales/es-ES.json +49 -5
  19. package/dist/esm/i18n/locales/locales/en-US.json +49 -5
  20. package/dist/esm/i18n/locales/locales/es-ES.json +49 -5
  21. package/dist/esm/index.js +8 -2
  22. package/dist/esm/mixins/OxyServices.accounts.js +64 -30
  23. package/dist/esm/mixins/OxyServices.followGraph.js +201 -0
  24. package/dist/esm/mixins/OxyServices.user.js +17 -20
  25. package/dist/esm/mixins/index.js +4 -0
  26. package/dist/esm/server/index.js +5 -1
  27. package/dist/esm/server/userInvalidation.js +5 -26
  28. package/dist/esm/session/accountProjection.js +44 -9
  29. package/dist/esm/utils/accountCacheSweep.js +75 -0
  30. package/dist/esm/utils/identityCacheSweep.js +92 -0
  31. package/dist/types/.tsbuildinfo +1 -1
  32. package/dist/types/index.d.ts +3 -3
  33. package/dist/types/mixins/OxyServices.accounts.d.ts +91 -34
  34. package/dist/types/mixins/OxyServices.followGraph.d.ts +211 -0
  35. package/dist/types/mixins/OxyServices.user.d.ts +10 -7
  36. package/dist/types/mixins/index.d.ts +2 -1
  37. package/dist/types/models/interfaces.d.ts +11 -3
  38. package/dist/types/server/index.d.ts +4 -2
  39. package/dist/types/server/userInvalidation.d.ts +5 -24
  40. package/dist/types/session/accountProjection.d.ts +38 -4
  41. package/dist/types/utils/accountCacheSweep.d.ts +75 -0
  42. package/dist/types/utils/identityCacheSweep.d.ts +80 -0
  43. package/package.json +2 -2
  44. package/src/i18n/locales/en-US.json +49 -5
  45. package/src/i18n/locales/es-ES.json +49 -5
  46. package/src/index.ts +15 -2
  47. package/src/mixins/OxyServices.accounts.ts +123 -45
  48. package/src/mixins/OxyServices.followGraph.ts +266 -0
  49. package/src/mixins/OxyServices.user.ts +17 -20
  50. package/src/mixins/__tests__/accounts.test.ts +5 -0
  51. package/src/mixins/__tests__/followGraph.test.ts +128 -0
  52. package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +407 -0
  53. package/src/mixins/index.ts +5 -0
  54. package/src/models/interfaces.ts +11 -3
  55. package/src/server/__tests__/userInvalidation.test.ts +3 -20
  56. package/src/server/index.ts +5 -2
  57. package/src/server/userInvalidation.ts +8 -36
  58. package/src/session/__tests__/accountProjection.test.ts +109 -2
  59. package/src/session/accountProjection.ts +47 -9
  60. package/src/utils/__tests__/identityCacheSweep.test.ts +151 -0
  61. package/src/utils/accountCacheSweep.ts +93 -0
  62. package/src/utils/identityCacheSweep.ts +104 -0
@@ -1748,11 +1748,53 @@
1748
1748
  "description": "A programmatic account with service credentials"
1749
1749
  }
1750
1750
  },
1751
- "organizationCategory": {
1751
+ "accountCategory": {
1752
+ "news": "News",
1753
+ "politics": "Politics & policy",
1754
+ "business": "Business",
1755
+ "startup": "Startups & entrepreneurship",
1756
+ "finance": "Finance & investing",
1757
+ "crypto": "Crypto & web3",
1758
+ "marketplace": "Marketplace & classifieds",
1759
+ "retail": "Retail & ecommerce",
1760
+ "real_estate": "Real estate",
1752
1761
  "agency": "Real estate agency",
1762
+ "landlord": "Landlord & property management",
1753
1763
  "cooperative": "Housing cooperative",
1754
- "landlord": "Landlord / property manager",
1755
- "other": "Other organization"
1764
+ "architecture": "Architecture & construction",
1765
+ "technology": "Technology",
1766
+ "software": "Software & development",
1767
+ "ai": "AI & machine learning",
1768
+ "security": "Security & privacy",
1769
+ "automation": "Automation & tools",
1770
+ "science": "Science & research",
1771
+ "education": "Education & training",
1772
+ "books": "Books & writing",
1773
+ "health": "Health & medicine",
1774
+ "fitness": "Fitness & wellbeing",
1775
+ "sports": "Sports",
1776
+ "gaming": "Gaming & esports",
1777
+ "music": "Music",
1778
+ "film": "Film & TV",
1779
+ "podcast": "Podcasts & audio",
1780
+ "art": "Art & design",
1781
+ "photography": "Photography",
1782
+ "comedy": "Comedy",
1783
+ "food": "Food & drink",
1784
+ "travel": "Travel & places",
1785
+ "fashion": "Fashion & beauty",
1786
+ "home_garden": "Home & garden",
1787
+ "diy": "DIY & making",
1788
+ "automotive": "Cars & motoring",
1789
+ "animals": "Animals & pets",
1790
+ "family": "Family & parenting",
1791
+ "nonprofit": "Non-profit & charity",
1792
+ "government": "Government & public sector",
1793
+ "community": "Local community",
1794
+ "activism": "Activism & advocacy",
1795
+ "environment": "Environment & sustainability",
1796
+ "religion": "Religion & spirituality",
1797
+ "other": "Other"
1756
1798
  },
1757
1799
  "create": {
1758
1800
  "title": "Create account",
@@ -1772,8 +1814,9 @@
1772
1814
  "invalidChars": "Only letters, numbers, hyphens, and underscores",
1773
1815
  "checkFailed": "Could not check availability"
1774
1816
  },
1775
- "organizationCategory": {
1776
- "label": "Organization type"
1817
+ "accountCategory": {
1818
+ "label": "Categories",
1819
+ "hint": "Pick up to {{max}}. The first one is your main category."
1777
1820
  },
1778
1821
  "toasts": {
1779
1822
  "success": "Account created",
@@ -1796,6 +1839,7 @@
1796
1839
  "title": "Members",
1797
1840
  "subtitle": "People with access to this account.",
1798
1841
  "empty": "No members yet.",
1842
+ "inherited": "Inherited",
1799
1843
  "actions": {
1800
1844
  "remove": "Remove member",
1801
1845
  "transfer": "Transfer ownership"
@@ -1748,11 +1748,53 @@
1748
1748
  "description": "Una cuenta programática con credenciales de servicio"
1749
1749
  }
1750
1750
  },
1751
- "organizationCategory": {
1751
+ "accountCategory": {
1752
+ "news": "Noticias",
1753
+ "politics": "Política",
1754
+ "business": "Negocios",
1755
+ "startup": "Startups y emprendimiento",
1756
+ "finance": "Finanzas e inversión",
1757
+ "crypto": "Cripto y web3",
1758
+ "marketplace": "Marketplace y anuncios",
1759
+ "retail": "Comercio y ecommerce",
1760
+ "real_estate": "Inmobiliaria",
1752
1761
  "agency": "Agencia inmobiliaria",
1762
+ "landlord": "Casero y gestión de fincas",
1753
1763
  "cooperative": "Cooperativa de vivienda",
1754
- "landlord": "Propietario / administrador de fincas",
1755
- "other": "Otra organización"
1764
+ "architecture": "Arquitectura y construcción",
1765
+ "technology": "Tecnología",
1766
+ "software": "Software y desarrollo",
1767
+ "ai": "IA y aprendizaje automático",
1768
+ "security": "Seguridad y privacidad",
1769
+ "automation": "Automatización y herramientas",
1770
+ "science": "Ciencia e investigación",
1771
+ "education": "Educación y formación",
1772
+ "books": "Libros y escritura",
1773
+ "health": "Salud y medicina",
1774
+ "fitness": "Deporte y bienestar",
1775
+ "sports": "Deportes",
1776
+ "gaming": "Videojuegos y esports",
1777
+ "music": "Música",
1778
+ "film": "Cine y TV",
1779
+ "podcast": "Pódcast y audio",
1780
+ "art": "Arte y diseño",
1781
+ "photography": "Fotografía",
1782
+ "comedy": "Comedia",
1783
+ "food": "Comida y bebida",
1784
+ "travel": "Viajes y lugares",
1785
+ "fashion": "Moda y belleza",
1786
+ "home_garden": "Hogar y jardín",
1787
+ "diy": "Bricolaje y manualidades",
1788
+ "automotive": "Coches y motor",
1789
+ "animals": "Animales y mascotas",
1790
+ "family": "Familia y crianza",
1791
+ "nonprofit": "ONG y benéficas",
1792
+ "government": "Gobierno y sector público",
1793
+ "community": "Comunidad local",
1794
+ "activism": "Activismo y defensa",
1795
+ "environment": "Medio ambiente y sostenibilidad",
1796
+ "religion": "Religión y espiritualidad",
1797
+ "other": "Otra"
1756
1798
  },
1757
1799
  "create": {
1758
1800
  "title": "Crear cuenta",
@@ -1772,8 +1814,9 @@
1772
1814
  "invalidChars": "Solo letras, números, guiones y guiones bajos",
1773
1815
  "checkFailed": "No se pudo comprobar la disponibilidad"
1774
1816
  },
1775
- "organizationCategory": {
1776
- "label": "Tipo de organización"
1817
+ "accountCategory": {
1818
+ "label": "Categorías",
1819
+ "hint": "Elige hasta {{max}}. La primera es tu categoría principal."
1777
1820
  },
1778
1821
  "toasts": {
1779
1822
  "success": "Cuenta creada",
@@ -1796,6 +1839,7 @@
1796
1839
  "title": "Miembros",
1797
1840
  "subtitle": "Personas con acceso a esta cuenta.",
1798
1841
  "empty": "Aún no hay miembros.",
1842
+ "inherited": "Heredado",
1799
1843
  "actions": {
1800
1844
  "remove": "Eliminar miembro",
1801
1845
  "transfer": "Transferir propiedad"
@@ -1748,11 +1748,53 @@
1748
1748
  "description": "A programmatic account with service credentials"
1749
1749
  }
1750
1750
  },
1751
- "organizationCategory": {
1751
+ "accountCategory": {
1752
+ "news": "News",
1753
+ "politics": "Politics & policy",
1754
+ "business": "Business",
1755
+ "startup": "Startups & entrepreneurship",
1756
+ "finance": "Finance & investing",
1757
+ "crypto": "Crypto & web3",
1758
+ "marketplace": "Marketplace & classifieds",
1759
+ "retail": "Retail & ecommerce",
1760
+ "real_estate": "Real estate",
1752
1761
  "agency": "Real estate agency",
1762
+ "landlord": "Landlord & property management",
1753
1763
  "cooperative": "Housing cooperative",
1754
- "landlord": "Landlord / property manager",
1755
- "other": "Other organization"
1764
+ "architecture": "Architecture & construction",
1765
+ "technology": "Technology",
1766
+ "software": "Software & development",
1767
+ "ai": "AI & machine learning",
1768
+ "security": "Security & privacy",
1769
+ "automation": "Automation & tools",
1770
+ "science": "Science & research",
1771
+ "education": "Education & training",
1772
+ "books": "Books & writing",
1773
+ "health": "Health & medicine",
1774
+ "fitness": "Fitness & wellbeing",
1775
+ "sports": "Sports",
1776
+ "gaming": "Gaming & esports",
1777
+ "music": "Music",
1778
+ "film": "Film & TV",
1779
+ "podcast": "Podcasts & audio",
1780
+ "art": "Art & design",
1781
+ "photography": "Photography",
1782
+ "comedy": "Comedy",
1783
+ "food": "Food & drink",
1784
+ "travel": "Travel & places",
1785
+ "fashion": "Fashion & beauty",
1786
+ "home_garden": "Home & garden",
1787
+ "diy": "DIY & making",
1788
+ "automotive": "Cars & motoring",
1789
+ "animals": "Animals & pets",
1790
+ "family": "Family & parenting",
1791
+ "nonprofit": "Non-profit & charity",
1792
+ "government": "Government & public sector",
1793
+ "community": "Local community",
1794
+ "activism": "Activism & advocacy",
1795
+ "environment": "Environment & sustainability",
1796
+ "religion": "Religion & spirituality",
1797
+ "other": "Other"
1756
1798
  },
1757
1799
  "create": {
1758
1800
  "title": "Create account",
@@ -1772,8 +1814,9 @@
1772
1814
  "invalidChars": "Only letters, numbers, hyphens, and underscores",
1773
1815
  "checkFailed": "Could not check availability"
1774
1816
  },
1775
- "organizationCategory": {
1776
- "label": "Organization type"
1817
+ "accountCategory": {
1818
+ "label": "Categories",
1819
+ "hint": "Pick up to {{max}}. The first one is your main category."
1777
1820
  },
1778
1821
  "toasts": {
1779
1822
  "success": "Account created",
@@ -1796,6 +1839,7 @@
1796
1839
  "title": "Members",
1797
1840
  "subtitle": "People with access to this account.",
1798
1841
  "empty": "No members yet.",
1842
+ "inherited": "Inherited",
1799
1843
  "actions": {
1800
1844
  "remove": "Remove member",
1801
1845
  "transfer": "Transfer ownership"
@@ -1748,11 +1748,53 @@
1748
1748
  "description": "Una cuenta programática con credenciales de servicio"
1749
1749
  }
1750
1750
  },
1751
- "organizationCategory": {
1751
+ "accountCategory": {
1752
+ "news": "Noticias",
1753
+ "politics": "Política",
1754
+ "business": "Negocios",
1755
+ "startup": "Startups y emprendimiento",
1756
+ "finance": "Finanzas e inversión",
1757
+ "crypto": "Cripto y web3",
1758
+ "marketplace": "Marketplace y anuncios",
1759
+ "retail": "Comercio y ecommerce",
1760
+ "real_estate": "Inmobiliaria",
1752
1761
  "agency": "Agencia inmobiliaria",
1762
+ "landlord": "Casero y gestión de fincas",
1753
1763
  "cooperative": "Cooperativa de vivienda",
1754
- "landlord": "Propietario / administrador de fincas",
1755
- "other": "Otra organización"
1764
+ "architecture": "Arquitectura y construcción",
1765
+ "technology": "Tecnología",
1766
+ "software": "Software y desarrollo",
1767
+ "ai": "IA y aprendizaje automático",
1768
+ "security": "Seguridad y privacidad",
1769
+ "automation": "Automatización y herramientas",
1770
+ "science": "Ciencia e investigación",
1771
+ "education": "Educación y formación",
1772
+ "books": "Libros y escritura",
1773
+ "health": "Salud y medicina",
1774
+ "fitness": "Deporte y bienestar",
1775
+ "sports": "Deportes",
1776
+ "gaming": "Videojuegos y esports",
1777
+ "music": "Música",
1778
+ "film": "Cine y TV",
1779
+ "podcast": "Pódcast y audio",
1780
+ "art": "Arte y diseño",
1781
+ "photography": "Fotografía",
1782
+ "comedy": "Comedia",
1783
+ "food": "Comida y bebida",
1784
+ "travel": "Viajes y lugares",
1785
+ "fashion": "Moda y belleza",
1786
+ "home_garden": "Hogar y jardín",
1787
+ "diy": "Bricolaje y manualidades",
1788
+ "automotive": "Coches y motor",
1789
+ "animals": "Animales y mascotas",
1790
+ "family": "Familia y crianza",
1791
+ "nonprofit": "ONG y benéficas",
1792
+ "government": "Gobierno y sector público",
1793
+ "community": "Comunidad local",
1794
+ "activism": "Activismo y defensa",
1795
+ "environment": "Medio ambiente y sostenibilidad",
1796
+ "religion": "Religión y espiritualidad",
1797
+ "other": "Otra"
1756
1798
  },
1757
1799
  "create": {
1758
1800
  "title": "Crear cuenta",
@@ -1772,8 +1814,9 @@
1772
1814
  "invalidChars": "Solo letras, números, guiones y guiones bajos",
1773
1815
  "checkFailed": "No se pudo comprobar la disponibilidad"
1774
1816
  },
1775
- "organizationCategory": {
1776
- "label": "Tipo de organización"
1817
+ "accountCategory": {
1818
+ "label": "Categorías",
1819
+ "hint": "Elige hasta {{max}}. La primera es tu categoría principal."
1777
1820
  },
1778
1821
  "toasts": {
1779
1822
  "success": "Cuenta creada",
@@ -1796,6 +1839,7 @@
1796
1839
  "title": "Miembros",
1797
1840
  "subtitle": "Personas con acceso a esta cuenta.",
1798
1841
  "empty": "Aún no hay miembros.",
1842
+ "inherited": "Heredado",
1799
1843
  "actions": {
1800
1844
  "remove": "Eliminar miembro",
1801
1845
  "transfer": "Transferir propiedad"
package/dist/cjs/index.js CHANGED
@@ -18,11 +18,11 @@
18
18
  * If a symbol does not appear here, it is NOT part of the public API.
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.ORGANIZATION_CATEGORIES = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.commonsDeliveryPlatform = exports.pushTargetsFromDelivery = exports.selectCommonsDelivery = exports.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.ServiceAssetMetadataError = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.AssetUrlResolutionError = exports.OxyServices = void 0;
22
- exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = exports.isNative = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = void 0;
23
- exports.buildAccountsArray = exports.updateAvatarVisibility = exports.isDev = exports.consoleSink = exports.resetLoggerConfig = exports.getLoggerConfig = exports.configureLogger = exports.createLogger = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE = exports.DISPLAY_NAME_ORPHANED_MARK_SOURCE = exports.DISPLAY_NAME_DISALLOWED_SOURCE = exports.DISPLAY_NAME_ALLOWED_SCRIPTS = exports.isValidDisplayName = exports.isValidPassword = exports.isValidUsername = exports.isValidEmail = exports.DISPLAY_NAME_INVALID_MESSAGE = exports.MAX_DISPLAY_NAME_LENGTH = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.buildQueryParams = exports.translate = exports.withRetry = void 0;
24
- exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = exports.createWebIdentityPinStore = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isLoopbackOrigin = exports.consumeOAuthReturnPath = exports.persistOAuthReturnPath = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.canonicalizeOAuthRedirectUri = exports.normalizeOAuthRedirectUri = exports.OXY_OAUTH_RETURN_PATH_STORAGE_KEY = exports.OXY_OAUTH_REDIRECT_URI_STORAGE_KEY = exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.isOxyRpOrigin = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = void 0;
25
- exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AccountNotOnDeviceError = exports.establishIdentitySession = void 0;
21
+ exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.ACCOUNT_CATEGORY_IDS = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.commonsDeliveryPlatform = exports.pushTargetsFromDelivery = exports.selectCommonsDelivery = exports.parseCommonsApprovalExpiresAt = exports.getCommonsApprovalBlockingReason = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.ServiceAssetMetadataError = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.AssetUrlResolutionError = exports.OxyServices = void 0;
22
+ exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = exports.isNative = exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = void 0;
23
+ exports.resetLoggerConfig = exports.getLoggerConfig = exports.configureLogger = exports.createLogger = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.DISPLAY_NAME_UNFLANKED_SEPARATOR_SOURCE = exports.DISPLAY_NAME_ORPHANED_MARK_SOURCE = exports.DISPLAY_NAME_DISALLOWED_SOURCE = exports.DISPLAY_NAME_ALLOWED_SCRIPTS = exports.isValidDisplayName = exports.isValidPassword = exports.isValidUsername = exports.isValidEmail = exports.DISPLAY_NAME_INVALID_MESSAGE = exports.MAX_DISPLAY_NAME_LENGTH = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.buildQueryParams = exports.translate = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = void 0;
24
+ exports.createWebIdentityPinStore = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.isSwitchTargetAccount = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isLoopbackOrigin = exports.consumeOAuthReturnPath = exports.persistOAuthReturnPath = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.canonicalizeOAuthRedirectUri = exports.normalizeOAuthRedirectUri = exports.OXY_OAUTH_RETURN_PATH_STORAGE_KEY = exports.OXY_OAUTH_REDIRECT_URI_STORAGE_KEY = exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.isOxyRpOrigin = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.isDev = exports.consoleSink = void 0;
25
+ exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AccountNotOnDeviceError = exports.establishIdentitySession = exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = void 0;
26
26
  // Ensure crypto polyfills are loaded before anything else
27
27
  require("./crypto/polyfill");
28
28
  // ---------------------------------------------------------------------------
@@ -66,7 +66,11 @@ Object.defineProperty(exports, "getNormalizedUserHandle", { enumerable: true, ge
66
66
  var profileLinks_1 = require("./utils/profileLinks");
67
67
  Object.defineProperty(exports, "normalizeProfileLinks", { enumerable: true, get: function () { return profileLinks_1.normalizeProfileLinks; } });
68
68
  var OxyServices_accounts_1 = require("./mixins/OxyServices.accounts");
69
- Object.defineProperty(exports, "ORGANIZATION_CATEGORIES", { enumerable: true, get: function () { return OxyServices_accounts_1.ORGANIZATION_CATEGORIES; } });
69
+ Object.defineProperty(exports, "ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return OxyServices_accounts_1.ACCOUNT_CATEGORY_IDS; } });
70
+ Object.defineProperty(exports, "MAX_ACCOUNT_CATEGORIES", { enumerable: true, get: function () { return OxyServices_accounts_1.MAX_ACCOUNT_CATEGORIES; } });
71
+ Object.defineProperty(exports, "SELECTABLE_ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return OxyServices_accounts_1.SELECTABLE_ACCOUNT_CATEGORY_IDS; } });
72
+ Object.defineProperty(exports, "isSelectableAccountCategoryId", { enumerable: true, get: function () { return OxyServices_accounts_1.isSelectableAccountCategoryId; } });
73
+ Object.defineProperty(exports, "kindAcceptsAccountCategories", { enumerable: true, get: function () { return OxyServices_accounts_1.kindAcceptsAccountCategories; } });
70
74
  // ---------------------------------------------------------------------------
71
75
  // Reputation (Oxy Trust: ledger, balances, disputes, rules, influence).
72
76
  // The whole type family — the closed value sets, the two balance views and the
@@ -366,7 +370,14 @@ Object.defineProperty(exports, "accountIdsOf", { enumerable: true, get: function
366
370
  // chooser: device sign-ins ∪ account graph, deduped by accountId). Pure +
367
371
  // I/O-free — the caller hydrates profiles via `getUsersByIds`. Shared by
368
372
  // `@oxyhq/services` and auth.oxy.so so the list can't diverge.
373
+ // `isSwitchTargetAccount` is the switcher's own question ("can I become this
374
+ // account?"), exported so a surface that renders `AccountNode`s rather than the
375
+ // projection — the Console's workspace switcher, the accounts app's
376
+ // managed-accounts rows — asks the SAME question instead of testing a kind
377
+ // literal. It is NOT `isActAsEligibleKind`: that one is false for `personal`
378
+ // too, so gating a switcher on it alone empties the list.
369
379
  var accountProjection_1 = require("./session/accountProjection");
380
+ Object.defineProperty(exports, "isSwitchTargetAccount", { enumerable: true, get: function () { return accountProjection_1.isSwitchTargetAccount; } });
370
381
  Object.defineProperty(exports, "projectSwitchableAccounts", { enumerable: true, get: function () { return accountProjection_1.projectSwitchableAccounts; } });
371
382
  Object.defineProperty(exports, "switchableAccountIds", { enumerable: true, get: function () { return accountProjection_1.switchableAccountIds; } });
372
383
  // Headless controller for the unified account dialog. Framework-agnostic
@@ -1,13 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isActAsEligibleKind = exports.ORGANIZATION_CATEGORIES = exports.ACCOUNT_KINDS = void 0;
3
+ exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.isActAsEligibleKind = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.ACCOUNT_KINDS = exports.ACCOUNT_CATEGORY_IDS = void 0;
4
4
  exports.OxyServicesAccountsMixin = OxyServicesAccountsMixin;
5
5
  const userIdentity_1 = require("../utils/userIdentity");
6
+ const identityCacheSweep_1 = require("../utils/identityCacheSweep");
7
+ const accountCacheSweep_1 = require("../utils/accountCacheSweep");
6
8
  const mixinHelpers_1 = require("./mixinHelpers");
7
9
  var contracts_1 = require("@oxyhq/contracts");
10
+ Object.defineProperty(exports, "ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return contracts_1.ACCOUNT_CATEGORY_IDS; } });
8
11
  Object.defineProperty(exports, "ACCOUNT_KINDS", { enumerable: true, get: function () { return contracts_1.ACCOUNT_KINDS; } });
9
- Object.defineProperty(exports, "ORGANIZATION_CATEGORIES", { enumerable: true, get: function () { return contracts_1.ORGANIZATION_CATEGORIES; } });
12
+ Object.defineProperty(exports, "MAX_ACCOUNT_CATEGORIES", { enumerable: true, get: function () { return contracts_1.MAX_ACCOUNT_CATEGORIES; } });
13
+ Object.defineProperty(exports, "SELECTABLE_ACCOUNT_CATEGORY_IDS", { enumerable: true, get: function () { return contracts_1.SELECTABLE_ACCOUNT_CATEGORY_IDS; } });
10
14
  Object.defineProperty(exports, "isActAsEligibleKind", { enumerable: true, get: function () { return contracts_1.isActAsEligibleKind; } });
15
+ Object.defineProperty(exports, "isSelectableAccountCategoryId", { enumerable: true, get: function () { return contracts_1.isSelectableAccountCategoryId; } });
16
+ Object.defineProperty(exports, "kindAcceptsAccountCategories", { enumerable: true, get: function () { return contracts_1.kindAcceptsAccountCategories; } });
11
17
  function OxyServicesAccountsMixin(Base) {
12
18
  return class extends Base {
13
19
  constructor(...args) {
@@ -119,7 +125,7 @@ function OxyServicesAccountsMixin(Base) {
119
125
  const res = await this.makeRequest('POST', '/accounts', data, { cache: false });
120
126
  // A new account changes the accessible forest — bust every cached list
121
127
  // (flat + tree) so it appears on the next `listAccounts()` read.
122
- this._invalidateAccountLists();
128
+ (0, accountCacheSweep_1.evictOxyAccountForestCache)(this);
123
129
  return res.account;
124
130
  }
125
131
  catch (error) {
@@ -165,6 +171,18 @@ function OxyServicesAccountsMixin(Base) {
165
171
  /**
166
172
  * Update an account's mutable profile fields. Tree placement changes
167
173
  * (reparenting) go through the dedicated move endpoint, not here.
174
+ *
175
+ * An account IS a user, so this write changes identity — and a profile
176
+ * screen never reads `/accounts/<id>`. It reads `GET /users/<id>` and
177
+ * `GET /profiles/username/<handle>`, both cached for 5 minutes in the
178
+ * CALLER'S OWN process, so busting only the account-graph keys left every
179
+ * profile surface serving the pre-edit avatar and name for the full TTL
180
+ * with a perfectly healthy server (the cross-service `oxy:user:invalidate`
181
+ * signal does not help: it evicts BACKEND caches, and cannot reach a cache
182
+ * living in a browser tab). {@link evictOxyIdentityCache} owns that key
183
+ * list — see its docs for why the handle-keyed entries are prefix-swept
184
+ * (a RENAME leaves the old handle's entry unreachable by any targeted key).
185
+ *
168
186
  * @param accountId - The account's Mongo `_id`.
169
187
  * @param data - Subset of updatable profile fields.
170
188
  */
@@ -173,8 +191,15 @@ function OxyServicesAccountsMixin(Base) {
173
191
  const res = await this.makeRequest('PATCH', `/accounts/${encodeURIComponent(accountId)}`, data, { cache: false });
174
192
  // Bust the cached detail and every list (which embeds account profile
175
193
  // data) so neither serves the pre-update snapshot.
176
- this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}`);
177
- this._invalidateAccountLists();
194
+ (0, accountCacheSweep_1.evictOxyAccountForestCache)(this, accountId);
195
+ // The parent's children list embeds this account's profile and is keyed
196
+ // by the PARENT id, so it is reachable only from the response node.
197
+ const parentAccountId = res.account?.parentAccountId;
198
+ if (parentAccountId) {
199
+ this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(parentAccountId)}/children`);
200
+ }
201
+ // Every identity read of this account, whichever key it lands under.
202
+ (0, identityCacheSweep_1.evictOxyIdentityCache)(this, accountId);
178
203
  return res.account;
179
204
  }
180
205
  catch (error) {
@@ -191,10 +216,9 @@ function OxyServicesAccountsMixin(Base) {
191
216
  try {
192
217
  const result = await this.makeRequest('DELETE', `/accounts/${encodeURIComponent(accountId)}`, undefined, { cache: false });
193
218
  // Bust every cached representation of the archived account.
194
- this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}`);
195
219
  this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}/members`);
196
220
  this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}/credentials`);
197
- this._invalidateAccountLists();
221
+ (0, accountCacheSweep_1.evictOxyAccountForestCache)(this, accountId);
198
222
  return result;
199
223
  }
200
224
  catch (error) {
@@ -218,7 +242,27 @@ function OxyServicesAccountsMixin(Base) {
218
242
  // Account members
219
243
  // =========================================================================
220
244
  /**
221
- * List members of an account (direct membership rows on the account).
245
+ * List the members of an account: the membership rows ON it, plus the rows
246
+ * on its ancestors that cascade into it. Each entry carries `source`
247
+ * (`direct` | `inherited`) saying which it is.
248
+ *
249
+ * Inherited entries are members in every sense the server enforces — an
250
+ * ancestor row with `inherit: true` resolves through
251
+ * `resolveEffectiveAccess` and confers every account permission on the
252
+ * descendant, `account:act_as` included — so a roster that omitted them
253
+ * answered `[]` for accounts several people could act on.
254
+ *
255
+ * Two things follow for a caller. An entry's `accountId` is the account its
256
+ * ROW lives on, so an inherited entry names an ancestor rather than the
257
+ * account you asked about; and the member-mutation endpoints only accept
258
+ * rows on the account in the path, so gate any edit/remove/transfer
259
+ * affordance on `source === 'direct'`.
260
+ *
261
+ * Asking what the CALLER holds over an account is a different question, and
262
+ * scanning this list for yourself is the wrong way to answer it — use
263
+ * {@link OxyServicesAccountsMixin.getAccount}, whose `callerMembership` is
264
+ * the server's own resolution.
265
+ *
222
266
  * @param accountId - The account's Mongo `_id`.
223
267
  */
224
268
  async listAccountMembers(accountId) {
@@ -289,7 +333,7 @@ function OxyServicesAccountsMixin(Base) {
289
333
  // Ownership change alters roles in the member list AND the detail, and
290
334
  // can change which accounts the caller "owns" in the list view.
291
335
  this._invalidateAccountMembership(accountId);
292
- this._invalidateAccountLists();
336
+ (0, accountCacheSweep_1.evictOxyAccountForestCache)(this);
293
337
  return result;
294
338
  }
295
339
  catch (error) {
@@ -533,35 +577,29 @@ function OxyServicesAccountsMixin(Base) {
533
577
  // Cache-invalidation helpers
534
578
  // =========================================================================
535
579
  /**
536
- * Bust every cached account list. `listAccounts({tree?})` keys the flat list
537
- * as `GET:/accounts` and the tree variant as `GET:/accounts?tree=true` (the
538
- * query string is part of the URL path). A change to the accessible forest
539
- * (create/archive/ownership transfer) invalidates both, so we clear the
540
- * unscoped entry plus every `?`-query variant via a prefix sweep. The prefix
541
- * `GET:/accounts?` matches only the query-string list variants, never the
542
- * `GET:/accounts/<id>…` detail/sub-resource keys.
580
+ * Bust the cached member list and detail for an account after a membership
581
+ * mutation. The member list (`listAccountMembers`) and the detail
582
+ * (`getAccount`, which can embed the caller's membership) both go stale when
583
+ * the member set or a member's role changes.
543
584
  *
544
585
  * Internal helper (leading underscore); not part of the supported public
545
586
  * surface. Public rather than `private` because mixins compose into an
546
587
  * exported anonymous class, where TypeScript cannot represent a private
547
588
  * member in the emitted declaration file (TS4094).
548
- */
549
- _invalidateAccountLists() {
550
- this.clearCacheEntry('GET:/accounts');
551
- this.clearCacheByPrefix('GET:/accounts?');
552
- }
553
- /**
554
- * Bust the cached member list and detail for an account after a membership
555
- * mutation. The member list (`listAccountMembers`) and the detail
556
- * (`getAccount`, which can embed the caller's membership) both go stale when
557
- * the member set or a member's role changes.
558
589
  *
559
- * Internal helper (leading underscore); see `_invalidateAccountLists` for why
560
- * this is public rather than `private`.
590
+ * The forest keys themselves are NOT owned here — see
591
+ * `utils/accountCacheSweep`, which the user mixin has to reach as well.
561
592
  */
562
593
  _invalidateAccountMembership(accountId) {
563
594
  this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}/members`);
564
- this.clearCacheEntry(`GET:/accounts/${encodeURIComponent(accountId)}`);
595
+ this.clearCacheEntry((0, accountCacheSweep_1.oxyAccountDetailCacheKey)(accountId));
596
+ // Inherited rows on descendant rosters are derived from this account's
597
+ // membership table — a targeted clear of only the mutated account's keys
598
+ // leaves every other cached `…/members` list serving stale inherited
599
+ // roles until MEDIUM TTL. Sweep all per-account sub-resource keys instead;
600
+ // the forest list keys (`GET:/accounts`, `GET:/accounts?…`) are excluded
601
+ // by the trailing slash on the prefix (see accountCacheSweep).
602
+ this.clearCacheByPrefix(accountCacheSweep_1.OXY_ACCOUNT_PER_ACCOUNT_CACHE_PREFIX);
565
603
  }
566
604
  /**
567
605
  * Bust every cached application list. `listAccountApps(accountId)` keys each
@@ -572,8 +610,8 @@ function OxyServicesAccountsMixin(Base) {
572
610
  * query-string list variants, never the `GET:/applications/<id>…`
573
611
  * detail/sub-resource keys.
574
612
  *
575
- * Internal helper (leading underscore); see `_invalidateAccountLists` for why
576
- * this is public rather than `private`.
613
+ * Internal helper (leading underscore); see `_invalidateAccountMembership`
614
+ * for why this is public rather than `private`.
577
615
  */
578
616
  _invalidateAppLists() {
579
617
  this.clearCacheEntry('GET:/applications');